@adobe/aio-cli-plugin-api-mesh 5.2.4-alpha.0 → 5.3.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.
Files changed (39) hide show
  1. package/oclif.manifest.json +1 -1
  2. package/package.json +13 -6
  3. package/src/commands/api-mesh/__tests__/cache-purge.test.js +1 -2
  4. package/src/commands/api-mesh/__tests__/create.test.js +19 -22
  5. package/src/commands/api-mesh/__tests__/delete-log-forwarding.test.js +106 -0
  6. package/src/commands/api-mesh/__tests__/delete.test.js +1 -2
  7. package/src/commands/api-mesh/__tests__/describe.test.js +1 -3
  8. package/src/commands/api-mesh/__tests__/get.test.js +2 -2
  9. package/src/commands/api-mesh/__tests__/log-get-bulk.test.js +19 -213
  10. package/src/commands/api-mesh/__tests__/run.test.js +191 -65
  11. package/src/commands/api-mesh/__tests__/update.test.js +8 -7
  12. package/src/commands/api-mesh/cache/purge.js +1 -3
  13. package/src/commands/api-mesh/config/delete/log-forwarding.js +80 -0
  14. package/src/commands/api-mesh/create.js +22 -6
  15. package/src/commands/api-mesh/delete.js +1 -3
  16. package/src/commands/api-mesh/describe.js +1 -3
  17. package/src/commands/api-mesh/get.js +1 -3
  18. package/src/commands/api-mesh/log-get-bulk.js +5 -26
  19. package/src/commands/api-mesh/log-get.js +1 -3
  20. package/src/commands/api-mesh/log-list.js +1 -3
  21. package/src/commands/api-mesh/run.js +207 -168
  22. package/src/commands/api-mesh/source/discover.js +2 -9
  23. package/src/commands/api-mesh/source/get.js +1 -8
  24. package/src/commands/api-mesh/source/install.js +1 -2
  25. package/src/commands/api-mesh/status.js +1 -2
  26. package/src/commands/api-mesh/update.js +21 -6
  27. package/src/commands/{PLUGINNAME/__tests__/index.test.js → api-mesh.js} +13 -15
  28. package/src/helpers.js +73 -15
  29. package/src/hooks/initMetadata.js +8 -0
  30. package/src/lib/smsClient.js +115 -1
  31. package/src/meshArtifact.js +231 -0
  32. package/src/project.js +56 -0
  33. package/src/server.js +74 -32
  34. package/src/utils.js +26 -24
  35. package/src/{index.js → worker.js} +9 -7
  36. package/src/wranglerCli.js +54 -0
  37. package/wrangler.toml +13 -0
  38. package/src/commands/PLUGINNAME/index.js +0 -32
  39. package/src/wranglerServer.js +0 -80
@@ -10,7 +10,9 @@ governing permissions and limitations under the License.
10
10
  */
11
11
 
12
12
  const { Command } = require('@oclif/core');
13
- const { initSdk, initRequestId, promptConfirm, importFiles } = require('../../helpers');
13
+ const chalk = require('chalk');
14
+
15
+ const { initSdk, promptConfirm, importFiles } = require('../../helpers');
14
16
  const logger = require('../../classes/logger');
