@adobe/aio-cli-plugin-api-mesh 2.0.0 → 2.2.0-beta.1
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/oclif.manifest.json +1 -1
- package/package.json +5 -3
- package/src/commands/__fixtures__/env_invalid +8 -0
- package/src/commands/__fixtures__/env_valid +3 -0
- package/src/commands/__fixtures__/files/requestParams.json +3 -0
- package/src/commands/__fixtures__/openapi-schema.json +4 -0
- package/src/commands/__fixtures__/requestParams.json +3 -0
- package/src/commands/__fixtures__/sample_fully_qualified_mesh.json +29 -0
- package/src/commands/__fixtures__/sample_invalid_mesh.txt +17 -0
- package/src/commands/__fixtures__/sample_mesh_files.json +23 -0
- package/src/commands/__fixtures__/sample_mesh_invalid_file_content.json +14 -0
- package/src/commands/__fixtures__/sample_mesh_invalid_file_name.json +27 -0
- package/src/commands/__fixtures__/sample_mesh_invalid_paths.json +23 -0
- package/src/commands/__fixtures__/sample_mesh_invalid_type.json +27 -0
- package/src/commands/__fixtures__/sample_mesh_mismatching_path.json +29 -0
- package/src/commands/__fixtures__/sample_mesh_outside_workspace_dir.json +23 -0
- package/src/commands/__fixtures__/sample_mesh_path_from_home.json +14 -0
- package/src/commands/__fixtures__/sample_mesh_subdirectory.json +23 -0
- package/src/commands/__fixtures__/sample_mesh_with_files_array.json +29 -0
- package/src/commands/__fixtures__/sample_mesh_with_placeholder +17 -0
- package/src/commands/api-mesh/__tests__/create.test.js +1334 -140
- package/src/commands/api-mesh/__tests__/delete.test.js +3 -3
- package/src/commands/api-mesh/__tests__/init.test.js +390 -0
- package/src/commands/api-mesh/__tests__/update.test.js +524 -109
- package/src/commands/api-mesh/create.js +47 -14
- package/src/commands/api-mesh/init.js +168 -0
- package/src/commands/api-mesh/update.js +49 -17
- package/src/helpers.js +254 -3
- package/src/lib/devConsole.js +1 -2
- package/src/templates/gitignore +1 -0
- package/src/templates/package.json +38 -0
- package/src/utils.js +337 -33
|
@@ -10,20 +10,26 @@ governing permissions and limitations under the License.
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
const { Command } = require('@oclif/core');
|
|
13
|
-
const { readFile } = require('fs/promises');
|
|
14
13
|
|
|
15
|
-
const { initSdk, initRequestId, promptConfirm } = require('../../helpers');
|
|
14
|
+
const { initSdk, initRequestId, promptConfirm, importFiles } = require('../../helpers');
|
|
16
15
|
const logger = require('../../classes/logger');
|
|
17
16
|
const CONSTANTS = require('../../constants');
|
|
18
|
-
const {
|
|
17
|
+
const {
|
|
18
|
+
ignoreCacheFlag,
|
|
19
|
+
autoConfirmActionFlag,
|
|
20
|
+
jsonFlag,
|
|
21
|
+
getFilesInMeshConfig,
|
|
22
|
+
envFileFlag,
|
|
23
|
+
checkPlaceholders,
|
|
24
|
+
readFileContents,
|
|
25
|
+
validateAndInterpolateMesh,
|
|
26
|
+
} = require('../../utils');
|
|
19
27
|
const {
|
|
20
28
|
createMesh,
|
|
21
29
|
createAPIMeshCredentials,
|
|
22
30
|
subscribeCredentialToMeshService,
|
|
23
31
|
} = require('../../lib/devConsole');
|
|
24
32
|
|
|
25
|
-
require('dotenv').config();
|
|
26
|
-
|
|
27
33
|
const { MULTITENANT_GRAPHQL_SERVER_BASE_URL } = CONSTANTS;
|
|
28
34
|
|
|
29
35
|
class CreateCommand extends Command {
|
|
@@ -32,6 +38,7 @@ class CreateCommand extends Command {
|
|
|
32
38
|
ignoreCache: ignoreCacheFlag,
|
|
33
39
|
autoConfirmAction: autoConfirmActionFlag,
|
|
34
40
|
json: jsonFlag,
|
|
41
|
+
env: envFileFlag,
|
|
35
42
|
};
|
|
36
43
|
|
|
37
44
|
static enableJsonFlag = true;
|
|
@@ -51,22 +58,47 @@ class CreateCommand extends Command {
|
|
|
51
58
|
|
|
52
59
|
const ignoreCache = await flags.ignoreCache;
|
|
53
60
|
const autoConfirmAction = await flags.autoConfirmAction;
|
|
54
|
-
|
|
61
|
+
const envFilePath = await flags.env;
|
|
55
62
|
const { imsOrgId, projectId, workspaceId } = await initSdk({
|
|
56
63
|
ignoreCache,
|
|
57
64
|
});
|
|
58
65
|
|
|
66
|
+
//Input the mesh data from the input file
|
|
67
|
+
let inputMeshData = await readFileContents(args.file, this, 'mesh');
|
|
68
|
+
|
|
59
69
|
let data;
|
|
60
70
|
|
|
71
|
+
if (checkPlaceholders(inputMeshData)) {
|
|
72
|
+
this.log('The provided mesh contains placeholders. Starting mesh interpolation process.');
|
|
73
|
+
data = await validateAndInterpolateMesh(inputMeshData, envFilePath, this);
|
|
74
|
+
} else {
|
|
75
|
+
try {
|
|
76
|
+
data = JSON.parse(inputMeshData);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
this.log(err.message);
|
|
79
|
+
this.error('Input mesh file is not a valid JSON. Please check the file provided.');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let filesList = [];
|
|
84
|
+
|
|
61
85
|
try {
|
|
62
|
-
|
|
63
|
-
} catch (
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
86
|
+
filesList = getFilesInMeshConfig(data, args.file);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
this.log(err.message);
|
|
89
|
+
this.error('Input mesh config is not valid.');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// if local files are present, import them in files array in meshConfig
|
|
93
|
+
if (filesList.length) {
|
|
94
|
+
try {
|
|
95
|
+
data = await importFiles(data, filesList, args.file, flags.autoConfirmAction);
|
|
96
|
+
} catch (err) {
|
|
97
|
+
this.log(err.message);
|
|
98
|
+
this.error(
|
|
99
|
+
'Unable to import the files in the mesh config. Please check the file and try again.',
|
|
100
|
+
);
|
|
101
|
+
}
|
|
70
102
|
}
|
|
71
103
|
|
|
72
104
|
let shouldContinue = true;
|
|
@@ -78,6 +110,7 @@ class CreateCommand extends Command {
|
|
|
78
110
|
if (shouldContinue) {
|
|
79
111
|
try {
|
|
80
112
|
const mesh = await createMesh(imsOrgId, projectId, workspaceId, data);
|
|
113
|
+
|
|
81
114
|
let sdkList = [];
|
|
82
115
|
|
|
83
116
|
if (mesh) {
|
|
@@ -0,0 +1,168 @@
|
|
|
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, Flags } = require('@oclif/core');
|
|
13
|
+
const resolve = require('path').resolve;
|
|
14
|
+
|
|
15
|
+
const { promptConfirm, promptSelect, runCliCommand } = require('../../helpers');
|
|
16
|
+
const { getAppRootDir } = require('../../utils');
|
|
17
|
+
|
|
18
|
+
const fs = require('fs/promises');
|
|
19
|
+
|
|
20
|
+
class InitCommand extends Command {
|
|
21
|
+
static summary = 'Initiate API Mesh workspace';
|
|
22
|
+
static description =
|
|
23
|
+
'This command will create a workspace where you can organise your API mesh configuration and other files';
|
|
24
|
+
|
|
25
|
+
static args = [
|
|
26
|
+
{
|
|
27
|
+
name: 'projectName',
|
|
28
|
+
required: true,
|
|
29
|
+
description: 'Project name',
|
|
30
|
+
},
|
|
31
|
+
];
|
|
32
|
+
|
|
33
|
+
static flags = {
|
|
34
|
+
path: Flags.string({
|
|
35
|
+
char: 'p',
|
|
36
|
+
summary: 'workspace path',
|
|
37
|
+
default: '.',
|
|
38
|
+
}),
|
|
39
|
+
packageManager: Flags.string({
|
|
40
|
+
char: 'm',
|
|
41
|
+
summary: 'select yarn or npm for package management',
|
|
42
|
+
options: ['npm', 'yarn'],
|
|
43
|
+
}),
|
|
44
|
+
git: Flags.string({
|
|
45
|
+
char: 'g',
|
|
46
|
+
summary: 'Should the workspace be initiated as a git project.',
|
|
47
|
+
options: ['y', 'n'],
|
|
48
|
+
}),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
static enableJsonFlag = true;
|
|
52
|
+
|
|
53
|
+
static examples = [
|
|
54
|
+
{
|
|
55
|
+
description: 'API mesh workspace init',
|
|
56
|
+
command: 'aio api-mesh init commerce-mesh',
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
description: 'API mesh workspace init with flags',
|
|
60
|
+
command:
|
|
61
|
+
'aio api-mesh init commerce-mesh --path ./mesh_projects/test_mesh --git y --packageManager yarn',
|
|
62
|
+
},
|
|
63
|
+
];
|
|
64
|
+
|
|
65
|
+
async createPackageJson(templatePath, filePath, projectTitle = 'api-mesh-starter') {
|
|
66
|
+
const template = await fs.readFile(templatePath, 'utf8');
|
|
67
|
+
|
|
68
|
+
const pkgJSON = { ...JSON.parse(template), name: projectTitle };
|
|
69
|
+
|
|
70
|
+
await fs.writeFile(filePath, JSON.stringify(pkgJSON, null, 2), 'utf8', { mode: 'w' });
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
async run() {
|
|
74
|
+
const { args, flags } = await this.parse(InitCommand);
|
|
75
|
+
const gitFlagOptions = {
|
|
76
|
+
y: true,
|
|
77
|
+
n: false,
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
let absolutePath = resolve(flags.path);
|
|
81
|
+
let shouldCreateGit = gitFlagOptions[flags.git];
|
|
82
|
+
let packageManagerChoice = flags.packageManager;
|
|
83
|
+
const packageJsonTemplate = `${getAppRootDir()}/src/templates/package.json`;
|
|
84
|
+
const shouldCreateWorkspace = await promptConfirm(
|
|
85
|
+
`Do you want to create the workspace in ${absolutePath}`,
|
|
86
|
+
);
|
|
87
|
+
|
|
88
|
+
if (shouldCreateWorkspace) {
|
|
89
|
+
if (shouldCreateGit === undefined) {
|
|
90
|
+
shouldCreateGit = await promptConfirm(`Do you want to initiate git in your workspace?`);
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
if (packageManagerChoice === undefined) {
|
|
94
|
+
packageManagerChoice = await promptSelect(`Select a package manager`, [
|
|
95
|
+
{ name: 'npm', value: 'npm' },
|
|
96
|
+
{ name: 'yarn', value: 'yarn' },
|
|
97
|
+
]);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
try {
|
|
101
|
+
await fs.access(absolutePath);
|
|
102
|
+
if (
|
|
103
|
+
!(await promptConfirm(
|
|
104
|
+
'The directory is not empty. Do you want to create a sub directory with project name',
|
|
105
|
+
))
|
|
106
|
+
) {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
absolutePath += '/' + args.projectName;
|
|
110
|
+
} catch (err) {
|
|
111
|
+
// No action needed
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
this.log(`Creating workspace in ${absolutePath}`);
|
|
115
|
+
|
|
116
|
+
try {
|
|
117
|
+
await fs.mkdir(absolutePath);
|
|
118
|
+
} catch (error) {
|
|
119
|
+
this.error(`Could not create directory ${error.message}`);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (shouldCreateGit) {
|
|
123
|
+
this.log('Initiating git in workspace');
|
|
124
|
+
try {
|
|
125
|
+
await runCliCommand('git init', absolutePath);
|
|
126
|
+
|
|
127
|
+
const gitIgnoreTemplate = `${getAppRootDir()}/src/templates/gitignore`;
|
|
128
|
+
|
|
129
|
+
await fs.writeFile(`${absolutePath}/.gitignore`, gitIgnoreTemplate, 'utf8', {
|
|
130
|
+
mode: 'w',
|
|
131
|
+
});
|
|
132
|
+
} catch (error) {
|
|
133
|
+
this.error(error);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
await fs.writeFile(`${absolutePath}/.env`, '', 'utf8', { mode: 'w' });
|
|
138
|
+
|
|
139
|
+
this.log(`Installing dependencies`);
|
|
140
|
+
|
|
141
|
+
await this.createPackageJson(
|
|
142
|
+
packageJsonTemplate,
|
|
143
|
+
`${absolutePath}/package.json`,
|
|
144
|
+
args.projectName,
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
if (packageManagerChoice === 'npm') {
|
|
148
|
+
try {
|
|
149
|
+
await runCliCommand(`npm install`, absolutePath);
|
|
150
|
+
} catch (error) {
|
|
151
|
+
this.error(error);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
if (packageManagerChoice === 'yarn') {
|
|
156
|
+
try {
|
|
157
|
+
await runCliCommand(`yarn install`, absolutePath);
|
|
158
|
+
} catch (error) {
|
|
159
|
+
this.error(error);
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
this.log('workspace setup done successfully');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = InitCommand;
|
|
@@ -10,20 +10,26 @@ governing permissions and limitations under the License.
|
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
12
|
const { Command } = require('@oclif/command');
|
|
13
|
-
const { readFile } = require('fs/promises');
|
|
14
13
|
|
|
15
14
|
const logger = require('../../classes/logger');
|
|
16
|
-
const { initSdk, initRequestId, promptConfirm } = require('../../helpers');
|
|
17
|
-
const {
|
|
15
|
+
const { initSdk, initRequestId, promptConfirm, importFiles } = require('../../helpers');
|
|
16
|
+
const {
|
|
17
|
+
ignoreCacheFlag,
|
|
18
|
+
autoConfirmActionFlag,
|
|
19
|
+
envFileFlag,
|
|
20
|
+
checkPlaceholders,
|
|
21
|
+
readFileContents,
|
|
22
|
+
validateAndInterpolateMesh,
|
|
23
|
+
getFilesInMeshConfig,
|
|
24
|
+
} = require('../../utils');
|
|
18
25
|
const { getMeshId, updateMesh } = require('../../lib/devConsole');
|
|
19
26
|
|
|
20
|
-
require('dotenv').config();
|
|
21
|
-
|
|
22
27
|
class UpdateCommand extends Command {
|
|
23
28
|
static args = [{ name: 'file' }];
|
|
24
29
|
static flags = {
|
|
25
30
|
ignoreCache: ignoreCacheFlag,
|
|
26
31
|
autoConfirmAction: autoConfirmActionFlag,
|
|
32
|
+
env: envFileFlag,
|
|
27
33
|
};
|
|
28
34
|
|
|
29
35
|
async run() {
|
|
@@ -41,23 +47,14 @@ class UpdateCommand extends Command {
|
|
|
41
47
|
|
|
42
48
|
const ignoreCache = await flags.ignoreCache;
|
|
43
49
|
const autoConfirmAction = await flags.autoConfirmAction;
|
|
50
|
+
const envFilePath = await flags.env;
|
|
44
51
|
|
|
45
52
|
const { imsOrgId, projectId, workspaceId } = await initSdk({
|
|
46
53
|
ignoreCache,
|
|
47
54
|
});
|
|
48
55
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
try {
|
|
52
|
-
data = JSON.parse(await readFile(args.file, 'utf8'));
|
|
53
|
-
} catch (error) {
|
|
54
|
-
logger.error(error);
|
|
55
|
-
|
|
56
|
-
this.log(error.message);
|
|
57
|
-
this.error(
|
|
58
|
-
'Unable to read the mesh configuration file provided. Please check the file and try again.',
|
|
59
|
-
);
|
|
60
|
-
}
|
|
56
|
+
//Input the mesh data from the input file
|
|
57
|
+
let inputMeshData = await readFileContents(args.file, this, 'mesh');
|
|
61
58
|
|
|
62
59
|
let meshId = null;
|
|
63
60
|
|
|
@@ -69,6 +66,41 @@ class UpdateCommand extends Command {
|
|
|
69
66
|
);
|
|
70
67
|
}
|
|
71
68
|
|
|
69
|
+
let data;
|
|
70
|
+
|
|
71
|
+
if (checkPlaceholders(inputMeshData)) {
|
|
72
|
+
this.log('The provided mesh contains placeholders. Starting mesh interpolation process.');
|
|
73
|
+
data = await validateAndInterpolateMesh(inputMeshData, envFilePath, this);
|
|
74
|
+
} else {
|
|
75
|
+
try {
|
|
76
|
+
data = JSON.parse(inputMeshData);
|
|
77
|
+
} catch (err) {
|
|
78
|
+
this.log(err.message);
|
|
79
|
+
this.error('Input mesh file is not a valid JSON. Please check the file provided.');
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
let filesList = [];
|
|
84
|
+
|
|
85
|
+
try {
|
|
86
|
+
filesList = getFilesInMeshConfig(data, args.file);
|
|
87
|
+
} catch (err) {
|
|
88
|
+
this.log(err.message);
|
|
89
|
+
this.error('Input mesh config is not valid.');
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// if local files are present, import them in files array in meshConfig
|
|
93
|
+
if (filesList.length) {
|
|
94
|
+
try {
|
|
95
|
+
data = await importFiles(data, filesList, args.file, flags.autoConfirmAction);
|
|
96
|
+
} catch (err) {
|
|
97
|
+
this.log(err.message);
|
|
98
|
+
this.error(
|
|
99
|
+
'Unable to import the files in the mesh config. Please check the file and try again.',
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
72
104
|
if (meshId) {
|
|
73
105
|
let shouldContinue = true;
|
|
74
106
|
|
package/src/helpers.js
CHANGED
|
@@ -12,7 +12,6 @@ governing permissions and limitations under the License.
|
|
|
12
12
|
|
|
13
13
|
const fs = require('fs');
|
|
14
14
|
const inquirer = require('inquirer');
|
|
15
|
-
|
|
16
15
|
const Config = require('@adobe/aio-lib-core-config');
|
|
17
16
|
const { getToken, context } = require('@adobe/aio-lib-ims');
|
|
18
17
|
const { CLI } = require('@adobe/aio-lib-ims/src/context');
|
|
@@ -22,10 +21,48 @@ const { getCliEnv } = require('@adobe/aio-lib-env');
|
|
|
22
21
|
const logger = require('../src/classes/logger');
|
|
23
22
|
const { UUID } = require('./classes/UUID');
|
|
24
23
|
const CONSTANTS = require('./constants');
|
|
25
|
-
const
|
|
24
|
+
const path = require('path');
|
|
25
|
+
const { exec } = require('child_process');
|
|
26
|
+
const { stdout, stderr } = require('process');
|
|
27
|
+
const jsmin = require('jsmin').jsmin;
|
|
26
28
|
|
|
27
29
|
const { DEV_CONSOLE_BASE_URL, DEV_CONSOLE_API_KEY, AIO_CLI_API_KEY } = CONSTANTS;
|
|
28
30
|
|
|
31
|
+
/**
|
|
32
|
+
* Returns the string representation of the object's path.
|
|
33
|
+
* If the path evaluates to false, the default string is returned.
|
|
34
|
+
*
|
|
35
|
+
* @param {object} obj
|
|
36
|
+
* @param {Array<string>} path
|
|
37
|
+
* @param {string} defaultString
|
|
38
|
+
* @returns {string}
|
|
39
|
+
*/
|
|
40
|
+
function objToString(obj, path = [], defaultString = '') {
|
|
41
|
+
try {
|
|
42
|
+
// Cache the current object
|
|
43
|
+
let current = obj;
|
|
44
|
+
|
|
45
|
+
// For each item in the path, dig into the object
|
|
46
|
+
for (let i = 0; i < path.length; i++) {
|
|
47
|
+
// If the item isn't found, return the default (or null)
|
|
48
|
+
if (!current[path[i]]) return defaultString;
|
|
49
|
+
|
|
50
|
+
// Otherwise, update the current value
|
|
51
|
+
current = current[path[i]];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
if (typeof current === 'string') {
|
|
55
|
+
return current;
|
|
56
|
+
} else if (typeof current === 'object') {
|
|
57
|
+
return JSON.stringify(current, null, 2);
|
|
58
|
+
} else {
|
|
59
|
+
return defaultString;
|
|
60
|
+
}
|
|
61
|
+
} catch (error) {
|
|
62
|
+
return defaultString;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
29
66
|
/**
|
|
30
67
|
* @param configFilePath
|
|
31
68
|
*/
|
|
@@ -311,7 +348,7 @@ const selectWorkspace = async (orgId, projectId, imsOrgTitle, projectTitle) => {
|
|
|
311
348
|
throw new Error('No workspace selected');
|
|
312
349
|
}
|
|
313
350
|
} else {
|
|
314
|
-
|
|
351
|
+
throw new Error(
|
|
315
352
|
'No workspaces found for the selected organization: ' +
|
|
316
353
|
imsOrgTitle +
|
|
317
354
|
' and project: ' +
|
|
@@ -459,7 +496,217 @@ async function promptInput(message) {
|
|
|
459
496
|
return selected.item;
|
|
460
497
|
}
|
|
461
498
|
|
|
499
|
+
/**
|
|
500
|
+
* Import the files in the files array in meshConfig
|
|
501
|
+
*
|
|
502
|
+
* @param data MeshConfig
|
|
503
|
+
* @param filesList List of files in meshConfig
|
|
504
|
+
* @param meshConfigName MeshConfigName
|
|
505
|
+
* @param autoConfirmActionFlag The user won't be prompted any questions, if this flag is set
|
|
506
|
+
*/
|
|
507
|
+
async function importFiles(data, filesListArray, meshConfigName, autoConfirmActionFlag) {
|
|
508
|
+
//if autoConfirmActionFlag is passed in the command, it should override by default
|
|
509
|
+
let shouldOverride = true;
|
|
510
|
+
let filesNotFound = [];
|
|
511
|
+
let filesPathMap = new Map();
|
|
512
|
+
let filesListMap = new Map(
|
|
513
|
+
filesListArray.map(ele => {
|
|
514
|
+
return [ele];
|
|
515
|
+
}),
|
|
516
|
+
);
|
|
517
|
+
|
|
518
|
+
//copy the meshConfig data
|
|
519
|
+
let resultData = data;
|
|
520
|
+
|
|
521
|
+
//array of {file to be overridden, overrideIndex}
|
|
522
|
+
let overrideArr = [];
|
|
523
|
+
|
|
524
|
+
if (data.meshConfig.files) {
|
|
525
|
+
for (let i = 0; i < data.meshConfig.files?.length; i++) {
|
|
526
|
+
filesPathMap.set(data.meshConfig.files[i].path, i);
|
|
527
|
+
}
|
|
528
|
+
}
|
|
529
|
+
|
|
530
|
+
for (let file of filesListMap.keys()) {
|
|
531
|
+
//if file exists in files array
|
|
532
|
+
if (filesPathMap.has(file)) {
|
|
533
|
+
//if file exists in files array, then override
|
|
534
|
+
if (fs.existsSync(path.resolve(path.dirname(meshConfigName), file))) {
|
|
535
|
+
if (!autoConfirmActionFlag) {
|
|
536
|
+
let index = filesPathMap.get(file);
|
|
537
|
+
overrideArr.push({ fileName: file, index: index });
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
} else {
|
|
541
|
+
//if file does not exist in files array, but exists in filesystem, we append
|
|
542
|
+
if (fs.existsSync(path.resolve(path.dirname(meshConfigName), file))) {
|
|
543
|
+
resultData = updateFilesArray(resultData, file, meshConfigName, -1);
|
|
544
|
+
} else {
|
|
545
|
+
filesNotFound.push(file);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (filesNotFound.length) {
|
|
551
|
+
for (let i = 0; i < filesNotFound.length; i++) {
|
|
552
|
+
filesNotFound[i] = path.basename(filesNotFound[i]);
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
throw new Error(
|
|
556
|
+
`Please make sure the file(s): ${filesNotFound.join(', ')} and ${path.basename(
|
|
557
|
+
meshConfigName,
|
|
558
|
+
)} are in the same directory/subdirectory`,
|
|
559
|
+
);
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
for (let i = 0; i < overrideArr.length; i++) {
|
|
563
|
+
shouldOverride = await promptConfirm(
|
|
564
|
+
`Do you want to override the ${path.basename(overrideArr[i].fileName)} file?`,
|
|
565
|
+
);
|
|
566
|
+
|
|
567
|
+
if (shouldOverride) {
|
|
568
|
+
resultData = updateFilesArray(
|
|
569
|
+
resultData,
|
|
570
|
+
overrideArr[i].fileName,
|
|
571
|
+
meshConfigName,
|
|
572
|
+
overrideArr[i].index,
|
|
573
|
+
);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
return resultData;
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
/**loads the pupa module dynamically and then interpolates the raw data from mesh file with object data
|
|
581
|
+
* @param {data}
|
|
582
|
+
* @param {obj}
|
|
583
|
+
* @returns {object} having interpolationStatus, missingKeys and interpolatedMesh
|
|
584
|
+
*/
|
|
585
|
+
|
|
586
|
+
async function interpolateMesh(data, obj) {
|
|
587
|
+
let missingKeys = new Set();
|
|
588
|
+
let interpolatedMesh;
|
|
589
|
+
let pupa;
|
|
590
|
+
try {
|
|
591
|
+
pupa = (await import('pupa')).default;
|
|
592
|
+
} catch {
|
|
593
|
+
throw new Error('Error while loading pupa module');
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
interpolatedMesh = pupa(data, obj, {
|
|
597
|
+
ignoreMissing: true,
|
|
598
|
+
transform: ({ value, key }) => {
|
|
599
|
+
if (key.startsWith('env.')) {
|
|
600
|
+
if (value) {
|
|
601
|
+
return value;
|
|
602
|
+
} else {
|
|
603
|
+
// missing value, add to list
|
|
604
|
+
missingKeys.add(key.split('.')[1]);
|
|
605
|
+
}
|
|
606
|
+
} else {
|
|
607
|
+
//ignore
|
|
608
|
+
return undefined;
|
|
609
|
+
}
|
|
610
|
+
return value;
|
|
611
|
+
},
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
if (missingKeys.size) {
|
|
615
|
+
return {
|
|
616
|
+
interpolationStatus: 'failed',
|
|
617
|
+
missingKeys: Array.from(missingKeys),
|
|
618
|
+
interpolatedMesh: '',
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
return {
|
|
622
|
+
interpolationStatus: 'success',
|
|
623
|
+
missingKeys: [],
|
|
624
|
+
interpolatedMeshData: interpolatedMesh,
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
|
|
628
|
+
/** Function to run cli command
|
|
629
|
+
*
|
|
630
|
+
* @param command Ocliff/Command
|
|
631
|
+
* @param workingDirectory string
|
|
632
|
+
*
|
|
633
|
+
* @returns Promise<void>
|
|
634
|
+
*/
|
|
635
|
+
function runCliCommand(command, workingDirectory = '.') {
|
|
636
|
+
return new Promise((resolve, reject) => {
|
|
637
|
+
const childProcess = exec(command, { cwd: workingDirectory });
|
|
638
|
+
childProcess.stdout.pipe(stdout);
|
|
639
|
+
childProcess.stdin.pipe(stderr);
|
|
640
|
+
childProcess.on('exit', code => {
|
|
641
|
+
if (code === 0) {
|
|
642
|
+
resolve();
|
|
643
|
+
} else {
|
|
644
|
+
reject(new Error(`${command} exection failed`));
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
/**
|
|
651
|
+
* Append/override files to the files array in meshConfig
|
|
652
|
+
*
|
|
653
|
+
* @param data MeshConfig
|
|
654
|
+
* @param file File to append or override
|
|
655
|
+
* @param meshConfigName MeshConfig name
|
|
656
|
+
* @param index Append operation if index is -1, else override, it is the index where the override takes place
|
|
657
|
+
*/
|
|
658
|
+
function updateFilesArray(data, file, meshConfigName, index) {
|
|
659
|
+
try {
|
|
660
|
+
let readFileData = fs.readFileSync(
|
|
661
|
+
path.resolve(path.dirname(meshConfigName), file),
|
|
662
|
+
{ encoding: 'utf-8' },
|
|
663
|
+
err => {
|
|
664
|
+
if (err) {
|
|
665
|
+
throw new Error(err);
|
|
666
|
+
}
|
|
667
|
+
},
|
|
668
|
+
);
|
|
669
|
+
|
|
670
|
+
try {
|
|
671
|
+
//validate JSON file
|
|
672
|
+
if (path.extname(file) === '.json') {
|
|
673
|
+
readFileData = JSON.stringify(JSON.parse(readFileData));
|
|
674
|
+
}
|
|
675
|
+
} catch (err) {
|
|
676
|
+
logger.error(err.message);
|
|
677
|
+
throw new Error(`Invalid JSON content in ${path.basename(file)}`);
|
|
678
|
+
}
|
|
679
|
+
|
|
680
|
+
//data to be overridden or appended
|
|
681
|
+
const dataInFilesArray = jsmin(readFileData);
|
|
682
|
+
|
|
683
|
+
if (index >= 0) {
|
|
684
|
+
data.meshConfig.files[index] = {
|
|
685
|
+
path: file,
|
|
686
|
+
content: dataInFilesArray,
|
|
687
|
+
};
|
|
688
|
+
} else {
|
|
689
|
+
//if the files array does not exist
|
|
690
|
+
if (!data.meshConfig.files) {
|
|
691
|
+
data.meshConfig.files = [];
|
|
692
|
+
}
|
|
693
|
+
|
|
694
|
+
//if the files arrray exists, we append the file path and content in meshConfig
|
|
695
|
+
data.meshConfig.files.push({
|
|
696
|
+
path: file,
|
|
697
|
+
content: dataInFilesArray,
|
|
698
|
+
});
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
return data;
|
|
702
|
+
} catch (err) {
|
|
703
|
+
logger.error(err.message);
|
|
704
|
+
throw new Error(err.message);
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
462
708
|
module.exports = {
|
|
709
|
+
objToString,
|
|
463
710
|
promptInput,
|
|
464
711
|
promptConfirm,
|
|
465
712
|
getLibConsoleCLI,
|
|
@@ -468,4 +715,8 @@ module.exports = {
|
|
|
468
715
|
initRequestId,
|
|
469
716
|
promptSelect,
|
|
470
717
|
promptMultiselect,
|
|
718
|
+
importFiles,
|
|
719
|
+
interpolateMesh,
|
|
720
|
+
runCliCommand,
|
|
721
|
+
updateFilesArray,
|
|
471
722
|
};
|
package/src/lib/devConsole.js
CHANGED
|
@@ -4,12 +4,11 @@
|
|
|
4
4
|
const axios = require('axios');
|
|
5
5
|
|
|
6
6
|
const logger = require('../classes/logger');
|
|
7
|
-
const { objToString } = require('../utils');
|
|
8
7
|
const CONSTANTS = require('../constants');
|
|
9
8
|
|
|
10
9
|
const { DEV_CONSOLE_TRANSPORTER_API_KEY } = CONSTANTS;
|
|
11
10
|
|
|
12
|
-
const { getDevConsoleConfig } = require('../helpers');
|
|
11
|
+
const { objToString, getDevConsoleConfig } = require('../helpers');
|
|
13
12
|
|
|
14
13
|
const getApiKeyCredential = async (organizationId, projectId, workspaceId) => {
|
|
15
14
|
const { baseUrl: devConsoleUrl, accessToken } = await getDevConsoleConfig();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
node_modules
|