@credibledata/cred-cli 0.0.100 → 0.0.103
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/README-DEV.md +2 -2
- package/README.md +1 -1
- package/coverage/coverage-summary.json +40 -0
- package/coverage/tmp/coverage-2152-1789496974457-0.json +1 -0
- package/coverage/tmp/coverage-2153-1789496954404-0.json +1 -0
- package/dist/client/api.js +6151 -2254
- package/dist/client/api.js.map +1 -1
- package/dist/client/base.js +1 -1
- package/dist/client/common.js +1 -1
- package/dist/client/configuration.js +1 -1
- package/dist/client/index.js +1 -1
- package/dist/clientconfiguration.js +114 -26
- package/dist/clientconfiguration.js.map +1 -1
- package/dist/clientconfiguration.spec.js +159 -37
- package/dist/clientconfiguration.spec.js.map +1 -1
- package/dist/commands/add.js +36 -5
- package/dist/commands/add.js.map +1 -1
- package/dist/commands/connection/createconnections.js +4 -4
- package/dist/commands/connection/createconnections.js.map +1 -1
- package/dist/commands/connection/createconnections.spec.js +11 -1
- package/dist/commands/connection/createconnections.spec.js.map +1 -1
- package/dist/commands/connection/deleteconnection.js +4 -4
- package/dist/commands/connection/deleteconnection.js.map +1 -1
- package/dist/commands/connection/deleteconnection.spec.js +1 -1
- package/dist/commands/connection/deleteconnection.spec.js.map +1 -1
- package/dist/commands/connection/listconnections.js +4 -4
- package/dist/commands/connection/listconnections.js.map +1 -1
- package/dist/commands/connection/listconnections.spec.js +1 -1
- package/dist/commands/connection/listconnections.spec.js.map +1 -1
- package/dist/commands/{project/createproject.js → environment/createenvironment.js} +17 -14
- package/dist/commands/environment/createenvironment.js.map +1 -0
- package/dist/commands/{project/createproject.spec.js → environment/createenvironment.spec.js} +46 -46
- package/dist/commands/environment/createenvironment.spec.js.map +1 -0
- package/dist/commands/{project/deleteproject.js → environment/deleteenvironment.js} +9 -9
- package/dist/commands/environment/deleteenvironment.js.map +1 -0
- package/dist/commands/{project/deleteproject.spec.js → environment/deleteenvironment.spec.js} +29 -29
- package/dist/commands/environment/deleteenvironment.spec.js.map +1 -0
- package/dist/commands/{project/getproject.js → environment/getenvironment.js} +8 -8
- package/dist/commands/environment/getenvironment.js.map +1 -0
- package/dist/commands/{project/getproject.spec.js → environment/getenvironment.spec.js} +32 -33
- package/dist/commands/environment/getenvironment.spec.js.map +1 -0
- package/dist/commands/{project/listprojects.js → environment/listenvironments.js} +10 -10
- package/dist/commands/environment/listenvironments.js.map +1 -0
- package/dist/commands/{project/listprojects.spec.js → environment/listenvironments.spec.js} +35 -35
- package/dist/commands/environment/listenvironments.spec.js.map +1 -0
- package/dist/commands/{project/setproject.js → environment/setenvironment.js} +6 -5
- package/dist/commands/environment/setenvironment.js.map +1 -0
- package/dist/commands/{project/setproject.spec.js → environment/setenvironment.spec.js} +9 -9
- package/dist/commands/environment/setenvironment.spec.js.map +1 -0
- package/dist/commands/environment/updateenvironment.js +130 -0
- package/dist/commands/environment/updateenvironment.js.map +1 -0
- package/dist/commands/environment/updateenvironment.spec.js +213 -0
- package/dist/commands/environment/updateenvironment.spec.js.map +1 -0
- package/dist/commands/get.js +66 -5
- package/dist/commands/get.js.map +1 -1
- package/dist/commands/legacy.js +9 -0
- package/dist/commands/legacy.js.map +1 -0
- package/dist/commands/list.js +95 -4
- package/dist/commands/list.js.map +1 -1
- package/dist/commands/materialization/cancelrun.js +62 -0
- package/dist/commands/materialization/cancelrun.js.map +1 -0
- package/dist/commands/materialization/getindex.js +52 -0
- package/dist/commands/materialization/getindex.js.map +1 -0
- package/dist/commands/materialization/getmaterialization.js +54 -0
- package/dist/commands/materialization/getmaterialization.js.map +1 -0
- package/dist/commands/materialization/getpreaggregate.js +55 -0
- package/dist/commands/materialization/getpreaggregate.js.map +1 -0
- package/dist/commands/materialization/getrun.js +54 -0
- package/dist/commands/materialization/getrun.js.map +1 -0
- package/dist/commands/materialization/listindexes.js +58 -0
- package/dist/commands/materialization/listindexes.js.map +1 -0
- package/dist/commands/materialization/listmaterializations.js +52 -0
- package/dist/commands/materialization/listmaterializations.js.map +1 -0
- package/dist/commands/materialization/listpreaggregates.js +61 -0
- package/dist/commands/materialization/listpreaggregates.js.map +1 -0
- package/dist/commands/materialization/listruns.js +60 -0
- package/dist/commands/materialization/listruns.js.map +1 -0
- package/dist/commands/materialization/rerun.js +111 -0
- package/dist/commands/materialization/rerun.js.map +1 -0
- package/dist/commands/misc/login.js +16 -2
- package/dist/commands/misc/login.js.map +1 -1
- package/dist/commands/misc/login.spec.js +133 -5
- package/dist/commands/misc/login.spec.js.map +1 -1
- package/dist/commands/package/deletepackage.js +4 -4
- package/dist/commands/package/deletepackage.js.map +1 -1
- package/dist/commands/package/deletepackage.spec.js +1 -1
- package/dist/commands/package/deletepackage.spec.js.map +1 -1
- package/dist/commands/package/listpackages.js +11 -4
- package/dist/commands/package/listpackages.js.map +1 -1
- package/dist/commands/package/listpackages.spec.js +13 -1
- package/dist/commands/package/listpackages.spec.js.map +1 -1
- package/dist/commands/package/publish.js +36 -13
- package/dist/commands/package/publish.js.map +1 -1
- package/dist/commands/package/publish.spec.js +27 -1
- package/dist/commands/package/publish.spec.js.map +1 -1
- package/dist/commands/package/updatepackage.js +4 -4
- package/dist/commands/package/updatepackage.js.map +1 -1
- package/dist/commands/package/updatepackage.spec.js +1 -1
- package/dist/commands/package/updatepackage.spec.js.map +1 -1
- package/dist/commands/permission/createpermission.js +123 -0
- package/dist/commands/permission/createpermission.js.map +1 -0
- package/dist/commands/permission/createpermission.spec.js +360 -0
- package/dist/commands/permission/createpermission.spec.js.map +1 -0
- package/dist/commands/permission/deletepermission.js +86 -0
- package/dist/commands/permission/deletepermission.js.map +1 -0
- package/dist/commands/permission/getpermission.js +85 -0
- package/dist/commands/permission/getpermission.js.map +1 -0
- package/dist/commands/permission/listpermissions.js +75 -0
- package/dist/commands/permission/listpermissions.js.map +1 -0
- package/dist/commands/permission/scope.js +140 -0
- package/dist/commands/permission/scope.js.map +1 -0
- package/dist/commands/rm.js +26 -4
- package/dist/commands/rm.js.map +1 -1
- package/dist/commands/set.js +12 -4
- package/dist/commands/set.js.map +1 -1
- package/dist/commands/update.js +29 -10
- package/dist/commands/update.js.map +1 -1
- package/dist/commands/version/archive-unarchive-version.js +4 -5
- package/dist/commands/version/archive-unarchive-version.js.map +1 -1
- package/dist/commands/version/archive-unarchive-version.spec.js +4 -4
- package/dist/commands/version/archive-unarchive-version.spec.js.map +1 -1
- package/dist/commands/version/listversions.js +4 -4
- package/dist/commands/version/listversions.js.map +1 -1
- package/dist/commands/version/listversions.spec.js +1 -1
- package/dist/commands/version/listversions.spec.js.map +1 -1
- package/dist/common/UserGroupId.js +1 -1
- package/dist/common/UserGroupId.js.map +1 -1
- package/dist/common/UserGroupId.spec.js +2 -4
- package/dist/common/UserGroupId.spec.js.map +1 -1
- package/dist/constants.js +95 -19
- package/dist/constants.js.map +1 -1
- package/dist/constants.spec.js +90 -0
- package/dist/constants.spec.js.map +1 -0
- package/dist/index.js +128 -15
- package/dist/index.js.map +1 -1
- package/dist/logger.js +5 -1
- package/dist/logger.js.map +1 -1
- package/openapitools.json +4 -1
- package/package.json +10 -9
- package/src/client/api.ts +9363 -3093
- package/src/client/base.ts +1 -1
- package/src/client/common.ts +1 -1
- package/src/client/configuration.ts +1 -1
- package/src/client/index.ts +1 -1
- package/src/clientconfiguration.spec.ts +238 -113
- package/src/clientconfiguration.ts +131 -30
- package/src/commands/add.ts +78 -12
- package/src/commands/connection/createconnections.spec.ts +11 -1
- package/src/commands/connection/createconnections.ts +4 -4
- package/src/commands/connection/deleteconnection.spec.ts +1 -1
- package/src/commands/connection/deleteconnection.ts +4 -4
- package/src/commands/connection/listconnections.spec.ts +1 -1
- package/src/commands/connection/listconnections.ts +4 -4
- package/src/commands/{project/createproject.spec.ts → environment/createenvironment.spec.ts} +56 -54
- package/src/commands/{project/createproject.ts → environment/createenvironment.ts} +17 -14
- package/src/commands/{project/deleteproject.spec.ts → environment/deleteenvironment.spec.ts} +59 -30
- package/src/commands/{project/deleteproject.ts → environment/deleteenvironment.ts} +10 -10
- package/src/commands/environment/getenvironment.spec.ts +110 -0
- package/src/commands/{project/getproject.ts → environment/getenvironment.ts} +9 -9
- package/src/commands/{project/listprojects.spec.ts → environment/listenvironments.spec.ts} +37 -35
- package/src/commands/{project/listprojects.ts → environment/listenvironments.ts} +13 -8
- package/src/commands/{project/setproject.spec.ts → environment/setenvironment.spec.ts} +8 -8
- package/src/commands/{project/setproject.ts → environment/setenvironment.ts} +4 -4
- package/src/commands/environment/updateenvironment.spec.ts +386 -0
- package/src/commands/environment/updateenvironment.ts +168 -0
- package/src/commands/get.ts +131 -9
- package/src/commands/legacy.ts +5 -0
- package/src/commands/list.ts +204 -9
- package/src/commands/materialization/cancelrun.ts +70 -0
- package/src/commands/materialization/getindex.ts +55 -0
- package/src/commands/materialization/getmaterialization.ts +57 -0
- package/src/commands/materialization/getpreaggregate.ts +58 -0
- package/src/commands/materialization/getrun.ts +55 -0
- package/src/commands/materialization/listindexes.ts +69 -0
- package/src/commands/materialization/listmaterializations.ts +53 -0
- package/src/commands/materialization/listpreaggregates.ts +74 -0
- package/src/commands/materialization/listruns.ts +77 -0
- package/src/commands/materialization/rerun.ts +123 -0
- package/src/commands/misc/login.spec.ts +165 -7
- package/src/commands/misc/login.ts +20 -2
- package/src/commands/package/deletepackage.spec.ts +1 -1
- package/src/commands/package/deletepackage.ts +4 -4
- package/src/commands/package/listpackages.spec.ts +17 -1
- package/src/commands/package/listpackages.ts +11 -4
- package/src/commands/package/publish.spec.ts +46 -1
- package/src/commands/package/publish.ts +38 -13
- package/src/commands/package/updatepackage.spec.ts +1 -1
- package/src/commands/package/updatepackage.ts +4 -4
- package/src/commands/permission/createpermission.spec.ts +507 -0
- package/src/commands/permission/createpermission.ts +181 -0
- package/src/commands/permission/deletepermission.ts +117 -0
- package/src/commands/permission/getpermission.ts +115 -0
- package/src/commands/permission/listpermissions.ts +101 -0
- package/src/commands/permission/scope.ts +180 -0
- package/src/commands/rm.ts +54 -9
- package/src/commands/set.ts +13 -4
- package/src/commands/update.ts +66 -23
- package/src/commands/version/archive-unarchive-version.spec.ts +4 -4
- package/src/commands/version/archive-unarchive-version.ts +4 -7
- package/src/commands/version/listversions.spec.ts +1 -1
- package/src/commands/version/listversions.ts +4 -4
- package/src/common/UserGroupId.spec.ts +2 -4
- package/src/common/UserGroupId.ts +1 -1
- package/src/constants.spec.ts +111 -0
- package/src/constants.ts +131 -19
- package/src/index.ts +187 -18
- package/src/logger.ts +5 -1
- package/bun.lock +0 -1158
- package/dist/commands/project/createproject.js.map +0 -1
- package/dist/commands/project/createproject.spec.js.map +0 -1
- package/dist/commands/project/deleteproject.js.map +0 -1
- package/dist/commands/project/deleteproject.spec.js.map +0 -1
- package/dist/commands/project/getproject.js.map +0 -1
- package/dist/commands/project/getproject.spec.js.map +0 -1
- package/dist/commands/project/listprojects.js.map +0 -1
- package/dist/commands/project/listprojects.spec.js.map +0 -1
- package/dist/commands/project/setproject.js.map +0 -1
- package/dist/commands/project/setproject.spec.js.map +0 -1
- package/dist/commands/project/updateproject.js +0 -68
- package/dist/commands/project/updateproject.js.map +0 -1
- package/dist/commands/project/updateproject.spec.js +0 -129
- package/dist/commands/project/updateproject.spec.js.map +0 -1
- package/src/commands/project/getproject.spec.ts +0 -109
- package/src/commands/project/updateproject.spec.ts +0 -217
- package/src/commands/project/updateproject.ts +0 -82
|
@@ -1,8 +1,14 @@
|
|
|
1
|
+
import crypto from "crypto";
|
|
1
2
|
import fs from "fs";
|
|
2
3
|
import { jwtDecode } from "jwt-decode";
|
|
3
4
|
import kleur from "kleur";
|
|
4
5
|
import os from "os";
|
|
5
|
-
import {
|
|
6
|
+
import {
|
|
7
|
+
ALL_ENVIRONMENTS,
|
|
8
|
+
ASCII_TITLE,
|
|
9
|
+
controlPlanesByEnv,
|
|
10
|
+
Environment,
|
|
11
|
+
} from "./constants";
|
|
6
12
|
import { logger } from "./logger";
|
|
7
13
|
|
|
8
14
|
interface ConfigFile {
|
|
@@ -33,6 +39,15 @@ interface JwtPayload {
|
|
|
33
39
|
sub?: string;
|
|
34
40
|
}
|
|
35
41
|
|
|
42
|
+
/**
|
|
43
|
+
* Thrown when `.cred` exists but cannot be used: either it does not parse as
|
|
44
|
+
* JSON or it parses but lacks the required top-level shape. Distinct from fs
|
|
45
|
+
* errors (ENOENT, EACCES) so callers that want to recover — `cred login` —
|
|
46
|
+
* can target *only* a corrupt-content failure and leave permission/IO errors
|
|
47
|
+
* to surface loudly.
|
|
48
|
+
*/
|
|
49
|
+
export class InvalidConfigError extends Error {}
|
|
50
|
+
|
|
36
51
|
export class ClientConfiguration {
|
|
37
52
|
private configPath = `${os.homedir()}/.cred`;
|
|
38
53
|
private config: ConfigFile;
|
|
@@ -44,28 +59,35 @@ export class ClientConfiguration {
|
|
|
44
59
|
}
|
|
45
60
|
|
|
46
61
|
public loadConfig(): ConfigFile {
|
|
62
|
+
let fileContents: Buffer | undefined;
|
|
47
63
|
try {
|
|
48
|
-
|
|
49
|
-
this.config = JSON.parse(fileContents.toString());
|
|
50
|
-
if (
|
|
51
|
-
!this.config.activeEnvironment ||
|
|
52
|
-
!this.config.configPerEnvironment
|
|
53
|
-
) {
|
|
54
|
-
throw new Error(
|
|
55
|
-
"Corrupted config file found, restoring to default settings.",
|
|
56
|
-
);
|
|
57
|
-
}
|
|
64
|
+
fileContents = fs.readFileSync(this.configPath);
|
|
58
65
|
} catch (error) {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
66
|
+
if ((error as NodeJS.ErrnoException)?.code === "ENOENT") {
|
|
67
|
+
// First-time setup: create a default config on disk.
|
|
68
|
+
this.config = this.defaultConfig();
|
|
69
|
+
this.writeConfig();
|
|
70
|
+
return this.config;
|
|
63
71
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
72
|
+
throw error;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
try {
|
|
76
|
+
this.config = JSON.parse(fileContents.toString());
|
|
77
|
+
} catch (error) {
|
|
78
|
+
// Non-atomic writes from older binaries, or a manually corrupted file,
|
|
79
|
+
// can leave `.cred` unparseable. Fail loud rather than silently
|
|
80
|
+
// overwriting — a silent reset erases the access token for every
|
|
81
|
+
// subsequent caller on the same machine.
|
|
82
|
+
throw new InvalidConfigError(
|
|
83
|
+
`Failed to parse ${this.configPath}: ${error}. The file may be corrupt; re-run \`cred login\` to reset.`,
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (!this.config.activeEnvironment || !this.config.configPerEnvironment) {
|
|
88
|
+
throw new InvalidConfigError(
|
|
89
|
+
`Invalid config structure in ${this.configPath}; re-run \`cred login\` to reset.`,
|
|
90
|
+
);
|
|
69
91
|
}
|
|
70
92
|
|
|
71
93
|
for (const env of ALL_ENVIRONMENTS) {
|
|
@@ -77,13 +99,86 @@ export class ClientConfiguration {
|
|
|
77
99
|
return this.config;
|
|
78
100
|
}
|
|
79
101
|
|
|
102
|
+
/**
|
|
103
|
+
* Ensure `.cred` is usable, recovering from a corrupt file if needed.
|
|
104
|
+
*
|
|
105
|
+
* `loadConfig` deliberately fails loud on a corrupt/invalid file so a read
|
|
106
|
+
* path never silently erases tokens. But `cred login` exists precisely to
|
|
107
|
+
* (re)establish config, so it must be able to get past a bad file — that is
|
|
108
|
+
* what the "re-run `cred login` to reset" message promises. We make the
|
|
109
|
+
* message true here: the bad file is renamed aside (never deleted, so a
|
|
110
|
+
* support engineer can still inspect it) and a fresh default is written.
|
|
111
|
+
*
|
|
112
|
+
* Only an {@link InvalidConfigError} triggers recovery. fs errors such as
|
|
113
|
+
* EACCES are real environment problems and are rethrown — resetting would
|
|
114
|
+
* just fail to write anyway, and we must not mask a permissions issue as a
|
|
115
|
+
* successful reset.
|
|
116
|
+
*
|
|
117
|
+
* @returns the path the corrupt file was backed up to, or null if the
|
|
118
|
+
* existing config was already valid.
|
|
119
|
+
*/
|
|
120
|
+
public recoverIfCorrupt(): string | null {
|
|
121
|
+
try {
|
|
122
|
+
this.loadConfig();
|
|
123
|
+
return null;
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (!(error instanceof InvalidConfigError)) {
|
|
126
|
+
throw error;
|
|
127
|
+
}
|
|
128
|
+
const backupPath = `${this.configPath}.corrupt-${crypto
|
|
129
|
+
.randomBytes(8)
|
|
130
|
+
.toString("hex")}`;
|
|
131
|
+
fs.renameSync(this.configPath, backupPath);
|
|
132
|
+
logger.warn(
|
|
133
|
+
`Existing config at ${this.configPath} was invalid and could not be read. ` +
|
|
134
|
+
`Backed it up to ${backupPath} and reset to defaults.`,
|
|
135
|
+
);
|
|
136
|
+
this.config = this.defaultConfig();
|
|
137
|
+
this.writeConfig();
|
|
138
|
+
return backupPath;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
private defaultConfig(): ConfigFile {
|
|
143
|
+
const configPerEnvironment: ConfigFile["configPerEnvironment"] = {};
|
|
144
|
+
for (const env of ALL_ENVIRONMENTS) {
|
|
145
|
+
configPerEnvironment[env] = {};
|
|
146
|
+
}
|
|
147
|
+
return { configPerEnvironment, activeEnvironment: "production" };
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Atomic: write to a sibling temp file, then rename into place.
|
|
151
|
+
// Readers either see the old file or the new file, never a truncated
|
|
152
|
+
// zero-byte snapshot (the window that `writeFileSync` exposes between
|
|
153
|
+
// open(O_TRUNC) and write).
|
|
154
|
+
//
|
|
155
|
+
// The temp suffix uses 16 bytes of crypto-random hex so the temp
|
|
156
|
+
// path is unguessable — a predictable name (pid + Date.now()) lets a
|
|
157
|
+
// co-located attacker pre-create a symlink at that path and trick
|
|
158
|
+
// us into clobbering an arbitrary file (CodeQL js/insecure-temporary-file).
|
|
159
|
+
// O_EXCL on open further refuses to follow a pre-existing entry.
|
|
160
|
+
private writeConfig(): void {
|
|
161
|
+
const tmp = `${this.configPath}.${crypto.randomBytes(16).toString("hex")}.tmp`;
|
|
162
|
+
const fd = fs.openSync(
|
|
163
|
+
tmp,
|
|
164
|
+
fs.constants.O_WRONLY | fs.constants.O_CREAT | fs.constants.O_EXCL,
|
|
165
|
+
0o600,
|
|
166
|
+
);
|
|
167
|
+
try {
|
|
168
|
+
fs.writeFileSync(fd, JSON.stringify(this.config));
|
|
169
|
+
} finally {
|
|
170
|
+
fs.closeSync(fd);
|
|
171
|
+
}
|
|
172
|
+
fs.renameSync(tmp, this.configPath);
|
|
173
|
+
}
|
|
174
|
+
|
|
80
175
|
public setOrganization(organizationName: string) {
|
|
81
176
|
this.loadConfig();
|
|
82
177
|
// TODO: Validate organization exists and user has access.
|
|
83
178
|
const environment = this.getEnvironment();
|
|
84
179
|
this.config.configPerEnvironment[environment].organization =
|
|
85
180
|
organizationName;
|
|
86
|
-
|
|
181
|
+
this.writeConfig();
|
|
87
182
|
}
|
|
88
183
|
|
|
89
184
|
public setProject(projectName: string) {
|
|
@@ -91,7 +186,7 @@ export class ClientConfiguration {
|
|
|
91
186
|
// TODO: Validate project exists and user has access.
|
|
92
187
|
const environment = this.getEnvironment();
|
|
93
188
|
this.config.configPerEnvironment[environment].project = projectName;
|
|
94
|
-
|
|
189
|
+
this.writeConfig();
|
|
95
190
|
}
|
|
96
191
|
|
|
97
192
|
public getOrganization() {
|
|
@@ -112,7 +207,7 @@ export class ClientConfiguration {
|
|
|
112
207
|
this.config.configPerEnvironment[environment].isServiceAccountToken =
|
|
113
208
|
!userToken;
|
|
114
209
|
this.config.configPerEnvironment[environment].accessToken = accessToken;
|
|
115
|
-
|
|
210
|
+
this.writeConfig();
|
|
116
211
|
}
|
|
117
212
|
|
|
118
213
|
public getAuthenticationHeader() {
|
|
@@ -135,7 +230,7 @@ export class ClientConfiguration {
|
|
|
135
230
|
const environment = this.getEnvironment();
|
|
136
231
|
this.config.configPerEnvironment[environment].jwtAccessToken =
|
|
137
232
|
jwtAccessToken;
|
|
138
|
-
|
|
233
|
+
this.writeConfig();
|
|
139
234
|
}
|
|
140
235
|
|
|
141
236
|
public getJwtAccessToken(): string | undefined {
|
|
@@ -154,7 +249,7 @@ export class ClientConfiguration {
|
|
|
154
249
|
username,
|
|
155
250
|
email,
|
|
156
251
|
};
|
|
157
|
-
|
|
252
|
+
this.writeConfig();
|
|
158
253
|
}
|
|
159
254
|
|
|
160
255
|
public getVSCodeUser(): { username: string; email: string } | undefined {
|
|
@@ -167,7 +262,7 @@ export class ClientConfiguration {
|
|
|
167
262
|
this.loadConfig();
|
|
168
263
|
const environment = this.getEnvironment();
|
|
169
264
|
this.config.configPerEnvironment[environment].refreshToken = refreshToken;
|
|
170
|
-
|
|
265
|
+
this.writeConfig();
|
|
171
266
|
}
|
|
172
267
|
|
|
173
268
|
public getRefreshToken(): string | undefined {
|
|
@@ -192,13 +287,13 @@ export class ClientConfiguration {
|
|
|
192
287
|
this.loadConfig();
|
|
193
288
|
const environment = this.getEnvironment();
|
|
194
289
|
this.config.configPerEnvironment[environment] = {};
|
|
195
|
-
|
|
290
|
+
this.writeConfig();
|
|
196
291
|
}
|
|
197
292
|
|
|
198
293
|
public setEnvironment(environment: Environment) {
|
|
199
294
|
this.loadConfig();
|
|
200
295
|
this.config.activeEnvironment = environment;
|
|
201
|
-
|
|
296
|
+
this.writeConfig();
|
|
202
297
|
}
|
|
203
298
|
|
|
204
299
|
public getEnvironment() {
|
|
@@ -245,14 +340,20 @@ export class ClientConfiguration {
|
|
|
245
340
|
public printStatus() {
|
|
246
341
|
this.loadConfig();
|
|
247
342
|
const tokenStatus = this.isTokenValid();
|
|
343
|
+
const cell = this.getEnvironment();
|
|
344
|
+
|
|
345
|
+
// The cell prints on both branches, and before anything else: an org and an
|
|
346
|
+
// environment name alone do not identify a cell (two cells can both hold a
|
|
347
|
+
// `demo`), and a stale token is most often a token for the wrong one.
|
|
348
|
+
console.log(kleur.green(ASCII_TITLE));
|
|
349
|
+
logger.info(`Cell: ${kleur.green(cell)} (${controlPlanesByEnv[cell]})`);
|
|
248
350
|
|
|
249
351
|
if (tokenStatus.valid) {
|
|
250
352
|
const organization = this.getOrganization();
|
|
251
353
|
const project = this.getProject();
|
|
252
354
|
|
|
253
|
-
console.log(kleur.green(ASCII_TITLE));
|
|
254
355
|
logger.info(`Organization: ${kleur.green(organization || "Not set")}`);
|
|
255
|
-
logger.info(`
|
|
356
|
+
logger.info(`Environment: ${kleur.green(project || "Not set")}`);
|
|
256
357
|
} else {
|
|
257
358
|
logger.error("Failed to get status");
|
|
258
359
|
logger.error(
|
package/src/commands/add.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
|
+
/* eslint-disable @typescript-eslint/no-explicit-any */
|
|
1
2
|
import { Command } from "commander";
|
|
2
3
|
import { controlPlanesByEnv, Environment } from "../constants";
|
|
3
4
|
import { createConnections } from "./connection/createconnections";
|
|
4
5
|
import { addMember } from "./group/addmember";
|
|
5
6
|
import { createGroup } from "./group/creategroup";
|
|
6
7
|
import { createGroupAccessToken } from "./groupaccesstoken/createToken";
|
|
7
|
-
import {
|
|
8
|
+
import { createEnvironment } from "./environment/createenvironment";
|
|
9
|
+
import { warnProjectDeprecated } from "./legacy";
|
|
10
|
+
import { createPermission } from "./permission/createpermission";
|
|
8
11
|
|
|
9
12
|
export const registerAddCommands = (cli: Command, environment: Environment) => {
|
|
10
13
|
const add = cli
|
|
@@ -12,14 +15,41 @@ export const registerAddCommands = (cli: Command, environment: Environment) => {
|
|
|
12
15
|
.description("Add a resource")
|
|
13
16
|
.argument("<resource>", "The resource to add");
|
|
14
17
|
|
|
18
|
+
const addEnvironmentAction = (environmentName: string, options: any) => {
|
|
19
|
+
createEnvironment(
|
|
20
|
+
controlPlanesByEnv[environment],
|
|
21
|
+
environmentName,
|
|
22
|
+
options.readmeFile,
|
|
23
|
+
options.replication,
|
|
24
|
+
options.debug,
|
|
25
|
+
options.yes,
|
|
26
|
+
);
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
add.command("environment")
|
|
30
|
+
.description("Add an environment.")
|
|
31
|
+
.argument("<environmentName>", "The name of the environment to create.")
|
|
32
|
+
.option("--debug")
|
|
33
|
+
.option("-y, --yes", "Skip confirmation.")
|
|
34
|
+
.option(
|
|
35
|
+
"--readmeFile <readmeFile>",
|
|
36
|
+
"The path to the readme file for the environment.",
|
|
37
|
+
)
|
|
38
|
+
.option(
|
|
39
|
+
"--replication <replicationCount>",
|
|
40
|
+
"The replication count (must be at least 1).",
|
|
41
|
+
parseInt,
|
|
42
|
+
)
|
|
43
|
+
.action(addEnvironmentAction);
|
|
44
|
+
|
|
15
45
|
add.command("project")
|
|
16
|
-
.description("
|
|
17
|
-
.argument("<projectName>", "The name of the
|
|
46
|
+
.description("[deprecated] Alias for 'add environment'.")
|
|
47
|
+
.argument("<projectName>", "The name of the environment to create.")
|
|
18
48
|
.option("--debug")
|
|
19
49
|
.option("-y, --yes", "Skip confirmation.")
|
|
20
50
|
.option(
|
|
21
51
|
"--readmeFile <readmeFile>",
|
|
22
|
-
"The path to the readme file for the
|
|
52
|
+
"The path to the readme file for the environment.",
|
|
23
53
|
)
|
|
24
54
|
.option(
|
|
25
55
|
"--replication <replicationCount>",
|
|
@@ -27,14 +57,8 @@ export const registerAddCommands = (cli: Command, environment: Environment) => {
|
|
|
27
57
|
parseInt,
|
|
28
58
|
)
|
|
29
59
|
.action((projectName, options) => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
projectName,
|
|
33
|
-
options.readmeFile,
|
|
34
|
-
options.replication,
|
|
35
|
-
options.debug,
|
|
36
|
-
options.yes,
|
|
37
|
-
);
|
|
60
|
+
warnProjectDeprecated("add environment");
|
|
61
|
+
addEnvironmentAction(projectName, options);
|
|
38
62
|
});
|
|
39
63
|
|
|
40
64
|
add.command("connection")
|
|
@@ -102,6 +126,48 @@ export const registerAddCommands = (cli: Command, environment: Environment) => {
|
|
|
102
126
|
);
|
|
103
127
|
});
|
|
104
128
|
|
|
129
|
+
add.command("permission")
|
|
130
|
+
.description(
|
|
131
|
+
"Grant a user or group a permission on the organization, an environment, or a package.",
|
|
132
|
+
)
|
|
133
|
+
.argument(
|
|
134
|
+
"<userGroupId>",
|
|
135
|
+
"Who to grant it to [user:{email}|group:{groupName}|user:*]",
|
|
136
|
+
)
|
|
137
|
+
.argument(
|
|
138
|
+
"<role>",
|
|
139
|
+
"The role to grant (organization: admin|modeler|member; environment: admin|modeler|viewer; package: viewer)",
|
|
140
|
+
)
|
|
141
|
+
.option(
|
|
142
|
+
"--environment <environmentName>",
|
|
143
|
+
"Grant on this environment instead of the organization.",
|
|
144
|
+
)
|
|
145
|
+
.option(
|
|
146
|
+
"--package <packageName>",
|
|
147
|
+
"Grant on this package. Uses --environment, or the current environment.",
|
|
148
|
+
)
|
|
149
|
+
.option(
|
|
150
|
+
"--notifyPeople",
|
|
151
|
+
"Email the person about the new access. Applies to an environment or a package; an organization grant always notifies a user subject.",
|
|
152
|
+
false,
|
|
153
|
+
)
|
|
154
|
+
.option("--debug")
|
|
155
|
+
.option("-y, --yes", "Skip confirmation.")
|
|
156
|
+
.action((userGroupId, role, options) => {
|
|
157
|
+
createPermission(
|
|
158
|
+
controlPlanesByEnv[environment],
|
|
159
|
+
userGroupId,
|
|
160
|
+
role,
|
|
161
|
+
options.debug || false,
|
|
162
|
+
{
|
|
163
|
+
environment: options.environment,
|
|
164
|
+
package: options.package,
|
|
165
|
+
notifyPeople: options.notifyPeople === true,
|
|
166
|
+
yes: options.yes === true,
|
|
167
|
+
},
|
|
168
|
+
);
|
|
169
|
+
});
|
|
170
|
+
|
|
105
171
|
add.command("group-access-token")
|
|
106
172
|
.description("Create an access token for a group.")
|
|
107
173
|
.argument("<groupName>", "The name of the group")
|
|
@@ -270,6 +270,13 @@ describe("create-connections", () => {
|
|
|
270
270
|
getConfirmationStub = sandbox.stub();
|
|
271
271
|
readFileSyncStub = sandbox.stub(fs, "readFileSync");
|
|
272
272
|
|
|
273
|
+
// Short-circuit loadConfig — createconnections calls getOrganization
|
|
274
|
+
// before it checks doesConfigExists, so we need to stub it or loadConfig
|
|
275
|
+
// would run against the stubbed readFileSync.
|
|
276
|
+
sandbox
|
|
277
|
+
.stub(ClientConfiguration.prototype, "getOrganization")
|
|
278
|
+
.returns("");
|
|
279
|
+
sandbox.stub(ClientConfiguration.prototype, "getProject").returns("");
|
|
273
280
|
sandbox
|
|
274
281
|
.stub(ClientConfiguration.prototype, "doesConfigExists")
|
|
275
282
|
.returns(false);
|
|
@@ -309,6 +316,9 @@ describe("create-connections", () => {
|
|
|
309
316
|
sandbox
|
|
310
317
|
.stub(ClientConfiguration.prototype, "doesConfigExists")
|
|
311
318
|
.returns(true);
|
|
319
|
+
sandbox
|
|
320
|
+
.stub(ClientConfiguration.prototype, "getOrganization")
|
|
321
|
+
.returns("test-org");
|
|
312
322
|
sandbox.stub(ClientConfiguration.prototype, "getProject").returns("");
|
|
313
323
|
sandbox
|
|
314
324
|
.stub(ConnectionsApi.prototype, "createConnection")
|
|
@@ -330,7 +340,7 @@ describe("create-connections", () => {
|
|
|
330
340
|
expect(createConnectionStub.called).to.be.false;
|
|
331
341
|
expect(
|
|
332
342
|
loggerStub.error.calledWith(
|
|
333
|
-
sinon.match("Please, make sure to set
|
|
343
|
+
sinon.match("Please, make sure to set an environment"),
|
|
334
344
|
),
|
|
335
345
|
).to.be.true;
|
|
336
346
|
});
|
|
@@ -18,15 +18,15 @@ export const createConnections = async (
|
|
|
18
18
|
) => {
|
|
19
19
|
const clientConfig = new ClientConfiguration();
|
|
20
20
|
const organizationName = clientConfig.getOrganization();
|
|
21
|
-
const
|
|
21
|
+
const environmentName = clientConfig.getProject();
|
|
22
22
|
|
|
23
23
|
if (!clientConfig.doesConfigExists()) {
|
|
24
24
|
logger.error("Please, make sure that you are logged in");
|
|
25
25
|
return;
|
|
26
26
|
}
|
|
27
27
|
|
|
28
|
-
if (!
|
|
29
|
-
logger.error("Please, make sure to set
|
|
28
|
+
if (!environmentName) {
|
|
29
|
+
logger.error("Please, make sure to set an environment");
|
|
30
30
|
return;
|
|
31
31
|
}
|
|
32
32
|
|
|
@@ -92,7 +92,7 @@ export const createConnections = async (
|
|
|
92
92
|
|
|
93
93
|
await connectionsApi.createConnection(
|
|
94
94
|
organizationName,
|
|
95
|
-
|
|
95
|
+
environmentName,
|
|
96
96
|
connection,
|
|
97
97
|
false,
|
|
98
98
|
{
|
|
@@ -131,7 +131,7 @@ describe("delete-connection", () => {
|
|
|
131
131
|
expect(deleteConnectionStub.called).to.be.false;
|
|
132
132
|
expect(
|
|
133
133
|
loggerStub.error.calledWith(
|
|
134
|
-
sinon.match("Please, make sure to set
|
|
134
|
+
sinon.match("Please, make sure to set an environment"),
|
|
135
135
|
),
|
|
136
136
|
).to.be.true;
|
|
137
137
|
});
|
|
@@ -14,15 +14,15 @@ export const deleteConnection = async (
|
|
|
14
14
|
) => {
|
|
15
15
|
const clientConfig = new ClientConfiguration();
|
|
16
16
|
const organizationName = clientConfig.getOrganization();
|
|
17
|
-
const
|
|
17
|
+
const environmentName = clientConfig.getProject();
|
|
18
18
|
|
|
19
19
|
if (!clientConfig.doesConfigExists()) {
|
|
20
20
|
logger.error("Please, make sure that you are logged in");
|
|
21
21
|
return;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
-
if (!
|
|
25
|
-
logger.error("Please, make sure to set
|
|
24
|
+
if (!environmentName) {
|
|
25
|
+
logger.error("Please, make sure to set an environment");
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
28
|
|
|
@@ -41,7 +41,7 @@ export const deleteConnection = async (
|
|
|
41
41
|
try {
|
|
42
42
|
await connectionsApi.deleteConnection(
|
|
43
43
|
organizationName,
|
|
44
|
-
|
|
44
|
+
environmentName,
|
|
45
45
|
connectionName,
|
|
46
46
|
{
|
|
47
47
|
baseURL: controlPlane,
|
|
@@ -113,7 +113,7 @@ describe("list-connections", () => {
|
|
|
113
113
|
expect(listConnectionsStub.called).to.be.false;
|
|
114
114
|
expect(
|
|
115
115
|
loggerStub.error.calledWith(
|
|
116
|
-
sinon.match("Please, make sure to set
|
|
116
|
+
sinon.match("Please, make sure to set an environment"),
|
|
117
117
|
),
|
|
118
118
|
).to.be.true;
|
|
119
119
|
});
|
|
@@ -19,15 +19,15 @@ export const listConnections = async (
|
|
|
19
19
|
) => {
|
|
20
20
|
const clientConfig = new ClientConfiguration();
|
|
21
21
|
const organizationName = clientConfig.getOrganization();
|
|
22
|
-
const
|
|
22
|
+
const environmentName = clientConfig.getProject();
|
|
23
23
|
|
|
24
24
|
if (!clientConfig.doesConfigExists()) {
|
|
25
25
|
logger.error("Please, make sure that you are logged in");
|
|
26
26
|
return;
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
if (!
|
|
30
|
-
logger.error("Please, make sure to set
|
|
29
|
+
if (!environmentName) {
|
|
30
|
+
logger.error("Please, make sure to set an environment");
|
|
31
31
|
return;
|
|
32
32
|
}
|
|
33
33
|
|
|
@@ -35,7 +35,7 @@ export const listConnections = async (
|
|
|
35
35
|
const { limit, offset } = parsePaginationParams(page, pageSize);
|
|
36
36
|
const response = await connectionsApi.listConnections(
|
|
37
37
|
organizationName,
|
|
38
|
-
|
|
38
|
+
environmentName,
|
|
39
39
|
limit,
|
|
40
40
|
offset,
|
|
41
41
|
{
|