15
17
  const {
16
18
  ignoreCacheFlag,
@@ -42,8 +44,6 @@ class CreateCommand extends Command {
42
44
  static enableJsonFlag = true;
43
45
 
44
46
  async run() {
45
- await initRequestId();
46
-
47
47
  logger.info(`RequestId: ${global.requestId}`);
48
48
 
49
49
  const { args, flags } = await this.parse(CreateCommand);
@@ -99,7 +99,7 @@ class CreateCommand extends Command {
99
99
  // if local files are present, import them in files array in meshConfig
100
100
  if (filesList.length) {
101
101
  try {
102
- data = await importFiles(data, filesList, args.file, flags.autoConfirmAction);
102
+ ({ data } = await importFiles(data, filesList, args.file, flags.autoConfirmAction));
103
103
  } catch (err) {
104
104
  this.log(err.message);
105
105
  this.error('Unable to import the files in the mesh config. Check the file and try again.');
@@ -112,8 +112,7 @@ class CreateCommand extends Command {
112
112
  await validateSecretsFile(secretsFilePath);
113
113
  const secretsData = await interpolateSecrets(secretsFilePath, this);
114
114
  const publicKey = await getPublicEncryptionKey(imsOrgCode);
115
- const encryptedSecrets = await encryptSecrets(publicKey, secretsData);
116
- data.secrets = encryptedSecrets;
115
+ data.secrets = await encryptSecrets(publicKey, secretsData);
117
116
  } catch (err) {
118
117
  this.log(err.message);
119
118
  this.error('Unable to import secrets. Check the file and try again.');
@@ -122,6 +121,23 @@ class CreateCommand extends Command {
122
121
 
123
122
  let shouldContinue = true;
124
123
 
124
+ if (
125
+ data?.meshConfig?.responseConfig?.includeHTTPDetails &&
126
+ workspaceName.toLowerCase() === 'production'
127
+ ) {
128
+ this.warn(
129
+ `Your mesh has ${chalk.yellowBright('includeHTTPDetails')} set to ${chalk.redBright(
130
+ 'true',
131
+ )}. This is a security risk and should not be used in production.\n` +
132
+ `When ${chalk.yellowBright('includeHTTPDetails')} is set to ${chalk.redBright(
133
+ 'true',
134
+ )} it exposes HTTP request and response details in the mesh logs, which can cause sensitive information to be exposed.\n` +
135
+ `Consider setting ${chalk.yellowBright('includeHTTPDetails')} to ${chalk.greenBright(
136
+ 'false',
137
+ )} in your mesh configuration file.`,
138
+ );
139
+ }
140
+
125
141
  if (!autoConfirmAction) {
126
142
  shouldContinue = await promptConfirm(`Are you sure you want to create a mesh?`);
127
143
  }
@@ -12,7 +12,7 @@ governing permissions and limitations under the License.
12
12
  const { Command } = require('@oclif/command');
13
13
 
14
14
  const logger = require('../../classes/logger');
15
- const { initSdk, initRequestId, promptConfirm } = require('../../helpers');
15
+ const { initSdk, promptConfirm } = require('../../helpers');
16
16
  const { ignoreCacheFlag, autoConfirmActionFlag } = require('../../utils');
17
17
  const { getMeshId, deleteMesh } = require('../../lib/smsClient');
18
18
 
@@ -25,8 +25,6 @@ class DeleteCommand extends Command {
25
25
  };
26
26
 
27
27
  async run() {
28
- await initRequestId();
29
-
30
28
  logger.info(`RequestId: ${global.requestId}`);
31
29
 
32
30
  const { flags } = await this.parse(DeleteCommand);
@@ -11,7 +11,7 @@ governing permissions and limitations under the License.
11
11
 
12
12
  const { Command } = require('@oclif/command');
13
13
  const logger = require('../../classes/logger');
14
- const { initSdk, initRequestId } = require('../../helpers');
14
+ const { initSdk } = require('../../helpers');
15
15
  const { ignoreCacheFlag } = require('../../utils');
16
16
  const { describeMesh } = require('../../lib/smsClient');
17
17
  const { buildMeshUrl } = require('../../urlBuilder');
@@ -24,8 +24,6 @@ class DescribeCommand extends Command {
24
24
  };
25
25
 
26
26
  async run() {
27
- await initRequestId();
28
-
29
27
  logger.info(`RequestId: ${global.requestId}`);
30
28
 
31
29
  const { flags } = await this.parse(DescribeCommand);
@@ -13,7 +13,7 @@ const { Command } = require('@oclif/core');
13
13
  const { writeFile } = require('fs/promises');
14
14
 
15
15
  const logger = require('../../classes/logger');
16
- const { initSdk, initRequestId } = require('../../helpers');
16
+ const { initSdk } = require('../../helpers');
17
17
  const { ignoreCacheFlag, jsonFlag } = require('../../utils');
18
18
  const { getMeshId, getMesh } = require('../../lib/smsClient');
19
19
  const { buildMeshUrl } = require('../../urlBuilder');
@@ -29,8 +29,6 @@ class GetCommand extends Command {
29
29
  static enableJsonFlag = true;
30
30
 
31
31
  async run() {
32
- await initRequestId();
33
-
34
32
  logger.info(`RequestId: ${global.requestId}`);
35
33
 
36
34
  const { args, flags } = await this.parse(GetCommand);
@@ -1,7 +1,7 @@
1
1
  const { Command } = require('@oclif/core');
2
2
  const path = require('path');
3
3
  const fs = require('fs');
4
- const { initRequestId, initSdk, promptConfirm } = require('../../helpers');
4
+ const { initSdk, promptConfirm } = require('../../helpers');
5
5
  const { getMeshId, getPresignedUrls } = require('../../lib/smsClient');
6
6
  const logger = require('../../classes/logger');
7
7
  const axios = require('axios');
@@ -11,12 +11,10 @@ const {
11
11
  endTimeFlag,
12
12
  logFilenameFlag,
13
13
  pastFlag,
14
- fromFlag,
15
14
  suggestCorrectedDateFormat,
16
15
  parsePastDuration,
17
16
  validateDateTimeRange,
18
17
  validateDateTimeFormat,
19
- localToUTCTime,
20
18
  } = require('../../utils');
21
19
 
22
20
  require('dotenv').config();
@@ -28,7 +26,6 @@ class GetBulkLogCommand extends Command {
28
26
  endTime: endTimeFlag,
29
27
  filename: logFilenameFlag,
30
28
  past: pastFlag,
31
- from: fromFlag,
32
29
  };
33
30
 
34
31
  async run() {
@@ -36,7 +33,6 @@ class GetBulkLogCommand extends Command {
36
33
  const columnHeaders =
37
34
  'EventTimestampMs,Exceptions,Logs,Outcome,MeshId,RayID,URL,Request Method,Response Status,Level';
38
35
 
39
- await initRequestId();
40
36
  logger.info(`RequestId: ${global.requestId}`);
41
37
  const { flags } = await this.parse(GetBulkLogCommand);
42
38
  const ignoreCache = await flags.ignoreCache;
@@ -90,26 +86,9 @@ class GetBulkLogCommand extends Command {
90
86
  formattedEndTime = flags.endTime.replace(/-|:|Z/g, '').replace('T', 'T');
91
87
  } else if (flags.past) {
92
88
  const pastTimeWindow = parsePastDuration(flags.past);
93
- if (flags.from) {
94
- let convertedTime;
95
- const dateTimeRegex = /^\d{4}-\d{2}-\d{2}:\d{2}:\d{2}:\d{2}$/;
96
- if (!dateTimeRegex.test(flags.from)) {
97
- this.error('Invalid format. Use the format YYYY-MM-DD:HH:MM:SS for --from.');
98
- } else {
99
- try {
100
- convertedTime = await localToUTCTime(flags.from.toString());
101
- } catch (error) {
102
- this.error(`Invalid date components passed in --from. Correct the date.`);
103
- }
104
- }
105
- // add the past window to the converted time to get the end time to fetch logs from the past
106
- calculatedStartTime = new Date(convertedTime);
107
- calculatedEndTime = new Date(calculatedStartTime.getTime() + pastTimeWindow);
108
- } else {
109
- // subtract the past window from the current time to get the start time to fetch recent logs from now
110
- calculatedEndTime = new Date();
111
- calculatedStartTime = new Date(calculatedEndTime.getTime() - pastTimeWindow);
112
- }
89
+ // Subtract the past window from the current time to get the start time to fetch recent logs from now
90
+ calculatedEndTime = new Date();
91
+ calculatedStartTime = new Date(calculatedEndTime.getTime() - pastTimeWindow);
113
92
 
114
93
  // Validate the calculated start and end times range
115
94
  validateDateTimeRange(calculatedStartTime, calculatedEndTime);
@@ -121,7 +100,7 @@ class GetBulkLogCommand extends Command {
121
100
  return;
122
101
  } else {
123
102
  this.error(
124
- 'Missing required flags. Provide at least one flag --startTime, --endTime, or --past --from or type `mesh log:get-bulk --help` for more information.',
103
+ 'Missing required flags. Provide a time range with --startTime and --endTime flags, or use the --past flag for more recent logs. Use the `mesh log:get-bulk --help` command for more information.',
125
104
  );
126
105
  return;
127
106
  }
@@ -10,7 +10,7 @@ governing permissions and limitations under the License.
10
10
  */
11
11
  const { Command } = require('@oclif/core');
12
12
  const logger = require('../../classes/logger');
13
- const { initSdk, initRequestId } = require('../../helpers');
13
+ const { initSdk } = require('../../helpers');
14
14
  const { ignoreCacheFlag } = require('../../utils');
15
15
  const { getMeshId, getLogsByRayId } = require('../../lib/smsClient');
16
16
  require('dotenv').config();
@@ -22,8 +22,6 @@ class FetchLogsCommand extends Command {
22
22
  };
23
23
 
24
24
  async run() {
25
- await initRequestId();
26
-
27
25
  logger.info(`RequestId: ${global.requestId}`);
28
26
 
29
27
  const { args, flags } = await this.parse(FetchLogsCommand);
@@ -1,7 +1,7 @@
1
1
  const { Command } = require('@oclif/core');
2
2
 
3
3
  const logger = require('../../classes/logger');
4
- const { initSdk, initRequestId } = require('../../helpers');
4
+ const { initSdk } = require('../../helpers');
5
5
  const { ignoreCacheFlag, fileNameFlag } = require('../../utils');
6
6
  const { getMeshId, listLogs } = require('../../lib/smsClient');
7
7
  const { appendFileSync, existsSync } = require('fs');
@@ -18,8 +18,6 @@ class ListLogsCommand extends Command {
18
18
  static enableJsonFlag = true;
19
19
 
20
20
  async run() {
21
- await initRequestId();
22
-
23
21
  logger.info(`RequestId: ${global.requestId}`);
24
22
 
25
23
  const { flags } = await this.parse(ListLogsCommand);
@@ -13,6 +13,7 @@ const { Command } = require('@oclif/core');
13
13
  const {
14
14
  portNoFlag,
15
15
  debugFlag,
16
+ inspectPortNoFlag,
16
17
  selectFlag,
17
18
  envFileFlag,
18
19
  secretsFlag,
@@ -27,18 +28,19 @@ const {
27
28
  const meshBuilder = require('@adobe-apimesh/mesh-builder');
28
29
  const fs = require('fs');
29
30
  const path = require('path');
30
- const {
31
- initSdk,
32
- initRequestId,
33
- importFiles,
34
- setUpTenantFiles,
35
- writeSecretsFile,
36
- } = require('../../helpers');
31
+ const { initSdk, importFiles, setUpTenantFiles, writeSecretsFile } = require('../../helpers');
37
32
  const logger = require('../../classes/logger');
38
33
  const { getMeshId, getMeshArtifact } = require('../../lib/smsClient');
39
34
  require('dotenv').config();
40
- const { runServer } = require('../../server');
41
- const { fixPlugins } = require('../../fixPlugins');
35
+ const { start } = require('../../wranglerCli');
36
+ const {
37
+ resolveOriginalSources,
38
+ copyBuiltMeshToPackage,
39
+ BUILT_MESH_ARTIFACT_DIRECTORY,
40
+ safeDelete,
41
+ getBuiltMeshTenantDirectory,
42
+ } = require('../../project');
43
+ const { resolveRelativeSources } = require('../../meshArtifact');
42
44
 
43
45
  const { validateMesh, buildMesh, compileMesh } = meshBuilder.default;
44
46
 
@@ -55,6 +57,7 @@ class RunCommand extends Command {
55
57
 
56
58
  static flags = {
57
59
  port: portNoFlag,
60
+ inspectPort: inspectPortNoFlag,
58
61
  debug: debugFlag,
59
62
  env: envFileFlag,
60
63
  autoConfirmAction: autoConfirmActionFlag,
@@ -66,182 +69,218 @@ class RunCommand extends Command {
66
69
 
67
70
  static examples = [];
68
71
 
69
- async run() {
70
- await initRequestId();
72
+ /**
73
+ * Validate the current working directory to ensure it is set up to run the command
74
+ * @returns {Promise<void>}
75
+ * @throws {Error} when project is not set up correctly
76
+ */
77
+ async validateCwd() {
78
+ //Ensure that current directory includes package.json
79
+ if (!fs.existsSync(path.join(process.cwd(), 'package.json'))) {
80
+ throw new Error(
81
+ '`aio api-mesh run` cannot be executed because there is no package.json file in the current directory. Use `aio api-mesh init` to set up a package.',
82
+ );
83
+ }
84
+ }
71
85
 
72
- logger.info(`RequestId: ${global.requestId}`);
86
+ /**
87
+ * Handle remote mesh artifact
88
+ * @returns {Promise<string>} Mesh identifier
89
+ * @throws {Error} when failure retrieving remote mesh artifact
90
+ */
91
+ async handleRemoteMeshArtifact() {
92
+ const { imsOrgCode, projectId, workspaceId, workspaceName } = await initSdk({});
73
93
 
74
- const { args, flags } = await this.parse(RunCommand);
75
- const secretsFilePath = await flags.secrets;
94
+ // Get the mesh identifier for the workspace
95
+ let meshId;
96
+ try {
97
+ meshId = await getMeshId(imsOrgCode, projectId, workspaceId, workspaceName);
98
+ } catch (err) {
99
+ throw new Error(
100
+ `Unable to get mesh ID. Please check the details and try again. RequestId: ${global.requestId}`,
101
+ );
102
+ }
76
103
 
77
- //Initialize the meshId based on
78
- let meshId = null;
104
+ try {
105
+ await getMeshArtifact(imsOrgCode, projectId, workspaceId, workspaceName, meshId);
106
+ } catch (err) {
107
+ throw new Error(
108
+ `Unable to retrieve mesh. Please check the details and try again. RequestId: ${global.requestId}`,
109
+ );
110
+ }
79
111
 
80
112
  try {
81
- //Ensure that current directory includes package.json
82
- if (fs.existsSync(path.join(process.cwd(), 'package.json'))) {
83
- //If select flag is present then getMeshId for the specified org
84
- if (flags.select) {
85
- const { imsOrgCode, projectId, workspaceId, workspaceName } = await initSdk({});
86
-
87
- try {
88
- meshId = await getMeshId(imsOrgCode, projectId, workspaceId, workspaceName);
89
- } catch (err) {
90
- throw new Error(
91
- `Unable to get mesh ID. Please check the details and try again. RequestId: ${global.requestId}`,
92
- );
93
- }
94
-
95
- try {
96
- await getMeshArtifact(imsOrgCode, projectId, workspaceId, workspaceName, meshId);
97
- } catch (err) {
98
- throw new Error(
99
- `Unable to retrieve mesh. Please check the details and try again. RequestId: ${global.requestId}`,
100
- );
101
- }
102
-
103
- try {
104
- await setUpTenantFiles(meshId);
105
- } catch (err) {
106
- throw new Error('Failed to install downloaded mesh');
107
- }
108
-
109
- this.log('Successfully downloaded mesh');
110
- } else {
111
- if (!args.file) {
112
- throw new Error('Missing file path. Run aio api-mesh run --help for more info.');
113
- }
114
-
115
- const envFilePath = await flags.env;
116
-
117
- //Read the mesh input file
118
- let inputMeshData = await readFileContents(args.file, this, 'mesh');
119
- let data;
120
-
121
- if (checkPlaceholders(inputMeshData)) {
122
- this.log(
123
- 'The provided mesh contains placeholders. Starting mesh interpolation process.',
124
- );
125
- data = await validateAndInterpolateMesh(inputMeshData, envFilePath, this);
126
- } else {
127
- try {
128
- data = JSON.parse(inputMeshData);
129
- } catch (err) {
130
- this.log(err.message);
131
- throw new Error(
132
- 'Input mesh file is not a valid JSON. Please check the file provided.',
133
- );
134
- }
135
- }
136
-
137
- let filesList = [];
138
-
139
- try {
140
- filesList = getFilesInMeshConfig(data, args.file);
141
- } catch (err) {
142
- this.log(err.message);
143
- throw new Error('Input mesh config is not valid.');
144
- }
145
-
146
- // if local files are present, import them in files array in meshConfig
147
- if (filesList.length) {
148
- try {
149
- // minification of js will not be done for run command if debugging is enabled
150
- data = await importFiles(
151
- data,
152
- filesList,
153
- args.file,
154
- flags.autoConfirmAction,
155
- !flags.debug,
156
- );
157
- } catch (err) {
158
- this.log(err.message);
159
- throw new Error(
160
- 'Unable to import the files in the mesh config. Please check the file and try again.',
161
- );
162
- }
163
- }
164
-
165
- //Generating unique mesh id
166
- meshId = 'testMesh';
167
-
168
- await validateMesh(data.meshConfig);
169
- await buildMesh(meshId, data.meshConfig);
170
- await compileMesh(meshId);
171
- }
172
- let portNo;
173
- //secrets management
174
- if (secretsFilePath) {
175
- try {
176
- await validateSecretsFile(secretsFilePath);
177
- const stringifiedSecrets = await interpolateSecrets(secretsFilePath, this);
178
- await writeSecretsFile(stringifiedSecrets, meshId);
179
- } catch (error) {
180
- this.log(error.message);
181
- this.error('Unable to import secrets. Please check the file and try again.');
182
- }
183
- }
184
-
185
- await this.copyMeshContent(meshId);
186
-
187
- //To set the port number using the environment file
188
- if (process.env.PORT !== undefined) {
189
- if (isNaN(process.env.PORT) || !Number.isInteger(parseInt(process.env.PORT))) {
190
- throw new Error('PORT value in the .env file is not a valid integer');
191
- }
192
-
193
- portNo = process.env.PORT;
194
- }
195
-
196
- //To set the port number as the provided value in the command
197
- if (flags.port !== undefined) {
198
- portNo = flags.port;
199
- }
200
-
201
- //To set the default port to 5000
202
- if (!portNo) {
203
- portNo = 5000;
204
- }
205
- this.log(`Starting server on port : ${portNo}`);
206
- await runServer(portNo);
207
- this.log(`Server is running on http://localhost:${portNo}/graphql`);
208
- } else {
113
+ await setUpTenantFiles(meshId);
114
+ } catch (err) {
115
+ throw new Error('Failed to install downloaded mesh');
116
+ }
117
+
118
+ // Resolve relative sources in built mesh for local development
119
+ const builtMeshTenantDir = getBuiltMeshTenantDirectory(meshId);
120
+ await resolveRelativeSources(builtMeshTenantDir);
121
+
122
+ this.log('Successfully downloaded mesh');
123
+
124
+ return meshId;
125
+ }
126
+
127
+ /**
128
+ * Handle local mesh configuration
129
+ * @param args {unknown} Arguments
130
+ * @param flags {unknown} Flags
131
+ * @returns {Promise<string>}
132
+ * @throws {Error} when failure building local mesh artifact
133
+ */
134
+ async handleLocalMeshConfig(args, flags) {
135
+ if (!args.file) {
136
+ throw new Error('Missing file path. Run aio api-mesh run --help for more info.');
137
+ }
138
+
139
+ const envFilePath = await flags.env;
140
+
141
+ //Read the mesh input file
142
+ let inputMeshData = await readFileContents(args.file, this, 'mesh');
143
+ let data;
144
+
145
+ // TODO: Should we check for secrets in use when no secrets file provided?
146
+ if (checkPlaceholders(inputMeshData)) {
147
+ this.log('The provided mesh contains placeholders. Starting mesh interpolation process.');
148
+ data = await validateAndInterpolateMesh(inputMeshData, envFilePath, this);
149
+ } else {
150
+ try {
151
+ data = JSON.parse(inputMeshData);
152
+ } catch (err) {
153
+ this.log(err.message);
154
+ throw new Error('Input mesh file is not a valid JSON. Please check the file provided.');
155
+ }
156
+ }
157
+
158
+ let filesList = [];
159
+
160
+ try {
161
+ filesList = getFilesInMeshConfig(data, args.file);
162
+ } catch (err) {
163
+ this.log(err.message);
164
+ throw new Error('Input mesh config is not valid.');
165
+ }
166
+
167
+ // if local files are present, import them in files array in meshConfig
168
+ let localFileOverrides;
169
+ if (filesList.length) {
170
+ try {
171
+ // minification of js will not be done for run command if debugging is enabled
172
+ ({ data, localFileOverrides } = await importFiles(
173
+ data,
174
+ filesList,
175
+ args.file,
176
+ flags.autoConfirmAction,
177
+ !flags.debug,
178
+ ));
179
+ } catch (err) {
180
+ this.log(err.message);
209
181
  throw new Error(
210
- '`aio api-mesh run` cannot be executed because there is no package.json file in the current directory. Use `aio api-mesh init` to set up a package.',
182
+ 'Unable to import the files in the mesh config. Please check the file and try again.',
211
183
  );
212
184
  }
213
- } catch (error) {
214
- this.error(error.message);
215
185
  }
186
+ // Empty mesh-artifact directory
187
+ safeDelete(BUILT_MESH_ARTIFACT_DIRECTORY);
188
+
189
+ //Generating unique mesh id
190
+ const meshId = 'testMesh';
191
+ await validateMesh(data.meshConfig);
192
+ await buildMesh(meshId, data.meshConfig);
193
+ await compileMesh(meshId);
194
+
195
+ // Resolve relative sources in built mesh for local development
196
+ const builtMeshTenantDir = getBuiltMeshTenantDirectory(meshId);
197
+ await resolveRelativeSources(builtMeshTenantDir);
198
+ await resolveOriginalSources(builtMeshTenantDir, localFileOverrides);
199
+
200
+ return meshId;
216
201
  }
217
202
 
218
- async copyMeshContent(meshId) {
219
- // Remove mesh artifact directory if exists
220
- if (fs.existsSync('.mesh')) {
221
- fs.rmSync('.mesh', { recursive: true });
203
+ updateFlagsFromEnv(flags) {
204
+ if (process.env.PORT !== undefined) {
205
+ flags.port = this.parseInt(
206
+ process.env.PORT,
207
+ 'PORT value in the .env file is not a valid integer',
208
+ );
209
+ }
210
+ if (process.env.INSPECT_PORT !== undefined) {
211
+ flags.inspectPort = this.parseInt(
212
+ process.env.INSPECT_PORT,
213
+ 'INSPECT_PORT value in the .env file is not a valid integer',
214
+ );
222
215
  }
223
- // Move built mesh artifact to expect directory
224
- fs.renameSync(`mesh-artifact/${meshId}`, '.mesh');
225
- // Remove tenant files directory if exists
226
- if (fs.existsSync('tenantFiles')) {
227
- fs.rmSync('tenantFiles', { recursive: true });
216
+ }
217
+
218
+ /**
219
+ * Parse integer from string
220
+ * @param value {string} String value
221
+ * @param errorMessage {string?} Optional error message when parsing fails
222
+ * @returns {number}
223
+ * @throws {Error} when value is not a valid integer
224
+ */
225
+ parseInt(value, errorMessage) {
226
+ const int = parseInt(value);
227
+ if (isNaN(int) || !Number.isInteger(int)) {
228
+ throw new Error(errorMessage || `Value is not a valid integer`);
228
229
  }
229
- // Move built tenant files if exists
230
- if (fs.existsSync('mesh-artifact/tenantFiles')) {
231
- // Tenant files included in the bundle for runtime/dynamic imports
232
- fs.cpSync('mesh-artifact/tenantFiles', '.mesh/tenantFiles', { recursive: true });
233
- fs.renameSync('mesh-artifact/tenantFiles', 'tenantFiles');
230
+ return int;
231
+ }
232
+
233
+ /**
234
+ * Handle secrets feature
235
+ * @param secretsFilePath {string} File path to secrets
236
+ * @param meshId {string} Mesh identifier
237
+ * @returns {Promise<void>}
238
+ */
239
+ async handleSecretsFeature(secretsFilePath, meshId) {
240
+ if (secretsFilePath) {
241
+ try {
242
+ await validateSecretsFile(secretsFilePath);
243
+ const stringifiedSecrets = await interpolateSecrets(secretsFilePath, this);
244
+ await writeSecretsFile(stringifiedSecrets, meshId);
245
+ } catch (error) {
246
+ this.log(error.message);
247
+ this.error('Unable to import secrets. Please check the file and try again.');
248
+ }
234
249
  }
250
+ }
235
251
 
236
- await fixPlugins('.mesh/index.js');
252
+ async run() {
253
+ try {
254
+ logger.info(`RequestId: ${global.requestId}`);
255
+
256
+ const { args, flags } = await this.parse(RunCommand);
257
+ await this.validateCwd();
258
+ this.updateFlagsFromEnv(flags);
259
+
260
+ // Use remote or local mesh artifact
261
+ let meshId;
262
+ if (flags.select) {
263
+ meshId = await this.handleRemoteMeshArtifact();
264
+ } else {
265
+ meshId = await this.handleLocalMeshConfig(args, flags);
266
+ }
237
267
 
238
- if (fs.existsSync(`${__dirname}/../../../.mesh`)) {
239
- fs.rmSync(`${__dirname}/../../../.mesh`, { recursive: true });
268
+ //secrets management
269
+ const secretsFilePath = await flags.secrets;
270
+ if (secretsFilePath) {
271
+ await this.handleSecretsFeature(secretsFilePath, meshId);
272
+ }
273
+
274
+ const builtMeshTenantDir = getBuiltMeshTenantDirectory(meshId);
275
+ await copyBuiltMeshToPackage(builtMeshTenantDir);
276
+
277
+ start(this, flags.port, flags.debug, flags.inspectPort);
278
+ if (flags.debug) {
279
+ this.log(`Debugging enabled on inspect port: ${flags.inspectPort}`);
280
+ }
281
+ } catch (error) {
282
+ this.error(error.message);
240
283
  }
241
- // At this time the bundle and build files must be copied out to the plugin directory
242
- fs.cpSync('.mesh', `${__dirname}/../../../.mesh`, { recursive: true });
243
- // Tenant files used at build time
244
- fs.cpSync('tenantFiles', `${__dirname}/../../../tenantFiles`, { recursive: true });
245
284
  }
246
285
  }
247
286