@adobe/aio-cli-plugin-api-mesh 2.2.0 → 2.3.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/oclif.manifest.json +1 -1
- package/package.json +2 -1
- 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/api-mesh/__tests__/create.test.js +1000 -31
- package/src/commands/api-mesh/__tests__/get.test.js +8 -0
- package/src/commands/api-mesh/__tests__/init.test.js +390 -0
- package/src/commands/api-mesh/__tests__/update.test.js +419 -4
- package/src/commands/api-mesh/create.js +37 -68
- package/src/commands/api-mesh/get.js +7 -2
- package/src/commands/api-mesh/init.js +168 -0
- package/src/commands/api-mesh/source/__tests__/get.test.js +1 -1
- package/src/commands/api-mesh/source/__tests__/install.test.js +2 -2
- package/src/commands/api-mesh/update.js +35 -67
- package/src/helpers.js +249 -91
- package/src/lib/devConsole.js +1 -2
- package/src/templates/gitignore +1 -0
- package/src/templates/package.json +38 -0
- package/src/utils.js +329 -31
- package/src/meshInterpolation.js +0 -120
|
@@ -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('Local workspace created successfully');
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
module.exports = InitCommand;
|
|
@@ -122,7 +122,7 @@ describe('source:get command tests', () => {
|
|
|
122
122
|
const version = '1.1.1';
|
|
123
123
|
await GetCommand.run([`-s=${name}@${version}`]).catch(err => {
|
|
124
124
|
expect(err.message).toContain(
|
|
125
|
-
chalk.red(`The version
|
|
125
|
+
chalk.red(`The version "1.1.1" for source name "test-01" doesn't exist.`),
|
|
126
126
|
);
|
|
127
127
|
});
|
|
128
128
|
});
|
|
@@ -104,9 +104,9 @@ describe('source:install command tests', () => {
|
|
|
104
104
|
});
|
|
105
105
|
test('Check executing with invalid file parameter', async () => {
|
|
106
106
|
await InstallCommand.run(['test-03', '-f=notexist.json']).catch(err => {
|
|
107
|
-
expect(err.message).
|
|
107
|
+
expect(err.message).toContain(
|
|
108
108
|
`Something went wrong trying to read the variables file.` +
|
|
109
|
-
`\nENOENT: no such file or directory
|
|
109
|
+
`\nENOENT: no such file or directory`,
|
|
110
110
|
);
|
|
111
111
|
});
|
|
112
112
|
});
|
|
@@ -10,15 +10,19 @@ 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
|
-
const meshInterpolation = require('../../meshInterpolation');
|
|
20
|
-
|
|
21
|
-
const dotenv = require('dotenv');
|
|
22
26
|
|
|
23
27
|
class UpdateCommand extends Command {
|
|
24
28
|
static args = [{ name: 'file' }];
|
|
@@ -43,27 +47,16 @@ class UpdateCommand extends Command {
|
|
|
43
47
|
|
|
44
48
|
const ignoreCache = await flags.ignoreCache;
|
|
45
49
|
const autoConfirmAction = await flags.autoConfirmAction;
|
|
46
|
-
const envFilePath=await flags.env;
|
|
50
|
+
const envFilePath = await flags.env;
|
|
47
51
|
|
|
48
52
|
const { imsOrgId, projectId, workspaceId } = await initSdk({
|
|
49
53
|
ignoreCache,
|
|
50
54
|
});
|
|
51
55
|
|
|
52
|
-
let inputMeshData;
|
|
53
|
-
|
|
54
56
|
//Input the mesh data from the input file
|
|
55
|
-
|
|
56
|
-
inputMeshData = await readFile(args.file, 'utf8');
|
|
57
|
-
} catch (error) {
|
|
58
|
-
logger.error(error);
|
|
59
|
-
|
|
60
|
-
this.log(error.message);
|
|
61
|
-
this.error(
|
|
62
|
-
'Unable to read the mesh configuration file provided. Please check the file and try again.',
|
|
63
|
-
);
|
|
64
|
-
}
|
|
57
|
+
let inputMeshData = await readFileContents(args.file, this, 'mesh');
|
|
65
58
|
|
|
66
|
-
let meshId;
|
|
59
|
+
let meshId = null;
|
|
67
60
|
|
|
68
61
|
try {
|
|
69
62
|
meshId = await getMeshId(imsOrgId, projectId, workspaceId);
|
|
@@ -75,61 +68,36 @@ class UpdateCommand extends Command {
|
|
|
75
68
|
|
|
76
69
|
let data;
|
|
77
70
|
|
|
78
|
-
if (
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
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 {
|
|
82
75
|
try {
|
|
83
|
-
|
|
84
|
-
} catch (
|
|
85
|
-
this.log(
|
|
86
|
-
this.error('
|
|
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.');
|
|
87
80
|
}
|
|
81
|
+
}
|
|
88
82
|
|
|
89
|
-
|
|
90
|
-
const envFileValidity = meshInterpolation.validateEnvFileFormat(envFileContent);
|
|
91
|
-
if (envFileValidity.valid) {
|
|
92
|
-
//load env file into the process.env object
|
|
93
|
-
meshInterpolation.clearEnv();
|
|
94
|
-
|
|
95
|
-
//Added env at start of each environment variable
|
|
96
|
-
const envObj = { env: dotenv.config({ path: envFilePath }).parsed };
|
|
97
|
-
|
|
98
|
-
let {
|
|
99
|
-
interpolationStatus,
|
|
100
|
-
missingKeys,
|
|
101
|
-
interpolatedMeshData,
|
|
102
|
-
} = await meshInterpolation.interpolateMesh(inputMeshData, envObj);
|
|
103
|
-
|
|
104
|
-
//De-duplicate the missing keys array
|
|
105
|
-
missingKeys = missingKeys.filter(function (item, index, inputArray) {
|
|
106
|
-
return inputArray.indexOf(item) == index;
|
|
107
|
-
});
|
|
83
|
+
let filesList = [];
|
|
108
84
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
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
|
+
}
|
|
114
91
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
} catch (err) {
|
|
118
|
-
this.log(err.message);
|
|
119
|
-
this.log(interpolatedMeshData);
|
|
120
|
-
this.error(
|
|
121
|
-
'Interpolated mesh is not a valid JSON. Please check the generated json file.',
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
} else {
|
|
125
|
-
this.error(`Issue in ${envFilePath} file - ` + envFileValidity.error);
|
|
126
|
-
}
|
|
127
|
-
} else {
|
|
92
|
+
// if local files are present, import them in files array in meshConfig
|
|
93
|
+
if (filesList.length) {
|
|
128
94
|
try {
|
|
129
|
-
data =
|
|
95
|
+
data = await importFiles(data, filesList, args.file, flags.autoConfirmAction);
|
|
130
96
|
} catch (err) {
|
|
131
97
|
this.log(err.message);
|
|
132
|
-
this.error(
|
|
98
|
+
this.error(
|
|
99
|
+
'Unable to import the files in the mesh config. Please check the file and try again.',
|
|
100
|
+
);
|
|
133
101
|
}
|
|
134
102
|
}
|
|
135
103
|
|