@adobe/aio-cli-plugin-api-mesh 1.0.0-beta → 1.0.3-beta

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.
@@ -0,0 +1,82 @@
1
+ /*
2
+ Copyright 2021 Adobe. All rights reserved.
3
+ This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License. You may obtain a copy
5
+ of the License at http://www.apache.org/licenses/LICENSE-2.0
6
+ Unless required by applicable law or agreed to in writing, software distributed under
7
+ the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8
+ OF ANY KIND, either express or implied. See the License for the specific language
9
+ governing permissions and limitations under the License.
10
+ */
11
+
12
+ const { Command } = require('@oclif/command');
13
+ const { readFile } = require('fs/promises');
14
+
15
+ const logger = require('../../classes/logger');
16
+ const { initSdk, initRequestId, promptConfirm } = require('../../helpers');
17
+
18
+ class UpdateCommand extends Command {
19
+ static args = [{ name: 'meshId' }, { name: 'file' }];
20
+
21
+ async run() {
22
+ await initRequestId();
23
+
24
+ logger.info(`RequestId: ${global.requestId}`);
25
+
26
+ const { args } = this.parse(UpdateCommand);
27
+
28
+ if (!args.meshId || !args.file) {
29
+ this.error('Missing required args. Run aio api-mesh update --help for more info.');
30
+
31
+ return;
32
+ }
33
+
34
+ const { schemaServiceClient, imsOrgId, projectId, workspaceId } = await initSdk();
35
+ let data;
36
+
37
+ try {
38
+ data = JSON.parse(await readFile(args.file, 'utf8'));
39
+ } catch (error) {
40
+ logger.error(error);
41
+
42
+ this.log(error.message);
43
+ this.error(
44
+ 'Unable to read the mesh configuration file provided. Please check the file and try again.',
45
+ );
46
+ }
47
+
48
+ const shouldContinue = await promptConfirm(
49
+ `Are you sure you want to update the mesh: ${args.meshId}?`,
50
+ );
51
+
52
+ if (shouldContinue) {
53
+ try {
54
+ const response = await schemaServiceClient.updateMesh(
55
+ imsOrgId,
56
+ projectId,
57
+ workspaceId,
58
+ args.meshId,
59
+ data,
60
+ );
61
+
62
+ this.log('Successfully updated the mesh with the id: %s', args.meshId);
63
+
64
+ return response;
65
+ } catch (error) {
66
+ this.log(error.message);
67
+
68
+ this.error(
69
+ `Unable to update the mesh. Please check the mesh configuration file and try again. If the error persists please contact support. RequestId: ${global.requestId}`,
70
+ );
71
+ }
72
+ } else {
73
+ this.log('Update cancelled');
74
+
75
+ return 'Update cancelled';
76
+ }
77
+ }
78
+ }
79
+
80
+ UpdateCommand.description = 'Update a mesh with the given config.';
81
+
82
+ module.exports = UpdateCommand;
package/src/helpers.js CHANGED
@@ -9,88 +9,214 @@ OF ANY KIND, either express or implied. See the License for the specific languag
9
9
  governing permissions and limitations under the License.
10
10
  */
11
11
 
12
- const Config = require('@adobe/aio-lib-core-config')
13
- const { getToken, context } = require('@adobe/aio-lib-ims')
14
- const { CLI } = require('@adobe/aio-lib-ims/src/context')
15
- const fs = require('fs')
16
- const libConsoleCLI = require('@adobe/aio-cli-lib-console')
17
- const { SchemaServiceClient } = require('./classes/SchemaServiceClient')
18
- const { getCliEnv } = require('@adobe/aio-lib-env')
19
- const aioConsoleLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin-commerce-admin', { provider: 'debug' })
20
- const CONSOLE_CONFIG_KEYS = {
21
- CONSOLE: 'console',
22
- ORG: 'org'
23
- }
12
+ const fs = require('fs');
13
+ const inquirer = require('inquirer');
14
+
15
+ const Config = require('@adobe/aio-lib-core-config');
16
+ const { getToken, context } = require('@adobe/aio-lib-ims');
17
+ const { CLI } = require('@adobe/aio-lib-ims/src/context');
18
+ const libConsoleCLI = require('@adobe/aio-cli-lib-console');
19
+ const { getCliEnv } = require('@adobe/aio-lib-env');
20
+ const aioConsoleLogger = require('@adobe/aio-lib-core-logging')('@adobe/aio-cli-plugin-api-mesh', {
21
+ provider: 'debug',
22
+ });
23
+
24
+ const { SchemaServiceClient } = require('./classes/SchemaServiceClient');
25
+ const logger = require('../src/classes/logger');
26
+ const { UUID } = require('./classes/UUID');
27
+
24
28
  const CONSOLE_API_KEYS = {
25
- prod: 'aio-cli-console-auth',
26
- stage: 'aio-cli-console-auth-stage'
27
- }
29
+ prod: 'aio-cli-console-auth',
30
+ stage: 'aio-cli-console-auth-stage',
31
+ };
28
32
 
