@adobe/aio-cli-plugin-api-mesh 3.2.0 → 3.2.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/README.md +7 -2
- package/package.json +71 -42
- package/src/commands/api-mesh/__tests__/run.test.js +57 -1
- package/src/commands/api-mesh/run.js +106 -61
- package/src/helpers.js +83 -0
- package/src/lib/devConsole.js +54 -0
- package/src/server.js +7 -3
- package/src/utils.js +6 -0
- package/oclif.manifest.json +0 -1
package/README.md
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
# Installation
|
|
2
2
|
|
|
3
|
-
Prerequisites
|
|
3
|
+
## Prerequisites
|
|
4
|
+
|
|
5
|
+
* [aio-cli](https://github.com/adobe/aio-cli).
|
|
6
|
+
* [node.js](https://nodejs.org/en/)
|
|
7
|
+
* [yarn](https://classic.yarnpkg.com/lang/en/docs/install).
|
|
8
|
+
|
|
4
9
|
To install a revision from this repository:
|
|
5
10
|
|
|
6
11
|
```
|
|
@@ -21,7 +26,7 @@ $ aio discover -i
|
|
|
21
26
|
|
|
22
27
|
### Local Development
|
|
23
28
|
|
|
24
|
-
Install project dependencies. `
|
|
29
|
+
Install project dependencies. `yarn install`
|
|
25
30
|
|
|
26
31
|
```
|
|
27
32
|
aio plugins:link api-mesh
|
package/package.json
CHANGED
|
@@ -1,22 +1,78 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@adobe/aio-cli-plugin-api-mesh",
|
|
3
|
-
"version": "3.2.
|
|
4
|
-
"
|
|
5
|
-
|
|
3
|
+
"version": "3.2.1",
|
|
4
|
+
"description": "Adobe I/O CLI plugin to develop and manage API mesh sources",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"oclif-plugin"
|
|
7
|
+
],
|
|
8
|
+
"homepage": "https://www.npmjs.com/package/@adobe/aio-cli-plugin-api-mesh",
|
|
9
|
+
"bugs": {
|
|
10
|
+
"url": "https://github.com/adobe/aio-cli-plugin-api-mesh/issues"
|
|
11
|
+
},
|
|
12
|
+
"repository": {
|
|
13
|
+
"type": "git",
|
|
14
|
+
"url": "https://github.com/adobe/aio-cli-plugin-api-mesh"
|
|
15
|
+
},
|
|
16
|
+
"license": "Apache-2.0",
|
|
17
|
+
"author": "Adobe Inc.",
|
|
18
|
+
"main": "src/index.js",
|
|
19
|
+
"directories": {
|
|
20
|
+
"test": "test"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"/oclif.manifest.json",
|
|
24
|
+
"/src"
|
|
25
|
+
],
|
|
26
|
+
"scripts": {
|
|
27
|
+
"e2e": "jest --collectCoverage=false --testRegex './e2e/e2e.js'",
|
|
28
|
+
"format": "prettier --check \"./**/*.{ts,tsx,js,css,json,md}\"",
|
|
29
|
+
"format:fix": "prettier --write \"./**/*.{ts,tsx,js,css,json,md}\"",
|
|
30
|
+
"lint": "eslint .",
|
|
31
|
+
"lint:fix": "eslint --fix .",
|
|
32
|
+
"prepack": "oclif-dev manifest && oclif-dev readme",
|
|
33
|
+
"postpack": "rm -f oclif.manifest.json",
|
|
34
|
+
"test": "jest",
|
|
35
|
+
"test:ci": "jest --ci",
|
|
36
|
+
"unit-tests": "jest --ci",
|
|
37
|
+
"version": "oclif-dev readme && git add README.md"
|
|
6
38
|
},
|
|
7
39
|
"dependencies": {
|
|
40
|
+
"@adobe-apimesh/mesh-builder": "1.4.0",
|
|
8
41
|
"@adobe/aio-cli-lib-console": "^4.0.0",
|
|
9
42
|
"@adobe/aio-lib-core-config": "^3.0.0",
|
|
10
43
|
"@adobe/aio-lib-core-logging": "^2.0.0",
|
|
11
44
|
"@adobe/aio-lib-env": "^2.0.0",
|
|
12
45
|
"@adobe/aio-lib-ims": "^6.0.1",
|
|
46
|
+
"@adobe/plugin-hooks": "0.1.1",
|
|
47
|
+
"@adobe/plugin-on-fetch": "0.1.0",
|
|
48
|
+
"@graphql-mesh/cli": "0.82.30",
|
|
49
|
+
"@graphql-mesh/graphql": "0.34.13",
|
|
50
|
+
"@graphql-mesh/json-schema": "0.35.38",
|
|
51
|
+
"@graphql-mesh/openapi": "0.33.39",
|
|
52
|
+
"@graphql-mesh/plugin-http-details-extensions": "0.1.21",
|
|
53
|
+
"@graphql-mesh/runtime": "0.46.21",
|
|
54
|
+
"@graphql-mesh/soap": "0.14.25",
|
|
55
|
+
"@graphql-mesh/transform-encapsulate": "0.4.21",
|
|
56
|
+
"@graphql-mesh/transform-federation": "0.11.14",
|
|
57
|
+
"@graphql-mesh/transform-filter-schema": "0.15.23",
|
|
58
|
+
"@graphql-mesh/transform-hoist-field": "0.2.21",
|
|
59
|
+
"@graphql-mesh/transform-naming-convention": "0.13.22",
|
|
60
|
+
"@graphql-mesh/transform-prefix": "0.12.22",
|
|
61
|
+
"@graphql-mesh/transform-prune": "0.1.20",
|
|
62
|
+
"@graphql-mesh/transform-rename": "0.14.22",
|
|
63
|
+
"@graphql-mesh/transform-replace-field": "0.4.20",
|
|
64
|
+
"@graphql-mesh/transform-resolvers-composition": "0.13.20",
|
|
65
|
+
"@graphql-mesh/transform-type-merging": "0.5.20",
|
|
66
|
+
"@graphql-mesh/types": "0.91.12",
|
|
67
|
+
"@graphql-mesh/store": "0.9.20",
|
|
13
68
|
"@oclif/command": "^1.6.1",
|
|
14
69
|
"@oclif/config": "^1.15.1",
|
|
15
70
|
"@oclif/core": "^1.14.1",
|
|
16
71
|
"@oclif/errors": "^1.1.2",
|
|
17
|
-
"@adobe-apimesh/mesh-builder": "1.3.2",
|
|
18
72
|
"axios": "^1.2.0",
|
|
19
73
|
"chalk": "^4.1.0",
|
|
74
|
+
"child_process": "^1.0.2",
|
|
75
|
+
"content-disposition": "^0.5.4",
|
|
20
76
|
"dotenv": "^16.0.3",
|
|
21
77
|
"eslint-plugin-promise": "^6.0.0",
|
|
22
78
|
"eslint-plugin-security": "^1.5.0",
|
|
@@ -24,6 +80,7 @@
|
|
|
24
80
|
"eslint-plugin-standard": "^5.0.0",
|
|
25
81
|
"fastify": "^4.23.2",
|
|
26
82
|
"fs-extra": "^11.1.0",
|
|
83
|
+
"graphql": "^16.6.0",
|
|
27
84
|
"inquirer": "^8.2.4",
|
|
28
85
|
"jsmin": "1.0.1",
|
|
29
86
|
"json-interpolate": "^1.0.3",
|
|
@@ -34,6 +91,7 @@
|
|
|
34
91
|
"pino-pretty": "^7.6.0",
|
|
35
92
|
"pupa": "^3.1.0",
|
|
36
93
|
"source-registry-storage-adapter": "github:devx-services/source-registry-storage-adapter#main",
|
|
94
|
+
"util": "^0.12.5",
|
|
37
95
|
"uuid": "^8.3.2"
|
|
38
96
|
},
|
|
39
97
|
"devDependencies": {
|
|
@@ -60,17 +118,15 @@
|
|
|
60
118
|
"stdout-stderr": "^0.1.9"
|
|
61
119
|
},
|
|
62
120
|
"engines": {
|
|
63
|
-
"
|
|
64
|
-
"
|
|
121
|
+
"node": "^16.13 || >=18.0.0",
|
|
122
|
+
"npm": ">=8.0.0"
|
|
123
|
+
},
|
|
124
|
+
"resolutions": {
|
|
125
|
+
"jackspeak": "2.1.1"
|
|
126
|
+
},
|
|
127
|
+
"publishConfig": {
|
|
128
|
+
"access": "public"
|
|
65
129
|
},
|
|
66
|
-
"files": [
|
|
67
|
-
"/oclif.manifest.json",
|
|
68
|
-
"/src"
|
|
69
|
-
],
|
|
70
|
-
"keywords": [
|
|
71
|
-
"oclif-plugin"
|
|
72
|
-
],
|
|
73
|
-
"license": "Apache-2.0",
|
|
74
130
|
"oclif": {
|
|
75
131
|
"commands": "./src/commands",
|
|
76
132
|
"bin": "aio",
|
|
@@ -78,32 +134,5 @@
|
|
|
78
134
|
"@oclif/plugin-help"
|
|
79
135
|
],
|
|
80
136
|
"repositoryPrefix": "<%- repo %>/blob/<%- version %>/<%- commandPath %>"
|
|
81
|
-
}
|
|
82
|
-
"main": "src/index.js",
|
|
83
|
-
"scripts": {
|
|
84
|
-
"test": "jest",
|
|
85
|
-
"test:ci": "jest --ci",
|
|
86
|
-
"unit-tests": "jest --ci",
|
|
87
|
-
"prepack": "oclif-dev manifest && oclif-dev readme",
|
|
88
|
-
"postpack": "rm -f oclif.manifest.json",
|
|
89
|
-
"version": "oclif-dev readme && git add README.md",
|
|
90
|
-
"e2e": "jest --collectCoverage=false --testRegex './e2e/e2e.js'",
|
|
91
|
-
"lint": "eslint .",
|
|
92
|
-
"lint:fix": "eslint --fix .",
|
|
93
|
-
"format": "prettier --check \"./**/*.{ts,tsx,js,css,json,md}\"",
|
|
94
|
-
"format:fix": "prettier --write \"./**/*.{ts,tsx,js,css,json,md}\""
|
|
95
|
-
},
|
|
96
|
-
"description": "Adobe I/O CLI plugin to develop and manage API mesh sources",
|
|
97
|
-
"directories": {
|
|
98
|
-
"test": "test"
|
|
99
|
-
},
|
|
100
|
-
"repository": {
|
|
101
|
-
"type": "git",
|
|
102
|
-
"url": "https://github.com/adobe/aio-cli-plugin-api-mesh"
|
|
103
|
-
},
|
|
104
|
-
"author": "Adobe Inc.",
|
|
105
|
-
"bugs": {
|
|
106
|
-
"url": "https://github.com/adobe/aio-cli-plugin-api-mesh/issues"
|
|
107
|
-
},
|
|
108
|
-
"homepage": "https://www.npmjs.com/package/@adobe/aio-cli-plugin-api-mesh"
|
|
137
|
+
}
|
|
109
138
|
}
|
|
@@ -16,14 +16,30 @@ const {
|
|
|
16
16
|
interpolateMesh,
|
|
17
17
|
importFiles,
|
|
18
18
|
promptConfirm,
|
|
19
|
+
setUpTenantFiles,
|
|
20
|
+
initSdk,
|
|
19
21
|
} = require('../../../helpers');
|
|
22
|
+
const { getMeshId, getMeshArtifact } = require('../../../lib/devConsole');
|
|
20
23
|
require('@adobe-apimesh/mesh-builder');
|
|
24
|
+
|
|
21
25
|
jest.mock('../../../helpers', () => ({
|
|
26
|
+
initSdk: jest.fn().mockResolvedValue({
|
|
27
|
+
imsOrgId: 'mockOrgId',
|
|
28
|
+
projectId: 'mockProjectId',
|
|
29
|
+
workspaceId: 'mockWorkspaceId',
|
|
30
|
+
workspaceName: 'mockWorkspaceTitle',
|
|
31
|
+
}),
|
|
22
32
|
initRequestId: jest.fn().mockResolvedValue({}),
|
|
23
33
|
startGraphqlServer: jest.fn().mockResolvedValue({}),
|
|
24
34
|
interpolateMesh: jest.fn().mockResolvedValue({}),
|
|
25
35
|
importFiles: jest.fn().mockResolvedValue(),
|
|
26
36
|
promptConfirm: jest.fn().mockResolvedValue(true),
|
|
37
|
+
setUpTenantFiles: jest.fn().mockResolvedValue(),
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
jest.mock('../../../lib/devConsole', () => ({
|
|
41
|
+
getMeshId: jest.fn().mockResolvedValue('mockMeshId'),
|
|
42
|
+
getMeshArtifact: jest.fn().mockResolvedValue(),
|
|
27
43
|
}));
|
|
28
44
|
|
|
29
45
|
jest.mock('@adobe-apimesh/mesh-builder', () => {
|
|
@@ -105,6 +121,13 @@ describe('run command tests', () => {
|
|
|
105
121
|
"parse": [Function],
|
|
106
122
|
"type": "option",
|
|
107
123
|
},
|
|
124
|
+
"select": {
|
|
125
|
+
"allowNo": false,
|
|
126
|
+
"default": false,
|
|
127
|
+
"description": "Retrieve existing artifacts from the mesh",
|
|
128
|
+
"parse": [Function],
|
|
129
|
+
"type": "boolean",
|
|
130
|
+
},
|
|
108
131
|
}
|
|
109
132
|
`);
|
|
110
133
|
expect(RunCommand.aliases).toMatchInlineSnapshot(`[]`);
|
|
@@ -121,7 +144,13 @@ describe('run command tests', () => {
|
|
|
121
144
|
new Error('Missing file path. Run aio api-mesh run --help for more info.'),
|
|
122
145
|
);
|
|
123
146
|
expect(logSpy.mock.calls).toMatchInlineSnapshot(`[]`);
|
|
124
|
-
expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
147
|
+
expect(errorLogSpy.mock.calls).toMatchInlineSnapshot(`
|
|
148
|
+
[
|
|
149
|
+
[
|
|
150
|
+
"Missing file path. Run aio api-mesh run --help for more info.",
|
|
151
|
+
],
|
|
152
|
+
]
|
|
153
|
+
`);
|
|
125
154
|
});
|
|
126
155
|
|
|
127
156
|
test('should use the port number provided in the flags for starting the server', async () => {
|
|
@@ -780,4 +809,31 @@ describe('run command tests', () => {
|
|
|
780
809
|
]
|
|
781
810
|
`);
|
|
782
811
|
});
|
|
812
|
+
|
|
813
|
+
test('should retrieve mesh artifact from sms if select flag is used', async () => {
|
|
814
|
+
const parseOutput = {
|
|
815
|
+
args: { file: 'src/commands/__fixtures__/sample_mesh.json' },
|
|
816
|
+
flags: { port: 6000, debug: false, select: true },
|
|
817
|
+
};
|
|
818
|
+
|
|
819
|
+
parseSpy.mockResolvedValue(parseOutput);
|
|
820
|
+
|
|
821
|
+
await RunCommand.run();
|
|
822
|
+
|
|
823
|
+
expect(initSdk).toHaveBeenCalled();
|
|
824
|
+
expect(getMeshId).toHaveBeenCalledWith(
|
|
825
|
+
'mockOrgId',
|
|
826
|
+
'mockProjectId',
|
|
827
|
+
'mockWorkspaceId',
|
|
828
|
+
'mockWorkspaceTitle',
|
|
829
|
+
);
|
|
830
|
+
expect(getMeshArtifact).toHaveBeenCalledWith(
|
|
831
|
+
'mockOrgId',
|
|
832
|
+
'mockProjectId',
|
|
833
|
+
'mockWorkspaceId',
|
|
834
|
+
'mockWorkspaceTitle',
|
|
835
|
+
'mockMeshId',
|
|
836
|
+
);
|
|
837
|
+
expect(setUpTenantFiles).toHaveBeenCalled();
|
|
838
|
+
});
|
|
783
839
|
});
|
|
@@ -13,6 +13,7 @@ const { Command } = require('@oclif/core');
|
|
|
13
13
|
const {
|
|
14
14
|
portNoFlag,
|
|
15
15
|
debugFlag,
|
|
16
|
+
selectFlag,
|
|
16
17
|
envFileFlag,
|
|
17
18
|
autoConfirmActionFlag,
|
|
18
19
|
readFileContents,
|
|
@@ -24,8 +25,15 @@ const meshBuilder = require('@adobe-apimesh/mesh-builder');
|
|
|
24
25
|
const fs = require('fs');
|
|
25
26
|
const UUID = require('../../uuid');
|
|
26
27
|
const path = require('path');
|
|
27
|
-
const {
|
|
28
|
+
const {
|
|
29
|
+
initSdk,
|
|
30
|
+
initRequestId,
|
|
31
|
+
startGraphqlServer,
|
|
32
|
+
importFiles,
|
|
33
|
+
setUpTenantFiles,
|
|
34
|
+
} = require('../../helpers');
|
|
28
35
|
const logger = require('../../classes/logger');
|
|
36
|
+
const { getMeshId, getMeshArtifact } = require('../../lib/devConsole');
|
|
29
37
|
require('dotenv').config();
|
|
30
38
|
|
|
31
39
|
const { validateMesh, buildMesh, compileMesh } = meshBuilder.default;
|
|
@@ -46,6 +54,7 @@ class RunCommand extends Command {
|
|
|
46
54
|
debug: debugFlag,
|
|
47
55
|
env: envFileFlag,
|
|
48
56
|
autoConfirmAction: autoConfirmActionFlag,
|
|
57
|
+
select: selectFlag,
|
|
49
58
|
};
|
|
50
59
|
|
|
51
60
|
static enableJsonFlag = true;
|
|
@@ -59,86 +68,122 @@ class RunCommand extends Command {
|
|
|
59
68
|
|
|
60
69
|
const { args, flags } = await this.parse(RunCommand);
|
|
61
70
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
}
|
|
71
|
+
//Initialize the meshId based on
|
|
72
|
+
let meshId = null;
|
|
65
73
|
|
|
66
|
-
|
|
74
|
+
try {
|
|
75
|
+
//Ensure that current directory includes package.json
|
|
76
|
+
if (fs.existsSync(path.join(process.cwd(), 'package.json'))) {
|
|
77
|
+
//If select flag is present then getMeshId for the specified org
|
|
78
|
+
if (flags.select) {
|
|
79
|
+
const { imsOrgId, projectId, workspaceId, workspaceName } = await initSdk({});
|
|
67
80
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
81
|
+
try {
|
|
82
|
+
meshId = await getMeshId(imsOrgId, projectId, workspaceId, workspaceName);
|
|
83
|
+
} catch (err) {
|
|
84
|
+
throw new Error(
|
|
85
|
+
`Unable to get mesh ID. Please check the details and try again. RequestId: ${global.requestId}`,
|
|
86
|
+
);
|
|
87
|
+
}
|
|
73
88
|
|
|
74
|
-
|
|
75
|
-
|
|
89
|
+
try {
|
|
90
|
+
await getMeshArtifact(imsOrgId, projectId, workspaceId, workspaceName, meshId);
|
|
91
|
+
} catch (err) {
|
|
92
|
+
throw new Error(
|
|
93
|
+
`Unable to retrieve mesh. Please check the details and try again. RequestId: ${global.requestId}`,
|
|
94
|
+
);
|
|
95
|
+
}
|
|
76
96
|
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
97
|
+
try {
|
|
98
|
+
await setUpTenantFiles(meshId);
|
|
99
|
+
} catch (err) {
|
|
100
|
+
throw new Error('Failed to install downloaded mesh');
|
|
101
|
+
}
|
|
81
102
|
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
103
|
+
this.log('Successfully downloaded mesh');
|
|
104
|
+
} else {
|
|
105
|
+
if (!args.file) {
|
|
106
|
+
throw new Error('Missing file path. Run aio api-mesh run --help for more info.');
|
|
107
|
+
}
|
|
86
108
|
|
|
87
|
-
|
|
109
|
+
const envFilePath = await flags.env;
|
|
88
110
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
111
|
+
//Read the mesh input file
|
|
112
|
+
let inputMeshData = await readFileContents(args.file, this, 'mesh');
|
|
113
|
+
let data;
|
|
114
|
+
|
|
115
|
+
if (checkPlaceholders(inputMeshData)) {
|
|
116
|
+
this.log(
|
|
117
|
+
'The provided mesh contains placeholders. Starting mesh interpolation process.',
|
|
118
|
+
);
|
|
119
|
+
data = await validateAndInterpolateMesh(inputMeshData, envFilePath, this);
|
|
120
|
+
} else {
|
|
121
|
+
try {
|
|
122
|
+
data = JSON.parse(inputMeshData);
|
|
123
|
+
} catch (err) {
|
|
124
|
+
this.log(err.message);
|
|
125
|
+
throw new Error(
|
|
126
|
+
'Input mesh file is not a valid JSON. Please check the file provided.',
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
let filesList = [];
|
|
95
132
|
|
|
96
|
-
if (checkPlaceholders(inputMeshData)) {
|
|
97
|
-
this.log('The provided mesh contains placeholders. Starting mesh interpolation process.');
|
|
98
|
-
data = await validateAndInterpolateMesh(inputMeshData, envFilePath, this);
|
|
99
|
-
} else {
|
|
100
133
|
try {
|
|
101
|
-
|
|
134
|
+
filesList = getFilesInMeshConfig(data, args.file);
|
|
102
135
|
} catch (err) {
|
|
103
136
|
this.log(err.message);
|
|
104
|
-
throw new Error('Input mesh
|
|
137
|
+
throw new Error('Input mesh config is not valid.');
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// if local files are present, import them in files array in meshConfig
|
|
141
|
+
if (filesList.length) {
|
|
142
|
+
try {
|
|
143
|
+
// minification of js will not be done for run command if debugging is enabled
|
|
144
|
+
data = await importFiles(
|
|
145
|
+
data,
|
|
146
|
+
filesList,
|
|
147
|
+
args.file,
|
|
148
|
+
flags.autoConfirmAction,
|
|
149
|
+
!flags.debug,
|
|
150
|
+
);
|
|
151
|
+
} catch (err) {
|
|
152
|
+
this.log(err.message);
|
|
153
|
+
throw new Error(
|
|
154
|
+
'Unable to import the files in the mesh config. Please check the file and try again.',
|
|
155
|
+
);
|
|
156
|
+
}
|
|
105
157
|
}
|
|
106
|
-
}
|
|
107
158
|
|
|
108
|
-
|
|
159
|
+
//Generating unique mesh id
|
|
160
|
+
meshId = UUID.newUuid().toString();
|
|
109
161
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
this.log(err.message);
|
|
114
|
-
throw new Error('Input mesh config is not valid.');
|
|
162
|
+
await validateMesh(data.meshConfig);
|
|
163
|
+
await buildMesh(meshId, data.meshConfig);
|
|
164
|
+
await compileMesh(meshId);
|
|
115
165
|
}
|
|
116
166
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
filesList,
|
|
124
|
-
args.file,
|
|
125
|
-
flags.autoConfirmAction,
|
|
126
|
-
!flags.debug,
|
|
127
|
-
);
|
|
128
|
-
} catch (err) {
|
|
129
|
-
this.log(err.message);
|
|
130
|
-
throw new Error(
|
|
131
|
-
'Unable to import the files in the mesh config. Please check the file and try again.',
|
|
132
|
-
);
|
|
167
|
+
let portNo;
|
|
168
|
+
|
|
169
|
+
//To set the port number using the environment file
|
|
170
|
+
if (process.env.PORT !== undefined) {
|
|
171
|
+
if (isNaN(process.env.PORT) || !Number.isInteger(parseInt(process.env.PORT))) {
|
|
172
|
+
throw new Error('PORT value in the .env file is not a valid integer');
|
|
133
173
|
}
|
|
174
|
+
|
|
175
|
+
portNo = process.env.PORT;
|
|
134
176
|
}
|
|
135
177
|
|
|
136
|
-
//
|
|
137
|
-
|
|
178
|
+
//To set the port number as the provided value in the command
|
|
179
|
+
if (flags.port !== undefined) {
|
|
180
|
+
portNo = flags.port;
|
|
181
|
+
}
|
|
138
182
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
183
|
+
//To set the default port to 5000
|
|
184
|
+
if (!portNo) {
|
|
185
|
+
portNo = 5000;
|
|
186
|
+
}
|
|
142
187
|
|
|
143
188
|
this.log(`Starting server on port : ${portNo}`);
|
|
144
189
|
await startGraphqlServer(meshId, portNo, flags.debug);
|
package/src/helpers.js
CHANGED
|
@@ -25,6 +25,7 @@ const path = require('path');
|
|
|
25
25
|
const { exec } = require('child_process');
|
|
26
26
|
const { stdout, stderr } = require('process');
|
|
27
27
|
const jsmin = require('jsmin').jsmin;
|
|
28
|
+
const { resolve: resolveAbsolutePath } = require('path');
|
|
28
29
|
|
|
29
30
|
const { DEV_CONSOLE_BASE_URL, DEV_CONSOLE_API_KEY, AIO_CLI_API_KEY } = CONSTANTS;
|
|
30
31
|
|
|
@@ -775,6 +776,87 @@ function startGraphqlServer(meshId, port, debug) {
|
|
|
775
776
|
});
|
|
776
777
|
}
|
|
777
778
|
|
|
779
|
+
/**
|
|
780
|
+
* Creates FileInfo object
|
|
781
|
+
*
|
|
782
|
+
* @param relativePath
|
|
783
|
+
* @returns
|
|
784
|
+
*/
|
|
785
|
+
function parseMaterializedFilePath(relativePath) {
|
|
786
|
+
const fileName = relativePath.replace(/^\.\//, '');
|
|
787
|
+
const file = path.basename(relativePath);
|
|
788
|
+
|
|
789
|
+
// js files are called using require, so we have to move it to relative to the artifact
|
|
790
|
+
if (path.extname(file) === '.js') {
|
|
791
|
+
relativePath = 'mesh-artifact/' + relativePath;
|
|
792
|
+
}
|
|
793
|
+
const absoluteFilePath = resolveAbsolutePath(relativePath);
|
|
794
|
+
const relative = path.dirname(absoluteFilePath);
|
|
795
|
+
const tenantTmpDir = {
|
|
796
|
+
relative,
|
|
797
|
+
absolute: resolveAbsolutePath(relative),
|
|
798
|
+
};
|
|
799
|
+
const relativeFilePath = relativePath;
|
|
800
|
+
return {
|
|
801
|
+
name: fileName,
|
|
802
|
+
relativePath: relativeFilePath,
|
|
803
|
+
absolutePath: absoluteFilePath,
|
|
804
|
+
parentDir: tenantTmpDir,
|
|
805
|
+
};
|
|
806
|
+
}
|
|
807
|
+
|
|
808
|
+
/**
|
|
809
|
+
* This function looks at a meshConfig to check if a files property exists and then materializes those files
|
|
810
|
+
* on the GraphQL server using the file.materializedPath
|
|
811
|
+
*
|
|
812
|
+
* @param config
|
|
813
|
+
*/
|
|
814
|
+
async function processFileConfig(config) {
|
|
815
|
+
if (config.files) {
|
|
816
|
+
await Promise.all(
|
|
817
|
+
config.files.map(async file => {
|
|
818
|
+
try {
|
|
819
|
+
if (file.materializedPath) {
|
|
820
|
+
const filePath = parseMaterializedFilePath(file.materializedPath);
|
|
821
|
+
try {
|
|
822
|
+
await fs.mkdirSync(filePath.parentDir.absolute, { recursive: true });
|
|
823
|
+
await fs.writeFileSync(filePath.absolutePath, file.content, { flag: 'w' });
|
|
824
|
+
} catch (e) {
|
|
825
|
+
throw new Error(
|
|
826
|
+
e,
|
|
827
|
+
`Materializing ${filePath.name} to ${filePath.absolutePath} failed`,
|
|
828
|
+
);
|
|
829
|
+
}
|
|
830
|
+
}
|
|
831
|
+
} catch (err) {
|
|
832
|
+
throw new Error(`Parsing file ${file.path} failed`);
|
|
833
|
+
}
|
|
834
|
+
}),
|
|
835
|
+
);
|
|
836
|
+
}
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
/**
|
|
840
|
+
* This function sets up the tenantFiles used in a particular mesh config
|
|
841
|
+
* into the tenantFiles folder
|
|
842
|
+
*
|
|
843
|
+
* @param config
|
|
844
|
+
*/
|
|
845
|
+
async function setUpTenantFiles(meshId) {
|
|
846
|
+
if (fs.existsSync(path.resolve(process.cwd(), 'mesh-artifact', meshId, 'files.json'))) {
|
|
847
|
+
if (!fs.existsSync(path.resolve(process.cwd(), 'mesh-artifact', 'tenantFiles'))) {
|
|
848
|
+
// Create tmp tenantFiles folder
|
|
849
|
+
fs.mkdirSync(path.resolve(process.cwd(), 'mesh-artifact', 'tenantFiles'));
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
const fileContents = fs
|
|
853
|
+
.readFileSync(path.resolve(process.cwd(), 'mesh-artifact', meshId, 'files.json'))
|
|
854
|
+
.toString();
|
|
855
|
+
const tenant = JSON.parse(fileContents);
|
|
856
|
+
await processFileConfig(tenant);
|
|
857
|
+
}
|
|
858
|
+
}
|
|
859
|
+
|
|
778
860
|
module.exports = {
|
|
779
861
|
objToString,
|
|
780
862
|
promptInput,
|
|
@@ -790,4 +872,5 @@ module.exports = {
|
|
|
790
872
|
runCliCommand,
|
|
791
873
|
updateFilesArray,
|
|
792
874
|
startGraphqlServer,
|
|
875
|
+
setUpTenantFiles,
|
|
793
876
|
};
|
package/src/lib/devConsole.js
CHANGED
|
@@ -5,6 +5,11 @@ const axios = require('axios');
|
|
|
5
5
|
|
|
6
6
|
const logger = require('../classes/logger');
|
|
7
7
|
const CONSTANTS = require('../constants');
|
|
8
|
+
const path = require('path');
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const util = require('util');
|
|
11
|
+
const exec = util.promisify(require('child_process').exec);
|
|
12
|
+
const contentDisposition = require('content-disposition');
|
|
8
13
|
|
|
9
14
|
const { DEV_CONSOLE_TRANSPORTER_API_KEY } = CONSTANTS;
|
|
10
15
|
|
|
@@ -768,6 +773,54 @@ const unsubscribeCredentialFromMeshService = async (
|
|
|
768
773
|
}
|
|
769
774
|
};
|
|
770
775
|
|
|
776
|
+
const getMeshArtifact = async (organizationId, projectId, workspaceId, workspaceName, meshId) => {
|
|
777
|
+
const { baseUrl: devConsoleUrl, accessToken, apiKey } = await getDevConsoleConfig();
|
|
778
|
+
const config = {
|
|
779
|
+
method: 'get',
|
|
780
|
+
url: `${devConsoleUrl}/organizations/${organizationId}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/artifact?API_KEY=${apiKey}`,
|
|
781
|
+
headers: {
|
|
782
|
+
'Authorization': `Bearer ${accessToken}`,
|
|
783
|
+
'x-request-id': global.requestId,
|
|
784
|
+
'workspaceName': workspaceName,
|
|
785
|
+
},
|
|
786
|
+
responseType: 'arraybuffer',
|
|
787
|
+
};
|
|
788
|
+
|
|
789
|
+
logger.info(
|
|
790
|
+
'Initiating GET %s',
|
|
791
|
+
`${devConsoleUrl}/organizations/${organizationId}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/artifact?API_KEY=${apiKey}`,
|
|
792
|
+
);
|
|
793
|
+
|
|
794
|
+
try {
|
|
795
|
+
const response = await axios(config);
|
|
796
|
+
|
|
797
|
+
if (response && response.status === 200) {
|
|
798
|
+
// Access the response data as an ArrayBuffer
|
|
799
|
+
const octetData = response.data;
|
|
800
|
+
const contentDispositionHeader = response.headers['content-disposition'];
|
|
801
|
+
|
|
802
|
+
const disposition = contentDisposition.parse(contentDispositionHeader);
|
|
803
|
+
const filename = disposition.parameters.filename;
|
|
804
|
+
|
|
805
|
+
// Save the octet-stream into a file
|
|
806
|
+
fs.writeFileSync(filename, octetData);
|
|
807
|
+
|
|
808
|
+
//Extract the file contents from the tar file
|
|
809
|
+
await exec(`tar -xf ${filename} -C ${path.resolve(process.cwd())}`);
|
|
810
|
+
|
|
811
|
+
//Delete the gzip compressed file
|
|
812
|
+
await exec(`rm ${filename}`);
|
|
813
|
+
} else {
|
|
814
|
+
throw new Error(`Something went wrong: 'Unable to get mesh artifact')}`);
|
|
815
|
+
}
|
|
816
|
+
} catch (error) {
|
|
817
|
+
throw new Error(
|
|
818
|
+
'Unable to get mesh artifact from Schema Management Service: %s',
|
|
819
|
+
error.message,
|
|
820
|
+
);
|
|
821
|
+
}
|
|
822
|
+
};
|
|
823
|
+
|
|
771
824
|
module.exports = {
|
|
772
825
|
getApiKeyCredential,
|
|
773
826
|
describeMesh,
|
|
@@ -781,4 +834,5 @@ module.exports = {
|
|
|
781
834
|
subscribeCredentialToServices,
|
|
782
835
|
subscribeCredentialToMeshService,
|
|
783
836
|
unsubscribeCredentialFromMeshService,
|
|
837
|
+
getMeshArtifact,
|
|
784
838
|
};
|
package/src/server.js
CHANGED
|
@@ -157,11 +157,15 @@ app.listen(
|
|
|
157
157
|
port: portNo,
|
|
158
158
|
},
|
|
159
159
|
async err => {
|
|
160
|
-
|
|
161
|
-
|
|
160
|
+
try {
|
|
161
|
+
if (err) {
|
|
162
|
+
throw new Error(`Server setup error: ${err.message}`);
|
|
163
|
+
}
|
|
164
|
+
yogaServer = await getYogaServer();
|
|
165
|
+
} catch (error) {
|
|
166
|
+
console.error(error);
|
|
162
167
|
process.exit(1);
|
|
163
168
|
}
|
|
164
|
-
yogaServer = await getYogaServer();
|
|
165
169
|
|
|
166
170
|
console.log(`Server is running on http://localhost:${portNo}/graphql`);
|
|
167
171
|
},
|
package/src/utils.js
CHANGED
|
@@ -51,6 +51,11 @@ const debugFlag = Flags.boolean({
|
|
|
51
51
|
default: false,
|
|
52
52
|
});
|
|
53
53
|
|
|
54
|
+
const selectFlag = Flags.boolean({
|
|
55
|
+
description: 'Retrieve existing artifacts from the mesh',
|
|
56
|
+
default: false,
|
|
57
|
+
});
|
|
58
|
+
|
|
54
59
|
/**
|
|
55
60
|
* Parse the meshConfig and get the list of (local) files to be imported
|
|
56
61
|
*
|
|
@@ -399,4 +404,5 @@ module.exports = {
|
|
|
399
404
|
getAppRootDir,
|
|
400
405
|
portNoFlag,
|
|
401
406
|
debugFlag,
|
|
407
|
+
selectFlag,
|
|
402
408
|
};
|
package/oclif.manifest.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":"3.2.0","commands":{"PLUGINNAME":{"id":"PLUGINNAME","description":"Your description here","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":["$ aio PLUGINNAME:some_command"],"flags":{"someflag":{"name":"someflag","type":"option","char":"f","description":"this is some flag"}},"args":[]},"api-mesh:create":{"id":"api-mesh:create","description":"Create a mesh with the given config.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false},"json":{"name":"json","type":"boolean","description":"Output JSON","allowNo":false},"env":{"name":"env","type":"option","char":"e","description":"Path to env file","default":".env"}},"args":[{"name":"file"}]},"api-mesh:delete":{"id":"api-mesh:delete","description":"Delete the config of a given mesh","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false}},"args":[]},"api-mesh:describe":{"id":"api-mesh:describe","description":"Get details of a mesh","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false}},"args":[]},"api-mesh:get":{"id":"api-mesh:get","description":"Get the config of a given mesh","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"json":{"name":"json","type":"boolean","description":"Output JSON","allowNo":false}},"args":[{"name":"file"}]},"api-mesh:init":{"id":"api-mesh:init","description":"This command will create a workspace where you can organise your API mesh configuration and other files","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":[{"description":"API mesh workspace init","command":"aio api-mesh init commerce-mesh"},{"description":"API mesh workspace init with flags","command":"aio api-mesh init commerce-mesh --path ./mesh_projects/test_mesh --git y --packageManager yarn"}],"flags":{"path":{"name":"path","type":"option","char":"p","default":"."},"packageManager":{"name":"packageManager","type":"option","char":"m","options":["npm","yarn"]},"git":{"name":"git","type":"option","char":"g","options":["y","n"]}},"args":[{"name":"projectName","description":"Project name","required":true}]},"api-mesh:run":{"id":"api-mesh:run","description":"Run a local development server that builds and compiles a mesh locally","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":[],"flags":{"port":{"name":"port","type":"option","char":"p","description":"Port number for the local dev server"},"debug":{"name":"debug","type":"boolean","description":"Enable debugging mode","allowNo":false},"env":{"name":"env","type":"option","char":"e","description":"Path to env file","default":".env"},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false}},"args":[{"name":"file","description":"Mesh File"}]},"api-mesh:status":{"id":"api-mesh:status","description":"Get a mesh status with a given meshid.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false}},"args":[]},"api-mesh:update":{"id":"api-mesh:update","description":"Update a mesh with the given config.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false},"autoConfirmAction":{"name":"autoConfirmAction","type":"boolean","char":"c","description":"Auto confirm action prompt. CLI will not check for user approval before executing the action.","allowNo":false},"env":{"name":"env","type":"option","char":"e","description":"Path to env file","default":".env"}},"args":[{"name":"file"}]},"api-mesh:source:discover":{"id":"api-mesh:source:discover","description":"Return the list of avaliable sources","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"flags":{"confirm":{"name":"confirm","type":"boolean","char":"c","description":"Auto confirm install action prompt. CLI will not check ask user to install source.","allowNo":false}},"args":[]},"api-mesh:source:get":{"id":"api-mesh:source:get","description":"Command returns the content of a specific source.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":["$ aio api-mesh:source:get -s=<version>@<source_name>","$ aio api-mesh:source:get -s<source_name>","$ aio api-mesh:source:get -m"],"flags":{"confirm":{"name":"confirm","type":"boolean","char":"c","description":"Auto confirm print action prompt. CLI will not check ask user to print source.","allowNo":false},"source":{"name":"source","type":"option","char":"s","description":"Source name"},"multiple":{"name":"multiple","type":"boolean","char":"m","description":"Select multiple sources","allowNo":false}},"args":[]},"api-mesh:source:install":{"id":"api-mesh:source:install","description":"Command to install the source to your API mesh.","pluginName":"@adobe/aio-cli-plugin-api-mesh","pluginType":"core","aliases":[],"examples":["$ aio api-mesh:source:install <version>@<source_name>","$ aio api-mesh:source:install <source_name> -v <variable_name>=<variable_value>","$ aio api-mesh:source:install <source_name> -f <path_to_variables_file>"],"flags":{"source":{"name":"source","type":"option","char":"s","description":"Source name"},"confirm":{"name":"confirm","type":"boolean","char":"c","description":"Auto confirm override action prompt. CLI will not check ask user to override source.","allowNo":false},"variable":{"name":"variable","type":"option","char":"v","description":"Variables required for the source"},"variable-file":{"name":"variable-file","type":"option","char":"f","description":"Variables file path"},"ignoreCache":{"name":"ignoreCache","type":"boolean","char":"i","description":"Ignore cache and force manual org -> project -> workspace selection","allowNo":false}},"args":[{"name":"source"}]}}}
|