@flowcore/cli-plugin-iam 1.0.0 → 1.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 +14 -0
- package/README.md +3 -3
- package/dist/commands/get/policy.js +2 -3
- package/dist/hooks/register-apply.d.ts +10 -0
- package/dist/hooks/register-apply.js +9 -0
- package/dist/resource-types/iam-api-version.d.ts +24 -0
- package/dist/resource-types/iam-api-version.js +106 -0
- package/dist/resource-types/policy-binding.resource.d.ts +82 -0
- package/dist/resource-types/policy-binding.resource.js +203 -0
- package/dist/resource-types/policy.resource.d.ts +110 -0
- package/dist/resource-types/policy.resource.js +158 -0
- package/dist/resource-types/role-binding.resource.d.ts +82 -0
- package/dist/resource-types/role-binding.resource.js +203 -0
- package/dist/resource-types/role.resource.d.ts +65 -0
- package/dist/resource-types/role.resource.js +191 -0
- package/dist/utils/clients/iam/Api.d.ts +84 -0
- package/dist/utils/clients/iam/Api.js +30 -0
- package/dist/utils/clients/iam/http-client.d.ts +2 -2
- package/dist/utils/clients/iam/http-client.js +6 -18
- package/dist/utils/fetch-manifest.util.js +0 -1
- package/oclif.manifest.json +1 -1
- package/package.json +8 -2
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
import { baseResourceDto } from "@flowcore/cli-plugin-core";
|
|
2
|
+
import { diff } from "@opentf/obj-diff";
|
|
3
|
+
import enquirer from "enquirer";
|
|
4
|
+
import { diffString } from "json-diff";
|
|
5
|
+
import { inspect } from "node:util";
|
|
6
|
+
import { z } from "zod";
|
|
7
|
+
export const roleDto = baseResourceDto.extend({
|
|
8
|
+
spec: z.object({
|
|
9
|
+
description: z.string().optional(),
|
|
10
|
+
flowcoreManaged: z.boolean().optional(),
|
|
11
|
+
policies: z.array(z.string()),
|
|
12
|
+
}),
|
|
13
|
+
});
|
|
14
|
+
export class RoleService {
|
|
15
|
+
iamClient;
|
|
16
|
+
logger;
|
|
17
|
+
getToken;
|
|
18
|
+
constructor(iamClient, logger, getToken) {
|
|
19
|
+
this.iamClient = iamClient;
|
|
20
|
+
this.logger = logger;
|
|
21
|
+
this.getToken = getToken;
|
|
22
|
+
}
|
|
23
|
+
async createNewRole(organizationId, role, skipConfirmation) {
|
|
24
|
+
const parsedRole = roleDto.parse(role);
|
|
25
|
+
try {
|
|
26
|
+
const roles = await this.iamClient.getApiV1RoleAssociationsOrganizationByOrganizationId(organizationId, {
|
|
27
|
+
headers: {
|
|
28
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
29
|
+
},
|
|
30
|
+
});
|
|
31
|
+
const existingRole = roles.data.find((r) => r.name === parsedRole.metadata.name);
|
|
32
|
+
const policies = await this.iamClient.getApiV1PolicyAssociationsOrganizationByOrganizationId(organizationId, {
|
|
33
|
+
headers: {
|
|
34
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
35
|
+
},
|
|
36
|
+
});
|
|
37
|
+
const linkedPolicies = policies.data.filter((p) => parsedRole.spec.policies.includes(p.name));
|
|
38
|
+
if (!existingRole) {
|
|
39
|
+
const result = await this.iamClient.postApiV1Roles({
|
|
40
|
+
description: parsedRole.spec.description ?? undefined,
|
|
41
|
+
name: parsedRole.metadata.name,
|
|
42
|
+
organizationId,
|
|
43
|
+
}, {
|
|
44
|
+
headers: {
|
|
45
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
46
|
+
},
|
|
47
|
+
});
|
|
48
|
+
if (result.status !== 200) {
|
|
49
|
+
this.logger.fatal(`Failed to create role: ${result.statusText}`);
|
|
50
|
+
}
|
|
51
|
+
const role = result.data;
|
|
52
|
+
for (const linkedPolicy of linkedPolicies) {
|
|
53
|
+
const binding = await this.iamClient.postApiV1PolicyAssociationsRoleByRoleId(role.id, {
|
|
54
|
+
policyId: linkedPolicy.id,
|
|
55
|
+
}, {
|
|
56
|
+
headers: {
|
|
57
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
58
|
+
},
|
|
59
|
+
});
|
|
60
|
+
if (binding.status !== 200) {
|
|
61
|
+
this.logger.fatal(`Failed to bind policy ${linkedPolicy.id} to role ${role.id}: ${binding.statusText}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
const alreadyLinkedPolicies = await this.iamClient.getApiV1PolicyAssociationsRoleByRoleId(existingRole.id, {
|
|
67
|
+
headers: {
|
|
68
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
69
|
+
},
|
|
70
|
+
});
|
|
71
|
+
this.logger.debug(`Found ${inspect(alreadyLinkedPolicies.data)} policies linked to role ${existingRole.id}`);
|
|
72
|
+
const newRole = {
|
|
73
|
+
description: parsedRole.spec.description ?? "",
|
|
74
|
+
name: parsedRole.metadata.name,
|
|
75
|
+
policies: parsedRole.spec.policies.sort(),
|
|
76
|
+
};
|
|
77
|
+
const existingRoleData = {
|
|
78
|
+
description: existingRole.description ?? "",
|
|
79
|
+
name: existingRole.name,
|
|
80
|
+
policies: alreadyLinkedPolicies.data.map((p) => p.name).sort(),
|
|
81
|
+
};
|
|
82
|
+
const diffResult = diff(existingRoleData, newRole);
|
|
83
|
+
if (diffResult.length === 0) {
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
if (!skipConfirmation) {
|
|
87
|
+
this.logger.info("Role has changed, do you want to apply these changes?");
|
|
88
|
+
this.logger.info(diffString(existingRoleData, newRole, {
|
|
89
|
+
color: true,
|
|
90
|
+
full: true,
|
|
91
|
+
}));
|
|
92
|
+
const { confirm } = await enquirer.prompt({
|
|
93
|
+
message: "Are you sure you want to update the role?",
|
|
94
|
+
name: "confirm",
|
|
95
|
+
type: "confirm",
|
|
96
|
+
});
|
|
97
|
+
if (!confirm) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
const result = await this.iamClient.patchApiV1RolesById(existingRole.id, {
|
|
102
|
+
description: newRole.description,
|
|
103
|
+
id: existingRole.id,
|
|
104
|
+
name: newRole.name,
|
|
105
|
+
organizationId,
|
|
106
|
+
}, {
|
|
107
|
+
headers: {
|
|
108
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
if (result.status !== 200) {
|
|
112
|
+
this.logger.fatal(`Failed to update role: ${result.statusText}`);
|
|
113
|
+
}
|
|
114
|
+
const toAdd = newRole.policies.filter((p) => !existingRoleData.policies.includes(p));
|
|
115
|
+
const toRemove = existingRoleData.policies.filter((p) => !newRole.policies.includes(p));
|
|
116
|
+
for (const policy of toAdd) {
|
|
117
|
+
const policyId = policies.data.find((p) => p.name === policy)?.id;
|
|
118
|
+
if (!policyId) {
|
|
119
|
+
this.logger.fatal(`Policy ${policy} not found`);
|
|
120
|
+
}
|
|
121
|
+
const binding = await this.iamClient.postApiV1PolicyAssociationsRoleByRoleId(existingRole.id, { policyId }, {
|
|
122
|
+
headers: {
|
|
123
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
124
|
+
},
|
|
125
|
+
});
|
|
126
|
+
if (binding.status !== 200) {
|
|
127
|
+
this.logger.error(`Failed to bind policy ${policyId} to role ${existingRole.id}: ${binding.statusText}`);
|
|
128
|
+
}
|
|
129
|
+
this.logger.debug(`Created binding for policy ${policyId} to role ${existingRole.id}`);
|
|
130
|
+
}
|
|
131
|
+
for (const policy of toRemove) {
|
|
132
|
+
console.log(policy, alreadyLinkedPolicies.data);
|
|
133
|
+
const policyId = alreadyLinkedPolicies.data.find((p) => p.name === policy)?.id;
|
|
134
|
+
if (!policyId) {
|
|
135
|
+
this.logger.fatal(`Policy ${policy} not found`);
|
|
136
|
+
}
|
|
137
|
+
const binding = await this.iamClient.deleteApiV1PolicyAssociationsRoleByRoleId(existingRole.id, { policyId }, {
|
|
138
|
+
headers: {
|
|
139
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
142
|
+
if (binding.status !== 200) {
|
|
143
|
+
this.logger.error(`Failed to unbind policy ${policyId} from role ${existingRole.id}: ${binding.statusText}`);
|
|
144
|
+
}
|
|
145
|
+
this.logger.debug(`Removed binding for policy ${policyId} from role ${existingRole.id}`);
|
|
146
|
+
}
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
catch (error) {
|
|
150
|
+
if (typeof error === "object" && error !== null && "error" in error) {
|
|
151
|
+
const err = error;
|
|
152
|
+
this.logger.fatal(`Failed to create role with error(${err.error.status} - ${err.error.code}): ${err.error.message}`);
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
this.logger.fatal(`Failed to create role with unknown error: ${error}`);
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
async deleteRole(organizationId, role) {
|
|
160
|
+
const parsedRole = roleDto.parse(role);
|
|
161
|
+
try {
|
|
162
|
+
const roles = await this.iamClient.getApiV1RoleAssociationsOrganizationByOrganizationId(organizationId, {
|
|
163
|
+
headers: {
|
|
164
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
const existingRole = roles.data.find((r) => r.name === parsedRole.metadata.name);
|
|
168
|
+
if (!existingRole) {
|
|
169
|
+
return false;
|
|
170
|
+
}
|
|
171
|
+
const result = await this.iamClient.deleteApiV1RolesById(existingRole.id, {
|
|
172
|
+
headers: {
|
|
173
|
+
Authorization: `Bearer ${await this.getToken()}`,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
if (result.status !== 200) {
|
|
177
|
+
this.logger.fatal(`Failed to delete role: ${result.statusText}`);
|
|
178
|
+
}
|
|
179
|
+
return true;
|
|
180
|
+
}
|
|
181
|
+
catch (error) {
|
|
182
|
+
if (typeof error === "object" && error !== null && "error" in error) {
|
|
183
|
+
const err = error;
|
|
184
|
+
this.logger.fatal(`Failed to delete role with error(${err.error.status} - ${err.error.code}): ${err.error.message}`);
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
this.logger.fatal(`Failed to delete role with unknown error: ${error}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
@@ -27,6 +27,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
27
27
|
description?: string;
|
|
28
28
|
/** The principal role that can access the resource */
|
|
29
29
|
principal?: string;
|
|
30
|
+
/** If the policy is managed by flowcore */
|
|
31
|
+
flowcoreManaged?: boolean;
|
|
30
32
|
} & {
|
|
31
33
|
/** The id of the policy */
|
|
32
34
|
id: string;
|
|
@@ -58,6 +60,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
58
60
|
description?: string;
|
|
59
61
|
/** The principal role that can access the resource */
|
|
60
62
|
principal?: string;
|
|
63
|
+
/** If the policy is managed by flowcore */
|
|
64
|
+
flowcoreManaged?: boolean;
|
|
61
65
|
}, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<object, any>>;
|
|
62
66
|
/**
|
|
63
67
|
* @description Get a policy by id
|
|
@@ -123,6 +127,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
123
127
|
name: string;
|
|
124
128
|
/** Role description */
|
|
125
129
|
description?: string;
|
|
130
|
+
/** Flowcore managed role */
|
|
131
|
+
flowcoreManaged?: boolean;
|
|
126
132
|
} & {
|
|
127
133
|
/** The id of the role */
|
|
128
134
|
id: string;
|
|
@@ -142,6 +148,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
142
148
|
name: string;
|
|
143
149
|
/** Role description */
|
|
144
150
|
description?: string;
|
|
151
|
+
/** Flowcore managed role */
|
|
152
|
+
flowcoreManaged?: boolean;
|
|
145
153
|
}, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<object, any>>;
|
|
146
154
|
/**
|
|
147
155
|
* @description Get a role by ID
|
|
@@ -158,6 +166,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
158
166
|
name: string;
|
|
159
167
|
/** Role description */
|
|
160
168
|
description?: string;
|
|
169
|
+
/** Flowcore managed role */
|
|
170
|
+
flowcoreManaged?: boolean;
|
|
161
171
|
} & {
|
|
162
172
|
/** Role ID */
|
|
163
173
|
id: string;
|
|
@@ -213,6 +223,40 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
213
223
|
/** The message of the archive role */
|
|
214
224
|
message: string;
|
|
215
225
|
}, any>>;
|
|
226
|
+
/**
|
|
227
|
+
* @description Fetch associations for a policy
|
|
228
|
+
*
|
|
229
|
+
* @tags policy-associations
|
|
230
|
+
* @name GetApiV1PolicyAssociationsByPolicyId
|
|
231
|
+
* @request GET:/api/v1/policy-associations/{policyId}
|
|
232
|
+
* @secure
|
|
233
|
+
*/
|
|
234
|
+
getApiV1PolicyAssociationsByPolicyId: (policyId: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
|
|
235
|
+
keys: {
|
|
236
|
+
/** The ID of the policy */
|
|
237
|
+
policyId: string;
|
|
238
|
+
/** The ID of the organization */
|
|
239
|
+
organizationId: string;
|
|
240
|
+
/** The ID of the key */
|
|
241
|
+
keyId: string;
|
|
242
|
+
}[];
|
|
243
|
+
users: {
|
|
244
|
+
/** The ID of the policy */
|
|
245
|
+
policyId: string;
|
|
246
|
+
/** The ID of the organization */
|
|
247
|
+
organizationId: string;
|
|
248
|
+
/** The ID of the user */
|
|
249
|
+
userId: string;
|
|
250
|
+
}[];
|
|
251
|
+
roles: {
|
|
252
|
+
/** The ID of the policy */
|
|
253
|
+
policyId: string;
|
|
254
|
+
/** The ID of the organization */
|
|
255
|
+
organizationId: string;
|
|
256
|
+
/** The ID of the role */
|
|
257
|
+
roleId: string;
|
|
258
|
+
}[];
|
|
259
|
+
}, any>>;
|
|
216
260
|
/**
|
|
217
261
|
* @description Fetch policies for an organization
|
|
218
262
|
*
|
|
@@ -240,6 +284,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
240
284
|
description?: string;
|
|
241
285
|
/** The principal role that can access the resource */
|
|
242
286
|
principal?: string;
|
|
287
|
+
/** If the policy is managed by flowcore */
|
|
288
|
+
flowcoreManaged?: boolean;
|
|
243
289
|
} & {
|
|
244
290
|
/** The id of the policy */
|
|
245
291
|
id: string;
|
|
@@ -274,6 +320,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
274
320
|
description?: string;
|
|
275
321
|
/** The principal role that can access the resource */
|
|
276
322
|
principal?: string;
|
|
323
|
+
/** If the policy is managed by flowcore */
|
|
324
|
+
flowcoreManaged?: boolean;
|
|
277
325
|
} & {
|
|
278
326
|
/** The id of the policy */
|
|
279
327
|
id: string;
|
|
@@ -345,6 +393,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
345
393
|
description?: string;
|
|
346
394
|
/** The principal role that can access the resource */
|
|
347
395
|
principal?: string;
|
|
396
|
+
/** If the policy is managed by flowcore */
|
|
397
|
+
flowcoreManaged?: boolean;
|
|
348
398
|
} & {
|
|
349
399
|
/** The id of the policy */
|
|
350
400
|
id: string;
|
|
@@ -416,6 +466,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
416
466
|
description?: string;
|
|
417
467
|
/** The principal role that can access the resource */
|
|
418
468
|
principal?: string;
|
|
469
|
+
/** If the policy is managed by flowcore */
|
|
470
|
+
flowcoreManaged?: boolean;
|
|
419
471
|
} & {
|
|
420
472
|
/** The id of the policy */
|
|
421
473
|
id: string;
|
|
@@ -460,6 +512,32 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
460
512
|
/** The ID of the role */
|
|
461
513
|
roleId: string;
|
|
462
514
|
}, any>>;
|
|
515
|
+
/**
|
|
516
|
+
* @description Fetch associations for a role
|
|
517
|
+
*
|
|
518
|
+
* @tags role-associations
|
|
519
|
+
* @name GetApiV1RoleAssociationsByRoleId
|
|
520
|
+
* @request GET:/api/v1/role-associations/{roleId}
|
|
521
|
+
* @secure
|
|
522
|
+
*/
|
|
523
|
+
getApiV1RoleAssociationsByRoleId: (roleId: string, params?: RequestParams) => Promise<import("./http-client.js").HttpResponse<{
|
|
524
|
+
keys: {
|
|
525
|
+
/** The ID of the role */
|
|
526
|
+
roleId: string;
|
|
527
|
+
/** The ID of the organization */
|
|
528
|
+
organizationId: string;
|
|
529
|
+
/** The ID of the key */
|
|
530
|
+
keyId: string;
|
|
531
|
+
}[];
|
|
532
|
+
users: {
|
|
533
|
+
/** The ID of the role */
|
|
534
|
+
roleId: string;
|
|
535
|
+
/** The ID of the organization */
|
|
536
|
+
organizationId: string;
|
|
537
|
+
/** The ID of the user */
|
|
538
|
+
userId: string;
|
|
539
|
+
}[];
|
|
540
|
+
}, any>>;
|
|
463
541
|
/**
|
|
464
542
|
* @description Fetch roles for an organization
|
|
465
543
|
*
|
|
@@ -475,6 +553,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
475
553
|
name: string;
|
|
476
554
|
/** Role description */
|
|
477
555
|
description?: string;
|
|
556
|
+
/** Flowcore managed role */
|
|
557
|
+
flowcoreManaged?: boolean;
|
|
478
558
|
} & {
|
|
479
559
|
/** The id of the role */
|
|
480
560
|
id: string;
|
|
@@ -497,6 +577,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
497
577
|
name: string;
|
|
498
578
|
/** Role description */
|
|
499
579
|
description?: string;
|
|
580
|
+
/** Flowcore managed role */
|
|
581
|
+
flowcoreManaged?: boolean;
|
|
500
582
|
} & {
|
|
501
583
|
/** Role ID */
|
|
502
584
|
id: string;
|
|
@@ -556,6 +638,8 @@ export declare class Api<SecurityDataType = unknown> extends HttpClient<Security
|
|
|
556
638
|
name: string;
|
|
557
639
|
/** Role description */
|
|
558
640
|
description?: string;
|
|
641
|
+
/** Flowcore managed role */
|
|
642
|
+
flowcoreManaged?: boolean;
|
|
559
643
|
} & {
|
|
560
644
|
/** Role ID */
|
|
561
645
|
id: string;
|
|
@@ -168,6 +168,21 @@ export class Api extends HttpClient {
|
|
|
168
168
|
format: "json",
|
|
169
169
|
...params,
|
|
170
170
|
});
|
|
171
|
+
/**
|
|
172
|
+
* @description Fetch associations for a policy
|
|
173
|
+
*
|
|
174
|
+
* @tags policy-associations
|
|
175
|
+
* @name GetApiV1PolicyAssociationsByPolicyId
|
|
176
|
+
* @request GET:/api/v1/policy-associations/{policyId}
|
|
177
|
+
* @secure
|
|
178
|
+
*/
|
|
179
|
+
getApiV1PolicyAssociationsByPolicyId = (policyId, params = {}) => this.request({
|
|
180
|
+
path: `/api/v1/policy-associations/${policyId}`,
|
|
181
|
+
method: "GET",
|
|
182
|
+
secure: true,
|
|
183
|
+
format: "json",
|
|
184
|
+
...params,
|
|
185
|
+
});
|
|
171
186
|
/**
|
|
172
187
|
* @description Fetch policies for an organization
|
|
173
188
|
*
|
|
@@ -331,6 +346,21 @@ export class Api extends HttpClient {
|
|
|
331
346
|
format: "json",
|
|
332
347
|
...params,
|
|
333
348
|
});
|
|
349
|
+
/**
|
|
350
|
+
* @description Fetch associations for a role
|
|
351
|
+
*
|
|
352
|
+
* @tags role-associations
|
|
353
|
+
* @name GetApiV1RoleAssociationsByRoleId
|
|
354
|
+
* @request GET:/api/v1/role-associations/{roleId}
|
|
355
|
+
* @secure
|
|
356
|
+
*/
|
|
357
|
+
getApiV1RoleAssociationsByRoleId = (roleId, params = {}) => this.request({
|
|
358
|
+
path: `/api/v1/role-associations/${roleId}`,
|
|
359
|
+
method: "GET",
|
|
360
|
+
secure: true,
|
|
361
|
+
format: "json",
|
|
362
|
+
...params,
|
|
363
|
+
});
|
|
334
364
|
/**
|
|
335
365
|
* @description Fetch roles for an organization
|
|
336
366
|
*
|
|
@@ -25,11 +25,11 @@ export interface ApiConfig<SecurityDataType = unknown> {
|
|
|
25
25
|
securityWorker?: (securityData: SecurityDataType | null) => Promise<RequestParams | void> | RequestParams | void;
|
|
26
26
|
customFetch?: typeof fetch;
|
|
27
27
|
}
|
|
28
|
-
export interface HttpResponse<D, E = unknown> extends Response {
|
|
28
|
+
export interface HttpResponse<D extends unknown, E extends unknown = unknown> extends Response {
|
|
29
29
|
data: D;
|
|
30
30
|
error: E;
|
|
31
31
|
}
|
|
32
|
-
type CancelToken =
|
|
32
|
+
type CancelToken = Symbol | string | number;
|
|
33
33
|
export declare enum ContentType {
|
|
34
34
|
Json = "application/json",
|
|
35
35
|
FormData = "multipart/form-data",
|
|
@@ -48,9 +48,7 @@ export class HttpClient {
|
|
|
48
48
|
const query = rawQuery || {};
|
|
49
49
|
const keys = Object.keys(query).filter((key) => "undefined" !== typeof query[key]);
|
|
50
50
|
return keys
|
|
51
|
-
.map((key) => Array.isArray(query[key])
|
|
52
|
-
? this.addArrayQueryParam(query, key)
|
|
53
|
-
: this.addQueryParam(query, key))
|
|
51
|
+
.map((key) => (Array.isArray(query[key]) ? this.addArrayQueryParam(query, key) : this.addQueryParam(query, key)))
|
|
54
52
|
.join("&");
|
|
55
53
|
}
|
|
56
54
|
addQueryParams(rawQuery) {
|
|
@@ -58,12 +56,8 @@ export class HttpClient {
|
|
|
58
56
|
return queryString ? `?${queryString}` : "";
|
|
59
57
|
}
|
|
60
58
|
contentFormatters = {
|
|
61
|
-
[ContentType.Json]: (input) => input !== null && (typeof input === "object" || typeof input === "string")
|
|
62
|
-
|
|
63
|
-
: input,
|
|
64
|
-
[ContentType.Text]: (input) => input !== null && typeof input !== "string"
|
|
65
|
-
? JSON.stringify(input)
|
|
66
|
-
: input,
|
|
59
|
+
[ContentType.Json]: (input) => input !== null && (typeof input === "object" || typeof input === "string") ? JSON.stringify(input) : input,
|
|
60
|
+
[ContentType.Text]: (input) => (input !== null && typeof input !== "string" ? JSON.stringify(input) : input),
|
|
67
61
|
[ContentType.FormData]: (input) => Object.keys(input || {}).reduce((formData, key) => {
|
|
68
62
|
const property = input[key];
|
|
69
63
|
formData.append(key, property instanceof Blob
|
|
@@ -119,16 +113,10 @@ export class HttpClient {
|
|
|
119
113
|
...requestParams,
|
|
120
114
|
headers: {
|
|
121
115
|
...(requestParams.headers || {}),
|
|
122
|
-
...(type && type !== ContentType.FormData
|
|
123
|
-
? { "Content-Type": type }
|
|
124
|
-
: {}),
|
|
116
|
+
...(type && type !== ContentType.FormData ? { "Content-Type": type } : {}),
|
|
125
117
|
},
|
|
126
|
-
signal: (cancelToken
|
|
127
|
-
|
|
128
|
-
: requestParams.signal) || null,
|
|
129
|
-
body: typeof body === "undefined" || body === null
|
|
130
|
-
? null
|
|
131
|
-
: payloadFormatter(body),
|
|
118
|
+
signal: (cancelToken ? this.createAbortSignal(cancelToken) : requestParams.signal) || null,
|
|
119
|
+
body: typeof body === "undefined" || body === null ? null : payloadFormatter(body),
|
|
132
120
|
}).then(async (response) => {
|
|
133
121
|
const r = response.clone();
|
|
134
122
|
r.data = null;
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -5,16 +5,18 @@
|
|
|
5
5
|
},
|
|
6
6
|
"dependencies": {
|
|
7
7
|
"@flowcore/cli-plugin-config": "^2.2.1",
|
|
8
|
-
"@flowcore/cli-plugin-core": "^4.0
|
|
8
|
+
"@flowcore/cli-plugin-core": "^4.6.0",
|
|
9
9
|
"@oclif/core": "^4.0.21",
|
|
10
10
|
"@oclif/plugin-help": "^6",
|
|
11
11
|
"@oclif/plugin-plugins": "^5.4.7",
|
|
12
|
+
"@opentf/obj-diff": "npm:@jsr/opentf__obj-diff",
|
|
12
13
|
"dayjs": "^1.11.10",
|
|
13
14
|
"deepmerge": "^4.3.1",
|
|
14
15
|
"enquirer": "^2.4.1",
|
|
15
16
|
"graphql": "^16.8.1",
|
|
16
17
|
"graphql-request": "^6.1.0",
|
|
17
18
|
"js-yaml": "^4.1.0",
|
|
19
|
+
"json-diff": "^1.0.6",
|
|
18
20
|
"lodash": "^4.17.21",
|
|
19
21
|
"radash": "^12.1.0",
|
|
20
22
|
"uuid": "^9.0.1",
|
|
@@ -27,6 +29,7 @@
|
|
|
27
29
|
"@types/chai": "^4",
|
|
28
30
|
"@types/deepmerge": "^2.2.0",
|
|
29
31
|
"@types/js-yaml": "^4.0.9",
|
|
32
|
+
"@types/json-diff": "^1.0.3",
|
|
30
33
|
"@types/lodash": "^4.14.202",
|
|
31
34
|
"@types/mocha": "^10",
|
|
32
35
|
"@types/node": "^18",
|
|
@@ -63,6 +66,9 @@
|
|
|
63
66
|
"@oclif/plugin-plugins",
|
|
64
67
|
"@flowcore/cli-plugin-config"
|
|
65
68
|
],
|
|
69
|
+
"hooks": {
|
|
70
|
+
"register-api": "./dist/hooks/register-apply"
|
|
71
|
+
},
|
|
66
72
|
"topicSeparator": " ",
|
|
67
73
|
"topics": {
|
|
68
74
|
"iam": {
|
|
@@ -82,7 +88,7 @@
|
|
|
82
88
|
"version": "oclif readme && git add README.md",
|
|
83
89
|
"update-schema": "rover graph introspect https://graph.api.flowcore.io/graphql -o schema.gql"
|
|
84
90
|
},
|
|
85
|
-
"version": "1.
|
|
91
|
+
"version": "1.1.0",
|
|
86
92
|
"bugs": "https://github.com/flowcore-io/cli-plugin-iam/issues",
|
|
87
93
|
"keywords": [
|
|
88
94
|
"oclif"
|