@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.
Files changed (32) hide show
  1. package/oclif.manifest.json +1 -1
  2. package/package.json +5 -3
  3. package/src/commands/__fixtures__/env_invalid +8 -0
  4. package/src/commands/__fixtures__/env_valid +3 -0
  5. package/src/commands/__fixtures__/files/requestParams.json +3 -0
  6. package/src/commands/__fixtures__/openapi-schema.json +4 -0
  7. package/src/commands/__fixtures__/requestParams.json +3 -0
  8. package/src/commands/__fixtures__/sample_fully_qualified_mesh.json +29 -0
  9. package/src/commands/__fixtures__/sample_invalid_mesh.txt +17 -0
  10. package/src/commands/__fixtures__/sample_mesh_files.json +23 -0
  11. package/src/commands/__fixtures__/sample_mesh_invalid_file_content.json +14 -0
  12. package/src/commands/__fixtures__/sample_mesh_invalid_file_name.json +27 -0
  13. package/src/commands/__fixtures__/sample_mesh_invalid_paths.json +23 -0
  14. package/src/commands/__fixtures__/sample_mesh_invalid_type.json +27 -0
  15. package/src/commands/__fixtures__/sample_mesh_mismatching_path.json +29 -0
  16. package/src/commands/__fixtures__/sample_mesh_outside_workspace_dir.json +23 -0
  17. package/src/commands/__fixtures__/sample_mesh_path_from_home.json +14 -0
  18. package/src/commands/__fixtures__/sample_mesh_subdirectory.json +23 -0
  19. package/src/commands/__fixtures__/sample_mesh_with_files_array.json +29 -0
  20. package/src/commands/__fixtures__/sample_mesh_with_placeholder +17 -0
  21. package/src/commands/api-mesh/__tests__/create.test.js +1334 -140
  22. package/src/commands/api-mesh/__tests__/delete.test.js +3 -3
  23. package/src/commands/api-mesh/__tests__/init.test.js +390 -0
  24. package/src/commands/api-mesh/__tests__/update.test.js +524 -109
  25. package/src/commands/api-mesh/create.js +47 -14
  26. package/src/commands/api-mesh/init.js +168 -0
  27. package/src/commands/api-mesh/update.js +49 -17
  28. package/src/helpers.js +254 -3
  29. package/src/lib/devConsole.js +1 -2
  30. package/src/templates/gitignore +1 -0
  31. package/src/templates/package.json +38 -0
  32. 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 { ignoreCacheFlag, autoConfirmActionFlag, jsonFlag } = require('../../utils');
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
- data = JSON.parse(await readFile(args.file, 'utf8'));
63
- } catch (error) {
64
- logger.error(error);
65
-
66
- this.log(error.message);
67
- this.error(
68
- 'Unable to read the mesh configuration file provided. Please check the file and try again.',
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 { ignoreCacheFlag, autoConfirmActionFlag } = require('../../utils');
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
- let data;
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 { objToString } = require('./utils');
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
- this.error(
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
  };
@@ -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