29
33
  /**
30
34
  * @returns {any} Returns a config object or null
31
35
  */
32
- async function getCommerceAdminConfig () {
33
- const configFile = Config.get('aio-cli-plugin-commerce-admin')
34
- try {
35
- const data = JSON.parse((fs.readFileSync(configFile,
36
- { encoding: 'utf8', flag: 'r' })))
37
- return {
38
- baseUrl: data.baseUrl || 'https://commerce.adobe.io',
39
- accessToken: (await getLibConsoleCLI()).accessToken,
40
- apiKey: data.apiKey
41
- }
42
- } catch (error) {
43
- return null
44
- }
36
+ async function getDevConsoleConfig() {
37
+ const configFile = Config.get('api-mesh.configPath');
38
+
39
+ if (!configFile) {
40
+ return {
41
+ baseUrl: 'https://developers.adobe.io/console',
42
+ accessToken: (await getLibConsoleCLI()).accessToken,
43
+ apiKey: 'adobe-graph-prod',
44
+ };
45
+ } else {
46
+ try {
47
+ if (!fs.existsSync(configFile)) {
48
+ throw new Error(
49
+ `Config file does not exist. Please run the command: aio config:set api-mesh.configPath <path_to_json_file> with a valid file.`,
50
+ );
51
+ }
52
+
53
+ const data = JSON.parse(fs.readFileSync(configFile, { encoding: 'utf8', flag: 'r' }));
54
+
55
+ if (!data.baseUrl || !data.apiKey) {
56
+ throw new Error(
57
+ 'Invalid config file. Please validate the file contents and try again. Config file must contain baseUrl and apiKey.',
58
+ );
59
+ }
60
+
61
+ const baseUrl = data.baseUrl.endsWith('/')
62
+ ? data.baseUrl.slice(0, data.baseUrl.length - 1)
63
+ : data.baseUrl;
64
+
65
+ return {
66
+ baseUrl: baseUrl,
67
+ accessToken: (await getLibConsoleCLI()).accessToken,
68
+ apiKey: data.apiKey,
69
+ };
70
+ } catch (error) {
71
+ logger.error(
72
+ 'Please run the command: aio config:set api-mesh.configPath <path_to_json_file> with a valid config file.',
73
+ );
74
+
75
+ throw new Error(error);
76
+ }
77
+ }
45
78
  }
46
79
 
47
80
  /**
48
81
  * @returns {string} Returns organizations the user belongs to
49
82
  */
50
- async function getAuthorizedOrganizations () {
51
- const { consoleCLI } = await getLibConsoleCLI()
52
- aioConsoleLogger.debug('Get the selected organization')
53
- const key = CONSOLE_CONFIG_KEYS.ORG
54
- this.configOrgCode = Config.get(`${CONSOLE_CONFIG_KEYS.CONSOLE}.${key}`)
55
- if (!this.configOrgCode) {
56
- const organizations = await consoleCLI.getOrganizations()
57
- const selectedOrg = await consoleCLI.promptForSelectOrganization(organizations)
58
- aioConsoleLogger.debug('Set the console config')
59
- Config.set(`${CONSOLE_CONFIG_KEYS.CONSOLE}.${key}`, { id: selectedOrg.id, code: selectedOrg.code, name: selectedOrg.name })
60
- this.imsOrgCode = selectedOrg.code
61
- return { imsOrgCode: this.imsOrgCode }
62
- } else {
63
- console.log(`Selecting your organization as: ${this.configOrgCode.name}`)
64
- return { imsOrgCode: this.configOrgCode.code }
65
- }
83
+ async function getAuthorizedOrganization() {
84
+ const { consoleCLI } = await getLibConsoleCLI();
85
+
86
+ aioConsoleLogger.debug('Get the selected organization');
87
+
88
+ const consoleConfigOrg = Config.get('console.org');
89
+
90
+ if (!consoleConfigOrg) {
91
+ const organizations = await consoleCLI.getOrganizations();
92
+ const selectedOrg = await consoleCLI.promptForSelectOrganization(organizations);
93
+
94
+ aioConsoleLogger.debug('Set the console config');
95
+
96
+ Config.set('console.org', {
97
+ id: selectedOrg.id,
98
+ code: selectedOrg.code,
99
+ name: selectedOrg.name,
100
+ });
101
+
102
+ return Object.assign({}, selectedOrg);
103
+ } else {
104
+ logger.info(`Selecting your organization as: ${consoleConfigOrg.name}`);
105
+
106
+ return Object.assign({}, consoleConfigOrg);
107
+ }
108
+ }
109
+
110
+ async function getProject(imsOrgId, imsOrgTitle) {
111
+ logger.info(`Initializing project selection for ${imsOrgId}`);
112
+
113
+ const { consoleCLI } = await getLibConsoleCLI();
114
+
115
+ const projects = await consoleCLI.getProjects(imsOrgId);
116
+ if (projects.length !== 0) {
117
+ const selectedProject = await consoleCLI.promptForSelectProject(projects);
118
+
119
+ return selectedProject;
120
+ } else {
121
+ aioConsoleLogger.error(`No projects found for the selected organization: ${imsOrgTitle}`);
122
+ }
66
123
  }
124
+
125
+ async function getWorkspace(orgId, projectId, imsOrgTitle, projectTitle) {
126
+ logger.info(`Initializing workspace selection for ${orgId} / ${projectId}`);
127
+
128
+ const { consoleCLI } = await getLibConsoleCLI();
129
+
130
+ const workspaces = await consoleCLI.getWorkspaces(orgId, projectId);
131
+ if (workspaces.length !== 0) {
132
+ const selectedWorkspace = await consoleCLI.promptForSelectWorkspace(workspaces);
133
+
134
+ return selectedWorkspace;
135
+ } else {
136
+ aioConsoleLogger.error(
137
+ `No workspaces found for the selected organization: ${imsOrgTitle} and project: ${projectTitle}`,
138
+ );
139
+ }
140
+ }
141
+
67
142
  /**
68
143
  * @private
69
144
  */
70
- async function getLibConsoleCLI () {
71
- await context.setCli({ 'cli.bare-output': true }, false)
72
- const clientEnv = getCliEnv()
73
- this.accessToken = await getToken(CLI)
74
- this.consoleCLI = await libConsoleCLI.init({ accessToken: this.accessToken, apiKey: CONSOLE_API_KEYS[clientEnv], env: clientEnv })
75
- return { consoleCLI: this.consoleCLI, accessToken: this.accessToken }
145
+ async function getLibConsoleCLI() {
146
+ await context.setCli({ 'cli.bare-output': true }, false);
147
+
148
+ const clientEnv = getCliEnv();
149
+
150
+ const accessToken = await getToken(CLI);
151
+
152
+ const consoleCLI = await libConsoleCLI.init({
153
+ accessToken: accessToken,
154
+ apiKey: CONSOLE_API_KEYS[clientEnv],
155
+ env: clientEnv,
156
+ });
157
+
158
+ return { consoleCLI: consoleCLI, accessToken: accessToken };
76
159
  }
77
160
 
78
161
  /**
79
162
  * @returns {any} Returns an object with properties ready for consumption
80
163
  */
81
- async function initSdk () {
82
- const { imsOrgCode } = await getAuthorizedOrganizations()
83
- console.log('Initialized user login and the selected organization')
84
- const { baseUrl, accessToken, apiKey } = await getCommerceAdminConfig()
85
- const schemaServiceClient = new SchemaServiceClient()
86
- schemaServiceClient.init(baseUrl, accessToken, apiKey)
87
- return {
88
- schemaServiceClient: schemaServiceClient,
89
- imsOrgCode: imsOrgCode
90
- }
164
+ async function initSdk() {
165
+ const org = await getAuthorizedOrganization();
166
+ const project = await getProject(org.id, org.name);
167
+ const workspace = await getWorkspace(org.id, project.id, org.name, project.title);
168
+
169
+ aioConsoleLogger.log(
170
+ `Initializing SDK for org: ${org.name}, project: ${project.title} and workspace: ${workspace.title}`,
171
+ );
172
+
173
+ logger.info('Initialized user login and the selected organization');
174
+
175
+ const { baseUrl, accessToken, apiKey } = await getDevConsoleConfig();
176
+
177
+ const schemaServiceClient = new SchemaServiceClient();
178
+ schemaServiceClient.init(baseUrl, accessToken, apiKey);
179
+
180
+ return {
181
+ schemaServiceClient: schemaServiceClient,
182
+ imsOrgId: org.id,
183
+ projectId: project.id,
184
+ workspaceId: workspace.id,
185
+ };
186
+ }
187
+
188
+ /**
189
+ * Generates a static global requestid for the lifecycle of this command request
190
+ */
191
+ async function initRequestId() {
192
+ global.requestId = UUID.newUuid().toString();
91
193
  }
92
194
 
93
- module.exports = {
94
- getCommerceAdminConfig,
95
- initSdk
195
+ /**
196
+ * Function to run the CLI Y/N prompt to confirm the user's action
197
+ *
198
+ * @param {string} message
199
+ *
200
+ * @returns boolean
201
+ */
202
+ async function promptConfirm(message) {
203
+ const prompt = inquirer.createPromptModule({ output: process.stderr });
204
+
205
+ const confirm = await prompt([
206
+ {
207
+ type: 'confirm',
208
+ name: 'res',
209
+ message,
210
+ },
211
+ ]);
212
+
213
+ return confirm.res;
96
214
  }
215
+
216
+ module.exports = {
217
+ promptConfirm,
218
+ getLibConsoleCLI,
219
+ getDevConsoleConfig,
220
+ initSdk,
221
+ initRequestId,
222
+ };
package/src/utils.js ADDED
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Returns the string representation of the object's path.
3
+ * If the path evaluates to false, the default string is returned.
4
+ *
5
+ * @param {object} obj
6
+ * @param {array<string>} path
7
+ * @param {string} defaultString
8
+ *
9
+ * @returns {string}
10
+ */
11
+ function objToString(obj, path, defaultString = '') {
12
+ try {
13
+ // Cache the current object
14
+ let current = obj;
15
+
16
+ // For each item in the path, dig into the object
17
+ for (let i = 0; i < path.length; i++) {
18
+ // If the item isn't found, return the default (or null)
19
+ if (!current[path[i]]) return defaultString;
20
+
21
+ // Otherwise, update the current value
22
+ current = current[path[i]];
23
+ }
24
+
25
+ if (typeof current === 'string') {
26
+ return current;
27
+ } else if (typeof current === 'object') {
28
+ return JSON.stringify(current, null, 2);
29
+ } else {
30
+ return defaultString;
31
+ }
32
+ } catch (error) {
33
+ return defaultString;
34
+ }
35
+ }
36
+
37
+ module.exports = {
38
+ objToString,
39
+ };
@@ -1,42 +0,0 @@
1
- /*
2
- Copyright 2021 Adobe. All rights reserved.
3
- This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- you may not use this file except in compliance with the License. You may obtain a copy
5
- of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- Unless required by applicable law or agreed to in writing, software distributed under
7
- the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8
- OF ANY KIND, either express or implied. See the License for the specific language
9
- governing permissions and limitations under the License.
10
- */
11
-
12
- const { Command } = require('@oclif/command')
13
- const { readFile } = require('fs/promises')
14
- const { initSdk } = require('../../../helpers')
15
-
16
- class CreateCommand extends Command {
17
- static args = [
18
- { name: 'file' }
19
- ]
20
-
21
- async run () {
22
- console.log('Start create tenant')
23
- const { args } = this.parse(CreateCommand)
24
- const { schemaServiceClient, imsOrgCode } = await initSdk()
25
- let data
26
- try {
27
- data = JSON.parse(await readFile(args.file, 'utf8'))
28
- } catch (error) {
29
- this.error('Unable to create a tenant with the given configuration')
30
- }
31
- data.imsOrgId = imsOrgCode
32
- const tenant = await schemaServiceClient.createTenant(data)
33
- tenant
34
- ? this.log(`Successfully created a tenant with the ID: ${data.tenantId} and imsOrgCode: ${data.imsOrgId}`)
35
- : this.error(`Unable to create a tenant with the ID ${data.tenantId}`)
36
- return tenant
37
- }
38
- }
39
-
40
- CreateCommand.description = 'Create a tenant with the given config.'
41
-
42
- module.exports = CreateCommand
@@ -1,33 +0,0 @@
1
- /*
2
- Copyright 2021 Adobe. All rights reserved.
3
- This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- you may not use this file except in compliance with the License. You may obtain a copy
5
- of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- Unless required by applicable law or agreed to in writing, software distributed under
7
- the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8
- OF ANY KIND, either express or implied. See the License for the specific language
9
- governing permissions and limitations under the License.
10
- */
11
-
12
- const { Command } = require('@oclif/command')
13
- const { initSdk } = require('../../../helpers')
14
-
15
- class GetCommand extends Command {
16
- static args = [
17
- { name: 'tenantId' }
18
- ]
19
-
20
- async run () {
21
- const { args } = this.parse(GetCommand)
22
- const { schemaServiceClient, imsOrgCode } = await initSdk()
23
- const tenant = await schemaServiceClient.getTenant(args.tenantId, imsOrgCode)
24
- tenant
25
- ? this.log(JSON.stringify(tenant))
26
- : this.error(`Unable to retrieve the tenant config for ${args.tenantId}`)
27
- return tenant
28
- }
29
- }
30
-
31
- GetCommand.description = 'Get the config of a given tenant'
32
-
33
- module.exports = GetCommand
@@ -1,42 +0,0 @@
1
- /*
2
- Copyright 2021 Adobe. All rights reserved.
3
- This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- you may not use this file except in compliance with the License. You may obtain a copy
5
- of the License at http://www.apache.org/licenses/LICENSE-2.0
6
- Unless required by applicable law or agreed to in writing, software distributed under
7
- the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
8
- OF ANY KIND, either express or implied. See the License for the specific language
9
- governing permissions and limitations under the License.
10
- */
11
-
12
- const { Command } = require('@oclif/command')
13
- const { readFile } = require('fs/promises')
14
- const { initSdk } = require('../../../helpers')
15
-
16
- class UpdateCommand extends Command {
17
- static args = [
18
- { name: 'tenantId' },
19
- { name: 'file' }
20
- ]
21
-
22
- async run () {
23
- const { args } = this.parse(UpdateCommand)
24
- const { schemaServiceClient, imsOrgCode } = await initSdk()
25
- let data
26
- try {
27
- data = JSON.parse(await readFile(args.file, 'utf8'))
28
- } catch (error) {
29
- this.error('Unable to update the tenant with the given configuration')
30
- }
31
- data.imsOrgId = imsOrgCode
32
- const tenant = await schemaServiceClient.updateTenant(args.tenantId, data)
33
- tenant
34
- ? this.log(`Successfully updated the tenant with the id: ${data.tenantId}`)
35
- : this.log(`Unable to update the tenant with the id: ${data.tenantId}`)
36
- return tenant
37
- }
38
- }
39
-
40
- UpdateCommand.description = 'Update a tenant with the given config.'
41
-
42
- module.exports = UpdateCommand