@flowcore/cli 2.0.1 → 2.1.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 +9 -0
- package/README.md +23 -17
- package/dist/commands/stream.d.ts +1 -1
- package/dist/commands/stream.js +10 -7
- package/dist/commands/whoami.d.ts +1 -1
- package/dist/commands/whoami.js +1 -2
- package/oclif.manifest.json +1 -147
- package/package.json +4 -5
- package/dist/base-command.d.ts +0 -17
- package/dist/base-command.js +0 -32
- package/dist/commands/config/set.d.ts +0 -13
- package/dist/commands/config/set.js +0 -45
- package/dist/commands/config/show.d.ts +0 -6
- package/dist/commands/config/show.js +0 -11
- package/dist/commands/login.d.ts +0 -19
- package/dist/commands/login.js +0 -146
- package/dist/utils/config.util.d.ts +0 -31
- package/dist/utils/config.util.js +0 -108
- package/dist/utils/object-path.util.d.ts +0 -1
- package/dist/utils/object-path.util.js +0 -17
- package/dist/utils/validate-login.util.d.ts +0 -24
- package/dist/utils/validate-login.util.js +0 -115
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,15 @@
|
|
|
10
10
|
|
|
11
11
|
* added description to start that includes week ([58687a7](https://github.com/flowcore-io/flowcore-cli/commit/58687a7bbb66aaa5d6da26af88e555cbb1e72467))
|
|
12
12
|
|
|
13
|
+
## [2.1.0](https://github.com/flowcore-io/flowcore-cli/compare/v2.0.1...v2.1.0) (2024-02-15)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Features
|
|
17
|
+
|
|
18
|
+
* added config as a separate plugin ([4098793](https://github.com/flowcore-io/flowcore-cli/commit/40987938a60470b1c8082e813cb96baba089c5b6))
|
|
19
|
+
* removed login from cli, moved to config plugin ([3789e06](https://github.com/flowcore-io/flowcore-cli/commit/3789e06b4938bc1b7429d3133ea8fe1054f7418f))
|
|
20
|
+
* switch login profile automatically when providing a stream url ([8172d2d](https://github.com/flowcore-io/flowcore-cli/commit/8172d2dd765dc44f714a82c4a53f7c6c258000b9))
|
|
21
|
+
|
|
13
22
|
## [2.0.1](https://github.com/flowcore-io/flowcore-cli/compare/v2.0.0...v2.0.1) (2024-01-15)
|
|
14
23
|
|
|
15
24
|
|
package/README.md
CHANGED
|
@@ -3,6 +3,7 @@ Flowcore CLI
|
|
|
3
3
|
|
|
4
4
|
Flowcore CLI is a command line interface for interacting with the Flowcore Platform.
|
|
5
5
|
|
|
6
|
+
[](https://npmjs.org/package/@flowcore/cli-plugin-config)
|
|
6
7
|
[](https://oclif.io)
|
|
7
8
|
[](https://github.com/flowcore-io/flowcore-cli/actions/workflows/build.yml)
|
|
8
9
|
|
|
@@ -17,7 +18,7 @@ $ npm install -g @flowcore/cli
|
|
|
17
18
|
$ flowcore COMMAND
|
|
18
19
|
running command...
|
|
19
20
|
$ flowcore (--version)
|
|
20
|
-
@flowcore/cli/2.0
|
|
21
|
+
@flowcore/cli/2.1.0 linux-x64 node-v20.11.0
|
|
21
22
|
$ flowcore --help [COMMAND]
|
|
22
23
|
USAGE
|
|
23
24
|
$ flowcore COMMAND
|
|
@@ -74,7 +75,7 @@ EXAMPLES
|
|
|
74
75
|
$ flowcore autocomplete --refresh-cache
|
|
75
76
|
```
|
|
76
77
|
|
|
77
|
-
_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v3.0.
|
|
78
|
+
_See code: [@oclif/plugin-autocomplete](https://github.com/oclif/plugin-autocomplete/blob/v3.0.8/src/commands/autocomplete/index.ts)_
|
|
78
79
|
|
|
79
80
|
## `flowcore config set`
|
|
80
81
|
|
|
@@ -82,9 +83,10 @@ Configure the cli
|
|
|
82
83
|
|
|
83
84
|
```
|
|
84
85
|
USAGE
|
|
85
|
-
$ flowcore config set [--profile <value>] [-c <value>] [-n <value>] [-l <value>] [-p] [-u <value>]
|
|
86
|
+
$ flowcore config set [--profile <value>] [-b <value>] [-c <value>] [-n <value>] [-l <value>] [-p] [-u <value>]
|
|
86
87
|
|
|
87
88
|
FLAGS
|
|
89
|
+
-b, --baseUrl=<value> base url to the flowcore platform
|
|
88
90
|
-c, --clientId=<value> client id to use for the login
|
|
89
91
|
-l, --loginUrl=<value> url to discover the openid configuration
|
|
90
92
|
-n, --clientSecret=<value> name to print
|
|
@@ -103,7 +105,7 @@ EXAMPLES
|
|
|
103
105
|
$ flowcore config set -l https://auth.flowcore.io/realms/flowcore/.well-known/openid-configuration -c my-client-id -p
|
|
104
106
|
```
|
|
105
107
|
|
|
106
|
-
_See code: [
|
|
108
|
+
_See code: [@flowcore/cli-plugin-config](https://github.com/flowcore/flowcore-cli-plugin-config/blob/v1.0.4/src/commands/config/set.ts)_
|
|
107
109
|
|
|
108
110
|
## `flowcore config show`
|
|
109
111
|
|
|
@@ -123,7 +125,7 @@ EXAMPLES
|
|
|
123
125
|
$ flowcore config show
|
|
124
126
|
```
|
|
125
127
|
|
|
126
|
-
_See code: [
|
|
128
|
+
_See code: [@flowcore/cli-plugin-config](https://github.com/flowcore/flowcore-cli-plugin-config/blob/v1.0.4/src/commands/config/show.ts)_
|
|
127
129
|
|
|
128
130
|
## `flowcore help [COMMANDS]`
|
|
129
131
|
|
|
@@ -166,7 +168,7 @@ EXAMPLES
|
|
|
166
168
|
$ flowcore login --port 8080
|
|
167
169
|
```
|
|
168
170
|
|
|
169
|
-
_See code: [
|
|
171
|
+
_See code: [@flowcore/cli-plugin-config](https://github.com/flowcore/flowcore-cli-plugin-config/blob/v1.0.4/src/commands/login.ts)_
|
|
170
172
|
|
|
171
173
|
## `flowcore plugins`
|
|
172
174
|
|
|
@@ -189,7 +191,7 @@ EXAMPLES
|
|
|
189
191
|
$ flowcore plugins
|
|
190
192
|
```
|
|
191
193
|
|
|
192
|
-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.
|
|
194
|
+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.2/src/commands/plugins/index.ts)_
|
|
193
195
|
|
|
194
196
|
## `flowcore plugins:install PLUGIN...`
|
|
195
197
|
|
|
@@ -258,7 +260,7 @@ EXAMPLES
|
|
|
258
260
|
$ flowcore plugins inspect myplugin
|
|
259
261
|
```
|
|
260
262
|
|
|
261
|
-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.
|
|
263
|
+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.2/src/commands/plugins/inspect.ts)_
|
|
262
264
|
|
|
263
265
|
## `flowcore plugins:install PLUGIN...`
|
|
264
266
|
|
|
@@ -302,7 +304,7 @@ EXAMPLES
|
|
|
302
304
|
$ flowcore plugins install someuser/someplugin
|
|
303
305
|
```
|
|
304
306
|
|
|
305
|
-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.
|
|
307
|
+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.2/src/commands/plugins/install.ts)_
|
|
306
308
|
|
|
307
309
|
## `flowcore plugins:link PLUGIN`
|
|
308
310
|
|
|
@@ -332,7 +334,7 @@ EXAMPLES
|
|
|
332
334
|
$ flowcore plugins link myplugin
|
|
333
335
|
```
|
|
334
336
|
|
|
335
|
-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.
|
|
337
|
+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.2/src/commands/plugins/link.ts)_
|
|
336
338
|
|
|
337
339
|
## `flowcore plugins:uninstall PLUGIN...`
|
|
338
340
|
|
|
@@ -366,10 +368,14 @@ Remove all user-installed and linked plugins.
|
|
|
366
368
|
|
|
367
369
|
```
|
|
368
370
|
USAGE
|
|
369
|
-
$ flowcore plugins reset
|
|
371
|
+
$ flowcore plugins reset [--hard] [--reinstall]
|
|
372
|
+
|
|
373
|
+
FLAGS
|
|
374
|
+
--hard Delete node_modules and package manager related files in addition to uninstalling plugins.
|
|
375
|
+
--reinstall Reinstall all plugins after uninstalling.
|
|
370
376
|
```
|
|
371
377
|
|
|
372
|
-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.
|
|
378
|
+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.2/src/commands/plugins/reset.ts)_
|
|
373
379
|
|
|
374
380
|
## `flowcore plugins:uninstall PLUGIN...`
|
|
375
381
|
|
|
@@ -397,7 +403,7 @@ EXAMPLES
|
|
|
397
403
|
$ flowcore plugins uninstall myplugin
|
|
398
404
|
```
|
|
399
405
|
|
|
400
|
-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.
|
|
406
|
+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.2/src/commands/plugins/uninstall.ts)_
|
|
401
407
|
|
|
402
408
|
## `flowcore plugins:uninstall PLUGIN...`
|
|
403
409
|
|
|
@@ -441,7 +447,7 @@ DESCRIPTION
|
|
|
441
447
|
Update installed plugins.
|
|
442
448
|
```
|
|
443
449
|
|
|
444
|
-
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.
|
|
450
|
+
_See code: [@oclif/plugin-plugins](https://github.com/oclif/plugin-plugins/blob/v4.2.2/src/commands/plugins/update.ts)_
|
|
445
451
|
|
|
446
452
|
## `flowcore stream STREAM`
|
|
447
453
|
|
|
@@ -479,7 +485,7 @@ EXAMPLES
|
|
|
479
485
|
$ flowcore stream https://flowcore.io/<org>/<data core>/<flow type>/[<event type1>,<event type2>,<event type3>].stream -o log -s 3m
|
|
480
486
|
```
|
|
481
487
|
|
|
482
|
-
_See code: [src/commands/stream.ts](https://github.com/flowcore-io/flowcore-cli/blob/v2.0
|
|
488
|
+
_See code: [src/commands/stream.ts](https://github.com/flowcore-io/flowcore-cli/blob/v2.1.0/src/commands/stream.ts)_
|
|
483
489
|
|
|
484
490
|
## `flowcore version`
|
|
485
491
|
|
|
@@ -499,7 +505,7 @@ FLAG DESCRIPTIONS
|
|
|
499
505
|
Additionally shows the architecture, node version, operating system, and versions of plugins that the CLI is using.
|
|
500
506
|
```
|
|
501
507
|
|
|
502
|
-
_See code: [@oclif/plugin-version](https://github.com/oclif/plugin-version/blob/v2.0.
|
|
508
|
+
_See code: [@oclif/plugin-version](https://github.com/oclif/plugin-version/blob/v2.0.12/src/commands/version.ts)_
|
|
503
509
|
|
|
504
510
|
## `flowcore whoami`
|
|
505
511
|
|
|
@@ -516,5 +522,5 @@ DESCRIPTION
|
|
|
516
522
|
Check what user you are logged in as
|
|
517
523
|
```
|
|
518
524
|
|
|
519
|
-
_See code: [src/commands/whoami.ts](https://github.com/flowcore-io/flowcore-cli/blob/v2.0
|
|
525
|
+
_See code: [src/commands/whoami.ts](https://github.com/flowcore-io/flowcore-cli/blob/v2.1.0/src/commands/whoami.ts)_
|
|
520
526
|
<!-- commandsstop -->
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { BaseCommand } from "
|
|
1
|
+
import { BaseCommand } from "@flowcore/cli-plugin-config";
|
|
2
2
|
export default class Stream extends BaseCommand<typeof Stream> {
|
|
3
3
|
static args: {
|
|
4
4
|
STREAM: import("@oclif/core/lib/interfaces/parser.js").Arg<string, Record<string, unknown>>;
|
package/dist/commands/stream.js
CHANGED
|
@@ -1,18 +1,17 @@
|
|
|
1
1
|
import { Queue } from "@datastructures-js/queue";
|
|
2
|
+
import { BaseCommand, LOGIN_CODES, ValidateLogin } from "@flowcore/cli-plugin-config";
|
|
2
3
|
import { Args, Flags, ux } from '@oclif/core';
|
|
3
4
|
import dayjs from "dayjs";
|
|
4
5
|
import isSameOrBefore from "dayjs/plugin/isSameOrBefore.js";
|
|
5
6
|
import utc from "dayjs/plugin/utc.js";
|
|
6
7
|
import _ from "lodash";
|
|
7
8
|
import { Subject } from "rxjs";
|
|
8
|
-
import { BaseCommand } from "../base-command.js";
|
|
9
9
|
import { QueryGraphQL } from "../utils/graphql.util.js";
|
|
10
10
|
import { FETCH_DATA_CORE_GQL_QUERY } from "../utils/queries/fetch-data-core.gql.js";
|
|
11
11
|
import { FETCH_EVENT_TYPE_RANGE_GQL_QUERY } from "../utils/queries/fetch-event-type-range.gql.js";
|
|
12
12
|
import { FETCH_EVENTS_GQL_QUERY } from "../utils/queries/fetch-events.gql.js";
|
|
13
13
|
import { FETCH_CATALOG_INDEXES_QUERY } from "../utils/queries/fetch-indexes.gql.js";
|
|
14
14
|
import { TIME_BUCKET_HOUR_PATTERN, TIME_BUCKET_PATTERN, createTimebucket, createTimebucketDayjs } from "../utils/timebucket.util.js";
|
|
15
|
-
import { LOGIN_CODES, ValidateLogin } from "../utils/validate-login.util.js";
|
|
16
15
|
dayjs.extend(utc);
|
|
17
16
|
dayjs.extend(isSameOrBefore);
|
|
18
17
|
export default class Stream extends BaseCommand {
|
|
@@ -36,6 +35,15 @@ export default class Stream extends BaseCommand {
|
|
|
36
35
|
timeout: Flags.integer({ char: 't', default: 5000, description: 'Timeout in milliseconds to wait for a response from the destination' }),
|
|
37
36
|
};
|
|
38
37
|
async run() {
|
|
38
|
+
const { args, flags } = await this.parse(Stream);
|
|
39
|
+
const parts = args.STREAM.replace(/https?:\/\//i, "").split("/");
|
|
40
|
+
if (parts.length !== 5) {
|
|
41
|
+
ux.error(`Invalid stream url, ${args.STREAM}`);
|
|
42
|
+
}
|
|
43
|
+
const newProfile = this.cliConfiguration.switchProfile(args.STREAM);
|
|
44
|
+
if (newProfile) {
|
|
45
|
+
ux.log(`Using profile ${ux.colorize("yellow", newProfile)} based on stream url`);
|
|
46
|
+
}
|
|
39
47
|
const config = this.cliConfiguration.getConfig();
|
|
40
48
|
const loginValidator = new ValidateLogin(config.login.url);
|
|
41
49
|
const validateLogin = await loginValidator.validate(config, this.cliConfiguration, !this.flags.json);
|
|
@@ -52,11 +60,6 @@ export default class Stream extends BaseCommand {
|
|
|
52
60
|
}
|
|
53
61
|
return config.auth.accessToken;
|
|
54
62
|
});
|
|
55
|
-
const { args, flags } = await this.parse(Stream);
|
|
56
|
-
const parts = args.STREAM.replace(/https?:\/\//i, "").split("/");
|
|
57
|
-
if (parts.length !== 5) {
|
|
58
|
-
ux.error(`Invalid stream url, ${args.STREAM}`);
|
|
59
|
-
}
|
|
60
63
|
const org = parts[1];
|
|
61
64
|
const dataCore = parts[2];
|
|
62
65
|
const aggregator = parts[3];
|
package/dist/commands/whoami.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { BaseCommand } from "
|
|
2
|
-
import { LOGIN_CODES, ValidateLogin } from "../utils/validate-login.util.js";
|
|
1
|
+
import { BaseCommand, LOGIN_CODES, ValidateLogin } from "@flowcore/cli-plugin-config";
|
|
3
2
|
export default class Whoami extends BaseCommand {
|
|
4
3
|
static description = 'Check what user you are logged in as';
|
|
5
4
|
async run() {
|
package/oclif.manifest.json
CHANGED
|
@@ -1,46 +1,5 @@
|
|
|
1
1
|
{
|
|
2
2
|
"commands": {
|
|
3
|
-
"login": {
|
|
4
|
-
"aliases": [],
|
|
5
|
-
"args": {},
|
|
6
|
-
"description": "login to the Flowcore Platform",
|
|
7
|
-
"examples": [
|
|
8
|
-
"<%= config.bin %> <%= command.id %>",
|
|
9
|
-
"<%= config.bin %> <%= command.id %> --port 8080"
|
|
10
|
-
],
|
|
11
|
-
"flags": {
|
|
12
|
-
"profile": {
|
|
13
|
-
"description": "Specify the configuration profile to use",
|
|
14
|
-
"name": "profile",
|
|
15
|
-
"hasDynamicHelp": false,
|
|
16
|
-
"multiple": false,
|
|
17
|
-
"type": "option"
|
|
18
|
-
},
|
|
19
|
-
"port": {
|
|
20
|
-
"char": "p",
|
|
21
|
-
"description": "port to listen for the callback",
|
|
22
|
-
"name": "port",
|
|
23
|
-
"default": 3000,
|
|
24
|
-
"hasDynamicHelp": false,
|
|
25
|
-
"multiple": false,
|
|
26
|
-
"type": "option"
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
|
-
"hasDynamicHelp": false,
|
|
30
|
-
"hiddenAliases": [],
|
|
31
|
-
"id": "login",
|
|
32
|
-
"pluginAlias": "@flowcore/cli",
|
|
33
|
-
"pluginName": "@flowcore/cli",
|
|
34
|
-
"pluginType": "core",
|
|
35
|
-
"strict": true,
|
|
36
|
-
"enableJsonFlag": false,
|
|
37
|
-
"isESM": true,
|
|
38
|
-
"relativePath": [
|
|
39
|
-
"dist",
|
|
40
|
-
"commands",
|
|
41
|
-
"login.js"
|
|
42
|
-
]
|
|
43
|
-
},
|
|
44
3
|
"stream": {
|
|
45
4
|
"aliases": [],
|
|
46
5
|
"args": {
|
|
@@ -168,112 +127,7 @@
|
|
|
168
127
|
"commands",
|
|
169
128
|
"whoami.js"
|
|
170
129
|
]
|
|
171
|
-
},
|
|
172
|
-
"config:set": {
|
|
173
|
-
"aliases": [],
|
|
174
|
-
"args": {},
|
|
175
|
-
"description": "Configure the cli",
|
|
176
|
-
"examples": [
|
|
177
|
-
"<%= config.bin %> <%= command.id %> -l https://auth.flowcore.io/realms/flowcore/.well-known/openid-configuration -c my-client-id -s my-client-secret",
|
|
178
|
-
"<%= config.bin %> <%= command.id %> -u https://graph.api.flowcore.io/graphql",
|
|
179
|
-
"<%= config.bin %> <%= command.id %> -l https://auth.flowcore.io/realms/flowcore/.well-known/openid-configuration -c my-client-id -p"
|
|
180
|
-
],
|
|
181
|
-
"flags": {
|
|
182
|
-
"profile": {
|
|
183
|
-
"description": "Specify the configuration profile to use",
|
|
184
|
-
"name": "profile",
|
|
185
|
-
"hasDynamicHelp": false,
|
|
186
|
-
"multiple": false,
|
|
187
|
-
"type": "option"
|
|
188
|
-
},
|
|
189
|
-
"clientId": {
|
|
190
|
-
"char": "c",
|
|
191
|
-
"description": "client id to use for the login",
|
|
192
|
-
"name": "clientId",
|
|
193
|
-
"hasDynamicHelp": false,
|
|
194
|
-
"multiple": false,
|
|
195
|
-
"type": "option"
|
|
196
|
-
},
|
|
197
|
-
"clientSecret": {
|
|
198
|
-
"char": "n",
|
|
199
|
-
"description": "name to print",
|
|
200
|
-
"name": "clientSecret",
|
|
201
|
-
"hasDynamicHelp": false,
|
|
202
|
-
"multiple": false,
|
|
203
|
-
"type": "option"
|
|
204
|
-
},
|
|
205
|
-
"loginUrl": {
|
|
206
|
-
"char": "l",
|
|
207
|
-
"description": "url to discover the openid configuration",
|
|
208
|
-
"name": "loginUrl",
|
|
209
|
-
"hasDynamicHelp": false,
|
|
210
|
-
"multiple": false,
|
|
211
|
-
"type": "option"
|
|
212
|
-
},
|
|
213
|
-
"port": {
|
|
214
|
-
"char": "p",
|
|
215
|
-
"description": "prompt for port to listen for the callback",
|
|
216
|
-
"name": "port",
|
|
217
|
-
"allowNo": false,
|
|
218
|
-
"type": "boolean"
|
|
219
|
-
},
|
|
220
|
-
"url": {
|
|
221
|
-
"char": "u",
|
|
222
|
-
"description": "url to the flowcore platform api",
|
|
223
|
-
"name": "url",
|
|
224
|
-
"hasDynamicHelp": false,
|
|
225
|
-
"multiple": false,
|
|
226
|
-
"type": "option"
|
|
227
|
-
}
|
|
228
|
-
},
|
|
229
|
-
"hasDynamicHelp": false,
|
|
230
|
-
"hiddenAliases": [],
|
|
231
|
-
"id": "config:set",
|
|
232
|
-
"pluginAlias": "@flowcore/cli",
|
|
233
|
-
"pluginName": "@flowcore/cli",
|
|
234
|
-
"pluginType": "core",
|
|
235
|
-
"strict": true,
|
|
236
|
-
"enableJsonFlag": false,
|
|
237
|
-
"isESM": true,
|
|
238
|
-
"relativePath": [
|
|
239
|
-
"dist",
|
|
240
|
-
"commands",
|
|
241
|
-
"config",
|
|
242
|
-
"set.js"
|
|
243
|
-
]
|
|
244
|
-
},
|
|
245
|
-
"config:show": {
|
|
246
|
-
"aliases": [],
|
|
247
|
-
"args": {},
|
|
248
|
-
"description": "Show the configured login url",
|
|
249
|
-
"examples": [
|
|
250
|
-
"<%= config.bin %> <%= command.id %>"
|
|
251
|
-
],
|
|
252
|
-
"flags": {
|
|
253
|
-
"profile": {
|
|
254
|
-
"description": "Specify the configuration profile to use",
|
|
255
|
-
"name": "profile",
|
|
256
|
-
"hasDynamicHelp": false,
|
|
257
|
-
"multiple": false,
|
|
258
|
-
"type": "option"
|
|
259
|
-
}
|
|
260
|
-
},
|
|
261
|
-
"hasDynamicHelp": false,
|
|
262
|
-
"hiddenAliases": [],
|
|
263
|
-
"id": "config:show",
|
|
264
|
-
"pluginAlias": "@flowcore/cli",
|
|
265
|
-
"pluginName": "@flowcore/cli",
|
|
266
|
-
"pluginType": "core",
|
|
267
|
-
"strict": true,
|
|
268
|
-
"enableJsonFlag": false,
|
|
269
|
-
"isESM": true,
|
|
270
|
-
"relativePath": [
|
|
271
|
-
"dist",
|
|
272
|
-
"commands",
|
|
273
|
-
"config",
|
|
274
|
-
"show.js"
|
|
275
|
-
]
|
|
276
130
|
}
|
|
277
131
|
},
|
|
278
|
-
"version": "2.0
|
|
132
|
+
"version": "2.1.0"
|
|
279
133
|
}
|
package/package.json
CHANGED
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@datastructures-js/queue": "^4.2.3",
|
|
8
|
+
"@flowcore/cli-plugin-config": "^1.0.4",
|
|
8
9
|
"@flowcore/time-bucket": "^1.1.0",
|
|
9
10
|
"@oclif/core": "^3",
|
|
10
11
|
"@oclif/plugin-autocomplete": "^3.0.2",
|
|
@@ -16,14 +17,11 @@
|
|
|
16
17
|
"cross-fetch": "^4.0.0",
|
|
17
18
|
"dayjs": "^1.11.10",
|
|
18
19
|
"enquirer": "^2.4.1",
|
|
19
|
-
"express": "^4.18.2",
|
|
20
20
|
"graphql": "^16.8.1",
|
|
21
21
|
"graphql-request": "^6.1.0",
|
|
22
22
|
"jwt-decode": "^4.0.0",
|
|
23
23
|
"lodash": "^4.17.21",
|
|
24
24
|
"merge": "^2.1.1",
|
|
25
|
-
"open": "^9.1.0",
|
|
26
|
-
"openid-client": "^5.6.1",
|
|
27
25
|
"rxjs": "^7.8.1",
|
|
28
26
|
"session": "^0.1.0"
|
|
29
27
|
},
|
|
@@ -68,7 +66,8 @@
|
|
|
68
66
|
"@oclif/plugin-version",
|
|
69
67
|
"@oclif/plugin-plugins",
|
|
70
68
|
"@oclif/plugin-autocomplete",
|
|
71
|
-
"@oclif/plugin-not-found"
|
|
69
|
+
"@oclif/plugin-not-found",
|
|
70
|
+
"@flowcore/cli-plugin-config"
|
|
72
71
|
],
|
|
73
72
|
"topicSeparator": " "
|
|
74
73
|
},
|
|
@@ -86,7 +85,7 @@
|
|
|
86
85
|
"prestart": "npm run build",
|
|
87
86
|
"update-schema": "rover graph introspect https://graph.api.staging.flowcore.io/graphql -o schema.gql"
|
|
88
87
|
},
|
|
89
|
-
"version": "2.0
|
|
88
|
+
"version": "2.1.0",
|
|
90
89
|
"bugs": "https://github.com/flowcore-io/flowcore-cli/issues",
|
|
91
90
|
"keywords": [
|
|
92
91
|
"flowcore",
|
package/dist/base-command.d.ts
DELETED
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { Command, Interfaces } from '@oclif/core';
|
|
2
|
-
import { CliConfiguration } from "./utils/config.util.js";
|
|
3
|
-
export type Flags<T extends typeof Command> = Interfaces.InferredFlags<typeof BaseCommand['baseFlags'] & T['flags']>;
|
|
4
|
-
export type Args<T extends typeof Command> = Interfaces.InferredArgs<T['args']>;
|
|
5
|
-
export declare abstract class BaseCommand<T extends typeof Command> extends Command {
|
|
6
|
-
static baseFlags: {
|
|
7
|
-
profile: Interfaces.OptionFlag<string | undefined, Interfaces.CustomOptions>;
|
|
8
|
-
};
|
|
9
|
-
protected args: Args<T>;
|
|
10
|
-
protected cliConfiguration: CliConfiguration;
|
|
11
|
-
protected flags: Flags<T>;
|
|
12
|
-
protected catch(err: Error & {
|
|
13
|
-
exitCode?: number;
|
|
14
|
-
}): Promise<unknown>;
|
|
15
|
-
protected finally(_: Error | undefined): Promise<unknown>;
|
|
16
|
-
protected init(): Promise<void>;
|
|
17
|
-
}
|
package/dist/base-command.js
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
// src/baseCommand.ts
|
|
2
|
-
import { Command, Flags } from '@oclif/core';
|
|
3
|
-
import { CliConfiguration } from "./utils/config.util.js";
|
|
4
|
-
export class BaseCommand extends Command {
|
|
5
|
-
// define flags that can be inherited by any command that extends BaseCommand
|
|
6
|
-
static baseFlags = {
|
|
7
|
-
'profile': Flags.string({
|
|
8
|
-
description: 'Specify the configuration profile to use',
|
|
9
|
-
}),
|
|
10
|
-
};
|
|
11
|
-
args;
|
|
12
|
-
cliConfiguration = new CliConfiguration();
|
|
13
|
-
flags;
|
|
14
|
-
async catch(err) {
|
|
15
|
-
return super.catch(err);
|
|
16
|
-
}
|
|
17
|
-
async finally(_) {
|
|
18
|
-
return super.finally(_);
|
|
19
|
-
}
|
|
20
|
-
async init() {
|
|
21
|
-
await super.init();
|
|
22
|
-
const { args, flags } = await this.parse({
|
|
23
|
-
args: this.ctor.args,
|
|
24
|
-
baseFlags: super.ctor.baseFlags,
|
|
25
|
-
flags: this.ctor.flags,
|
|
26
|
-
strict: this.ctor.strict,
|
|
27
|
-
});
|
|
28
|
-
this.cliConfiguration.init(flags.profile || "default", this.config.configDir);
|
|
29
|
-
this.flags = flags;
|
|
30
|
-
this.args = args;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from "../../base-command.js";
|
|
2
|
-
export default class Set extends BaseCommand<typeof Set> {
|
|
3
|
-
static description: string;
|
|
4
|
-
static examples: string[];
|
|
5
|
-
static flags: {
|
|
6
|
-
clientId: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
7
|
-
clientSecret: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
8
|
-
loginUrl: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
9
|
-
port: import("@oclif/core/lib/interfaces/parser.js").BooleanFlag<boolean>;
|
|
10
|
-
url: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<string | undefined, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
11
|
-
};
|
|
12
|
-
run(): Promise<void>;
|
|
13
|
-
}
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
import { Flags } from '@oclif/core';
|
|
2
|
-
import pkg from "enquirer";
|
|
3
|
-
import _ from "lodash";
|
|
4
|
-
import { BaseCommand } from "../../base-command.js";
|
|
5
|
-
const { prompt } = pkg;
|
|
6
|
-
export default class Set extends BaseCommand {
|
|
7
|
-
static description = 'Configure the cli';
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> <%= command.id %> -l https://auth.flowcore.io/realms/flowcore/.well-known/openid-configuration -c my-client-id -s my-client-secret',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> -u https://graph.api.flowcore.io/graphql',
|
|
11
|
-
'<%= config.bin %> <%= command.id %> -l https://auth.flowcore.io/realms/flowcore/.well-known/openid-configuration -c my-client-id -p',
|
|
12
|
-
];
|
|
13
|
-
static flags = {
|
|
14
|
-
clientId: Flags.string({ char: 'c', description: 'client id to use for the login' }),
|
|
15
|
-
clientSecret: Flags.string({ char: 'n', description: 'name to print' }),
|
|
16
|
-
loginUrl: Flags.string({ char: 'l', description: 'url to discover the openid configuration' }),
|
|
17
|
-
port: Flags.boolean({ char: 'p', description: 'prompt for port to listen for the callback' }),
|
|
18
|
-
url: Flags.string({ char: 'u', description: 'url to the flowcore platform api' }),
|
|
19
|
-
};
|
|
20
|
-
async run() {
|
|
21
|
-
const { flags } = await this.parse(Set);
|
|
22
|
-
let callbackPort;
|
|
23
|
-
if (flags.port) {
|
|
24
|
-
const port = await prompt([{
|
|
25
|
-
choices: ["3000", "4000", "5000", "6000"],
|
|
26
|
-
message: "Select a port to listen for the callback",
|
|
27
|
-
name: "callbackPort",
|
|
28
|
-
type: "select"
|
|
29
|
-
}]);
|
|
30
|
-
callbackPort = port.callbackPort;
|
|
31
|
-
}
|
|
32
|
-
console.log(flags);
|
|
33
|
-
this.cliConfiguration.setConfig({
|
|
34
|
-
...(flags.url && { api: {
|
|
35
|
-
url: flags.url,
|
|
36
|
-
} }),
|
|
37
|
-
login: {
|
|
38
|
-
...(callbackPort && { callbackPort }),
|
|
39
|
-
...(flags.loginUrl && { url: flags.loginUrl }),
|
|
40
|
-
..._.omit(flags, ["port", "url", "loginUrl"]),
|
|
41
|
-
}
|
|
42
|
-
});
|
|
43
|
-
this.cliConfiguration.displayConfigTable(this.log.bind(this));
|
|
44
|
-
}
|
|
45
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
import { BaseCommand } from "../../base-command.js";
|
|
2
|
-
export default class LoginShow extends BaseCommand {
|
|
3
|
-
static description = 'Show the configured login url';
|
|
4
|
-
static examples = [
|
|
5
|
-
'<%= config.bin %> <%= command.id %>',
|
|
6
|
-
];
|
|
7
|
-
async run() {
|
|
8
|
-
this.log(`Showing configuration for ${this.cliConfiguration.getSelectedProfile()}`);
|
|
9
|
-
this.cliConfiguration.displayConfigTable(this.log.bind(this));
|
|
10
|
-
}
|
|
11
|
-
}
|
package/dist/commands/login.d.ts
DELETED
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" resolution-mode="require"/>
|
|
2
|
-
import * as http from "node:http";
|
|
3
|
-
import { BaseClient } from "openid-client";
|
|
4
|
-
import { BaseCommand } from "../base-command.js";
|
|
5
|
-
export default class Login extends BaseCommand<typeof Login> {
|
|
6
|
-
static description: string;
|
|
7
|
-
static examples: string[];
|
|
8
|
-
static flags: {
|
|
9
|
-
port: import("@oclif/core/lib/interfaces/parser.js").OptionFlag<number, import("@oclif/core/lib/interfaces/parser.js").CustomOptions>;
|
|
10
|
-
};
|
|
11
|
-
protected client: BaseClient | undefined;
|
|
12
|
-
protected server: http.Server | undefined;
|
|
13
|
-
protected catch(err: Error & {
|
|
14
|
-
exitCode?: number;
|
|
15
|
-
}): Promise<unknown>;
|
|
16
|
-
protected init(): Promise<void>;
|
|
17
|
-
run(): Promise<void>;
|
|
18
|
-
private writeToken;
|
|
19
|
-
}
|
package/dist/commands/login.js
DELETED
|
@@ -1,146 +0,0 @@
|
|
|
1
|
-
import { Flags } from '@oclif/core';
|
|
2
|
-
import express from 'express';
|
|
3
|
-
import open from "open";
|
|
4
|
-
import { Issuer, generators } from "openid-client";
|
|
5
|
-
import { BaseCommand } from "../base-command.js";
|
|
6
|
-
export default class Login extends BaseCommand {
|
|
7
|
-
static description = 'login to the Flowcore Platform';
|
|
8
|
-
static examples = [
|
|
9
|
-
'<%= config.bin %> <%= command.id %>',
|
|
10
|
-
'<%= config.bin %> <%= command.id %> --port 8080',
|
|
11
|
-
];
|
|
12
|
-
static flags = {
|
|
13
|
-
port: Flags.integer({ char: 'p', default: 3000, description: 'port to listen for the callback' }),
|
|
14
|
-
};
|
|
15
|
-
client;
|
|
16
|
-
server;
|
|
17
|
-
catch(err) {
|
|
18
|
-
this.server?.close();
|
|
19
|
-
return super.catch(err);
|
|
20
|
-
}
|
|
21
|
-
async init() {
|
|
22
|
-
await super.init();
|
|
23
|
-
try {
|
|
24
|
-
const { login } = this.cliConfiguration.getConfig();
|
|
25
|
-
const oidcIssuer = await Issuer.discover(login.url);
|
|
26
|
-
this.client = new oidcIssuer.Client({
|
|
27
|
-
// eslint-disable-next-line camelcase
|
|
28
|
-
client_id: login.clientId,
|
|
29
|
-
// eslint-disable-next-line camelcase
|
|
30
|
-
...(login.clientSecret && { client_secret: login.clientSecret }),
|
|
31
|
-
// eslint-disable-next-line camelcase
|
|
32
|
-
redirect_uris: [`http://localhost:${login.callbackPort}/callback`],
|
|
33
|
-
// eslint-disable-next-line camelcase
|
|
34
|
-
response_types: ['code'],
|
|
35
|
-
// eslint-disable-next-line camelcase
|
|
36
|
-
token_endpoint_auth_method: 'none',
|
|
37
|
-
});
|
|
38
|
-
}
|
|
39
|
-
catch (error) {
|
|
40
|
-
this.error(`Failed to discover the openid configuration: ${error}`);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
async run() {
|
|
44
|
-
if (!this.client) {
|
|
45
|
-
this.error("No client configured");
|
|
46
|
-
}
|
|
47
|
-
const { login } = this.cliConfiguration.getConfig();
|
|
48
|
-
const codeVerifier = generators.codeVerifier();
|
|
49
|
-
const codeChallenge = generators.codeChallenge(codeVerifier);
|
|
50
|
-
const loginUrl = this.client.authorizationUrl({
|
|
51
|
-
// eslint-disable-next-line camelcase
|
|
52
|
-
code_challenge: codeChallenge,
|
|
53
|
-
// eslint-disable-next-line camelcase
|
|
54
|
-
code_challenge_method: 'S256',
|
|
55
|
-
scope: 'openid profile email flowcore_user offline_access',
|
|
56
|
-
});
|
|
57
|
-
const app = express();
|
|
58
|
-
app.get('/callback', async (req, res) => {
|
|
59
|
-
const params = this.client.callbackParams(req);
|
|
60
|
-
// eslint-disable-next-line camelcase
|
|
61
|
-
const tokenSet = await this.client.callback(`http://localhost:${port}/callback`, params, { code_verifier: codeVerifier });
|
|
62
|
-
if (!tokenSet.claims()) {
|
|
63
|
-
this.error("No claims in token set");
|
|
64
|
-
}
|
|
65
|
-
if (tokenSet.claims()) {
|
|
66
|
-
this.log(`Logged in as ${tokenSet.claims().preferred_username}`);
|
|
67
|
-
}
|
|
68
|
-
this.writeToken(tokenSet);
|
|
69
|
-
const claims = tokenSet.claims();
|
|
70
|
-
res.send(`
|
|
71
|
-
<!DOCTYPE html>
|
|
72
|
-
<html lang="en">
|
|
73
|
-
<head>
|
|
74
|
-
<meta charset="UTF-8">
|
|
75
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
76
|
-
<link rel="icon" href="https://flowcore.com/favicon.ico" type="image/x-icon" sizes="any">
|
|
77
|
-
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.4/css/all.min.css">
|
|
78
|
-
<title>Login Successful</title>
|
|
79
|
-
<style>
|
|
80
|
-
body {
|
|
81
|
-
font-family: Arial, sans-serif;
|
|
82
|
-
background-color: #000000;
|
|
83
|
-
color: #FFFFFF;
|
|
84
|
-
text-align: center;
|
|
85
|
-
padding: 50px;
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
h1 {
|
|
89
|
-
font-size: 32px;
|
|
90
|
-
margin-bottom: 20px;
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
p {
|
|
94
|
-
font-size: 16px;
|
|
95
|
-
margin-bottom: 30px;
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
.success-icon {
|
|
99
|
-
color: #66bd6a;
|
|
100
|
-
font-size: 48px;
|
|
101
|
-
margin-bottom: 20px;
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
.button {
|
|
105
|
-
background-color: #ff4ba2;
|
|
106
|
-
color: #FFFFFF;
|
|
107
|
-
padding: 10px 20px;
|
|
108
|
-
font-size: 18px;
|
|
109
|
-
border: none;
|
|
110
|
-
border-radius: 4px;
|
|
111
|
-
cursor: pointer;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
.button:hover {
|
|
115
|
-
background-color: #1976D2;
|
|
116
|
-
}
|
|
117
|
-
</style>
|
|
118
|
-
</head>
|
|
119
|
-
<body>
|
|
120
|
-
<div class="success-icon">
|
|
121
|
-
<i class="fa fa-check-circle"></i>
|
|
122
|
-
</div>
|
|
123
|
-
<h1>Login Successful</h1>
|
|
124
|
-
<p>Hello ${claims.preferred_username}! You have successfully logged in. You can now close this window.</p>
|
|
125
|
-
<button class="button" onclick="window.close();">Close Window</button>
|
|
126
|
-
</body>
|
|
127
|
-
</html>
|
|
128
|
-
`);
|
|
129
|
-
this.server?.close();
|
|
130
|
-
});
|
|
131
|
-
const port = login.callbackPort;
|
|
132
|
-
await open(loginUrl, { wait: false });
|
|
133
|
-
this.server = app.listen(port, () => {
|
|
134
|
-
this.log(`Listening for authentication callback on port ${port}`);
|
|
135
|
-
});
|
|
136
|
-
}
|
|
137
|
-
writeToken(tokenSet) {
|
|
138
|
-
this.cliConfiguration.setConfig({
|
|
139
|
-
auth: {
|
|
140
|
-
accessToken: tokenSet.access_token,
|
|
141
|
-
idToken: tokenSet.id_token,
|
|
142
|
-
refreshToken: tokenSet.refresh_token,
|
|
143
|
-
}
|
|
144
|
-
});
|
|
145
|
-
}
|
|
146
|
-
}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
export declare const CONFIG_FILE_NAME = "credentials.json";
|
|
2
|
-
export declare class CliConfiguration {
|
|
3
|
-
private config;
|
|
4
|
-
private configPath;
|
|
5
|
-
private selectedProfile;
|
|
6
|
-
private static generateConfigPath;
|
|
7
|
-
displayConfigTable(log: (message?: string, ...args: unknown[]) => void): void;
|
|
8
|
-
getConfig(): CliConfig;
|
|
9
|
-
getSelectedProfile(): string;
|
|
10
|
-
init(profile: string, path: string): void;
|
|
11
|
-
setConfig(newConfig: unknown): void;
|
|
12
|
-
private ensureConfigIsValid;
|
|
13
|
-
}
|
|
14
|
-
export type CliConfig = {
|
|
15
|
-
api: {
|
|
16
|
-
url: string;
|
|
17
|
-
};
|
|
18
|
-
auth?: {
|
|
19
|
-
accessToken: string;
|
|
20
|
-
idToken?: string;
|
|
21
|
-
refreshToken?: string;
|
|
22
|
-
};
|
|
23
|
-
login: {
|
|
24
|
-
callbackPort: number;
|
|
25
|
-
clientId: string;
|
|
26
|
-
clientSecret?: string;
|
|
27
|
-
url: string;
|
|
28
|
-
};
|
|
29
|
-
};
|
|
30
|
-
export declare const createDefaultConfig: (configPath: string) => void;
|
|
31
|
-
export declare const loadConfig: (configPath: string) => CliConfig;
|
|
@@ -1,108 +0,0 @@
|
|
|
1
|
-
import { ux } from "@oclif/core";
|
|
2
|
-
import _ from "lodash";
|
|
3
|
-
import { merge, recursive } from "merge";
|
|
4
|
-
import * as fs from "node:fs";
|
|
5
|
-
import * as path from "node:path";
|
|
6
|
-
import { getObjectPaths } from "./object-path.util.js";
|
|
7
|
-
export const CONFIG_FILE_NAME = "credentials.json";
|
|
8
|
-
export class CliConfiguration {
|
|
9
|
-
config = {};
|
|
10
|
-
configPath = "";
|
|
11
|
-
selectedProfile = "";
|
|
12
|
-
static generateConfigPath(configDir) {
|
|
13
|
-
return `${configDir}/${CONFIG_FILE_NAME}`;
|
|
14
|
-
}
|
|
15
|
-
displayConfigTable(log) {
|
|
16
|
-
const maskedValues = new Set([
|
|
17
|
-
"login.clientSecret",
|
|
18
|
-
"auth.accessToken",
|
|
19
|
-
"auth.idToken",
|
|
20
|
-
"auth.refreshToken",
|
|
21
|
-
]);
|
|
22
|
-
const objectPaths = getObjectPaths(this.config);
|
|
23
|
-
ux.table(objectPaths.map(oMap => maskedValues.has(oMap) ?
|
|
24
|
-
({ path: oMap, value: "*******" }) : ({ path: oMap, value: _.get(this.config, oMap) })), {
|
|
25
|
-
path: {},
|
|
26
|
-
value: {
|
|
27
|
-
get: (row) => row.value ?? "not configured",
|
|
28
|
-
header: 'Value'
|
|
29
|
-
}
|
|
30
|
-
}, {
|
|
31
|
-
printLine: log,
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
getConfig() {
|
|
35
|
-
return this.config;
|
|
36
|
-
}
|
|
37
|
-
getSelectedProfile() {
|
|
38
|
-
return this.selectedProfile;
|
|
39
|
-
}
|
|
40
|
-
init(profile, path) {
|
|
41
|
-
this.configPath = CliConfiguration.generateConfigPath(path);
|
|
42
|
-
this.selectedProfile = profile;
|
|
43
|
-
this.ensureConfigIsValid();
|
|
44
|
-
}
|
|
45
|
-
setConfig(newConfig) {
|
|
46
|
-
this.config = recursive(this.config, newConfig);
|
|
47
|
-
const existingConfig = JSON.parse(fs.readFileSync(this.configPath, "utf8"));
|
|
48
|
-
fs.writeFileSync(this.configPath, JSON.stringify(recursive(existingConfig, {
|
|
49
|
-
[this.selectedProfile]: this.config,
|
|
50
|
-
}), null, 2));
|
|
51
|
-
}
|
|
52
|
-
ensureConfigIsValid() {
|
|
53
|
-
const defaultConfig = {
|
|
54
|
-
api: {
|
|
55
|
-
url: "https://graph.api.flowcore.io/graphql",
|
|
56
|
-
},
|
|
57
|
-
login: {
|
|
58
|
-
callbackPort: 3000,
|
|
59
|
-
clientId: "flowcore-cli",
|
|
60
|
-
url: "https://auth.flowcore.io/realms/flowcore/.well-known/openid-configuration",
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
if (!fs.existsSync(path.dirname(this.configPath))) {
|
|
64
|
-
fs.mkdirSync(path.dirname(this.configPath), { recursive: true });
|
|
65
|
-
}
|
|
66
|
-
if (fs.existsSync(this.configPath)) {
|
|
67
|
-
const existingConfig = JSON.parse(fs.readFileSync(this.configPath, "utf8"));
|
|
68
|
-
this.config = existingConfig[this.selectedProfile] ? recursive(defaultConfig, existingConfig[this.selectedProfile]) : defaultConfig;
|
|
69
|
-
fs.writeFileSync(this.configPath, JSON.stringify(recursive(existingConfig, {
|
|
70
|
-
[this.selectedProfile]: this.config,
|
|
71
|
-
}), null, 2));
|
|
72
|
-
}
|
|
73
|
-
else {
|
|
74
|
-
this.config = defaultConfig;
|
|
75
|
-
fs.writeFileSync(this.configPath, JSON.stringify({
|
|
76
|
-
[this.selectedProfile]: this.config,
|
|
77
|
-
}, null, 2));
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
export const createDefaultConfig = (configPath) => {
|
|
82
|
-
const config = {
|
|
83
|
-
api: {
|
|
84
|
-
url: "https://graph.api.flowcore.io/graphql",
|
|
85
|
-
},
|
|
86
|
-
login: {
|
|
87
|
-
callbackPort: 3000,
|
|
88
|
-
clientId: "flowcoreweb",
|
|
89
|
-
url: "https://auth.flowcore.io/realms/flowcore/.well-known/openid-configuration",
|
|
90
|
-
}
|
|
91
|
-
};
|
|
92
|
-
if (!fs.existsSync(path.dirname(configPath))) {
|
|
93
|
-
fs.mkdirSync(path.dirname(configPath), { recursive: true });
|
|
94
|
-
}
|
|
95
|
-
if (fs.existsSync(configPath)) {
|
|
96
|
-
const existingConfig = JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
97
|
-
fs.writeFileSync(configPath, JSON.stringify(merge(config, existingConfig), null, 2));
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
fs.writeFileSync(configPath, JSON.stringify(config, null, 2));
|
|
101
|
-
}
|
|
102
|
-
};
|
|
103
|
-
export const loadConfig = (configPath) => {
|
|
104
|
-
if (!fs.existsSync(configPath)) {
|
|
105
|
-
createDefaultConfig(configPath);
|
|
106
|
-
}
|
|
107
|
-
return JSON.parse(fs.readFileSync(configPath, "utf8"));
|
|
108
|
-
};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function getObjectPaths(obj: unknown, parentKey?: string): string[];
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
export function getObjectPaths(obj, parentKey) {
|
|
2
|
-
let paths = [];
|
|
3
|
-
for (const key in obj) {
|
|
4
|
-
if (Object.hasOwn(obj, key)) {
|
|
5
|
-
const path = parentKey ? `${parentKey}.${key}` : key;
|
|
6
|
-
const value = obj[key];
|
|
7
|
-
if (typeof value === 'object' && value !== null) {
|
|
8
|
-
const nestedPaths = getObjectPaths(value, path);
|
|
9
|
-
paths = [...paths, ...nestedPaths];
|
|
10
|
-
}
|
|
11
|
-
else {
|
|
12
|
-
paths.push(path);
|
|
13
|
-
}
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
return paths;
|
|
17
|
-
}
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
import { CliConfig, CliConfiguration } from "./config.util.js";
|
|
2
|
-
export type UserInfo = {
|
|
3
|
-
family_name: string;
|
|
4
|
-
flowcore_user_id: string;
|
|
5
|
-
given_name: string;
|
|
6
|
-
name: string;
|
|
7
|
-
preferred_username: string;
|
|
8
|
-
};
|
|
9
|
-
export declare enum LOGIN_CODES {
|
|
10
|
-
LOGIN_EXPIRED = 2,
|
|
11
|
-
LOGIN_FAILED = 0,
|
|
12
|
-
LOGIN_SUCCESS = 1
|
|
13
|
-
}
|
|
14
|
-
export declare class ValidateLogin {
|
|
15
|
-
private readonly url;
|
|
16
|
-
constructor(url: string);
|
|
17
|
-
isExpired(config: CliConfig, client: CliConfiguration, displayProgress?: boolean): Promise<boolean>;
|
|
18
|
-
tryRefreshToken(config: CliConfig, client: CliConfiguration): Promise<CliConfig>;
|
|
19
|
-
validate(config: CliConfig, client: CliConfiguration, displayProgress?: boolean): Promise<{
|
|
20
|
-
status: LOGIN_CODES;
|
|
21
|
-
} | UserInfo & {
|
|
22
|
-
status: LOGIN_CODES;
|
|
23
|
-
}>;
|
|
24
|
-
}
|
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { ux } from "@oclif/core";
|
|
2
|
-
import { jwtDecode } from "jwt-decode";
|
|
3
|
-
export var LOGIN_CODES;
|
|
4
|
-
(function (LOGIN_CODES) {
|
|
5
|
-
LOGIN_CODES[LOGIN_CODES["LOGIN_EXPIRED"] = 2] = "LOGIN_EXPIRED";
|
|
6
|
-
LOGIN_CODES[LOGIN_CODES["LOGIN_FAILED"] = 0] = "LOGIN_FAILED";
|
|
7
|
-
LOGIN_CODES[LOGIN_CODES["LOGIN_SUCCESS"] = 1] = "LOGIN_SUCCESS";
|
|
8
|
-
})(LOGIN_CODES || (LOGIN_CODES = {}));
|
|
9
|
-
export class ValidateLogin {
|
|
10
|
-
url;
|
|
11
|
-
constructor(url) {
|
|
12
|
-
this.url = url;
|
|
13
|
-
}
|
|
14
|
-
async isExpired(config, client, displayProgress = true) {
|
|
15
|
-
const decoded = jwtDecode(config.auth?.accessToken ?? "");
|
|
16
|
-
if (decoded.exp === undefined) {
|
|
17
|
-
throw new Error("Invalid id token");
|
|
18
|
-
}
|
|
19
|
-
if (decoded.exp * 1000 < Date.now() - 5000) {
|
|
20
|
-
try {
|
|
21
|
-
if (displayProgress) {
|
|
22
|
-
ux.action.start("Refreshing token");
|
|
23
|
-
}
|
|
24
|
-
config = await this.tryRefreshToken(config, client);
|
|
25
|
-
if (displayProgress) {
|
|
26
|
-
ux.action.stop("Refreshed token");
|
|
27
|
-
}
|
|
28
|
-
return true;
|
|
29
|
-
}
|
|
30
|
-
catch (error) {
|
|
31
|
-
ux.error(`Failed to refresh token: ${error}`);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
return false;
|
|
35
|
-
}
|
|
36
|
-
async tryRefreshToken(config, client) {
|
|
37
|
-
if (config.auth?.refreshToken === undefined) {
|
|
38
|
-
throw new Error("No refresh token");
|
|
39
|
-
}
|
|
40
|
-
const response = await fetch(this.url);
|
|
41
|
-
const json = await response.json();
|
|
42
|
-
if (json.token_endpoint === undefined) {
|
|
43
|
-
throw new Error("No token_endpoint in openid configuration");
|
|
44
|
-
}
|
|
45
|
-
const body = new URLSearchParams();
|
|
46
|
-
body.append("grant_type", "refresh_token");
|
|
47
|
-
body.append("refresh_token", config.auth.refreshToken);
|
|
48
|
-
body.append("client_id", config.login.clientId);
|
|
49
|
-
body.append("client_secret", config.login.clientSecret ?? "");
|
|
50
|
-
const result = await fetch(json.token_endpoint, {
|
|
51
|
-
body,
|
|
52
|
-
method: "POST",
|
|
53
|
-
});
|
|
54
|
-
if (result.status !== 200) {
|
|
55
|
-
throw new Error("Failed to refresh token");
|
|
56
|
-
}
|
|
57
|
-
const resultJson = await result.json();
|
|
58
|
-
client.setConfig({
|
|
59
|
-
auth: {
|
|
60
|
-
...config.auth,
|
|
61
|
-
accessToken: resultJson.access_token,
|
|
62
|
-
idToken: resultJson.id_token,
|
|
63
|
-
refreshToken: resultJson.refresh_token,
|
|
64
|
-
}
|
|
65
|
-
});
|
|
66
|
-
return client.getConfig();
|
|
67
|
-
}
|
|
68
|
-
async validate(config, client, displayProgress = true) {
|
|
69
|
-
const response = await fetch(this.url);
|
|
70
|
-
const json = await response.json();
|
|
71
|
-
if (json.userinfo_endpoint === undefined) {
|
|
72
|
-
throw new Error("No userinfo_endpoint in openid configuration");
|
|
73
|
-
}
|
|
74
|
-
if (config.auth === undefined) {
|
|
75
|
-
return {
|
|
76
|
-
status: LOGIN_CODES.LOGIN_FAILED,
|
|
77
|
-
};
|
|
78
|
-
}
|
|
79
|
-
if (config.auth.accessToken === undefined) {
|
|
80
|
-
return {
|
|
81
|
-
status: LOGIN_CODES.LOGIN_FAILED,
|
|
82
|
-
};
|
|
83
|
-
}
|
|
84
|
-
try {
|
|
85
|
-
await this.isExpired(config, client, displayProgress);
|
|
86
|
-
}
|
|
87
|
-
catch {
|
|
88
|
-
return {
|
|
89
|
-
status: LOGIN_CODES.LOGIN_EXPIRED,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
try {
|
|
93
|
-
const result = await fetch(json.userinfo_endpoint, {
|
|
94
|
-
headers: {
|
|
95
|
-
"Authorization": `Bearer ${config?.auth?.accessToken}`,
|
|
96
|
-
}
|
|
97
|
-
});
|
|
98
|
-
if (result.status !== 200) {
|
|
99
|
-
return {
|
|
100
|
-
status: LOGIN_CODES.LOGIN_FAILED,
|
|
101
|
-
};
|
|
102
|
-
}
|
|
103
|
-
return {
|
|
104
|
-
...await result.json(),
|
|
105
|
-
status: LOGIN_CODES.LOGIN_SUCCESS,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
catch (error) {
|
|
109
|
-
console.error(error);
|
|
110
|
-
return {
|
|
111
|
-
status: LOGIN_CODES.LOGIN_FAILED,
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
}
|