@adobe/aio-cli-plugin-api-mesh 5.0.0-alpha → 5.0.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 +13 -3
- package/src/commands/api-mesh/__tests__/create.test.js +265 -195
- package/src/commands/api-mesh/__tests__/describe.test.js +15 -0
- package/src/commands/api-mesh/__tests__/get.test.js +72 -3
- package/src/commands/api-mesh/__tests__/run.test.js +22 -19
- package/src/commands/api-mesh/create.js +2 -1
- package/src/commands/api-mesh/describe.js +1 -1
- package/src/commands/api-mesh/get.js +5 -2
- package/src/commands/api-mesh/init.js +2 -0
- package/src/commands/api-mesh/run.js +32 -6
- package/src/commands/api-mesh/status.js +2 -0
- package/src/cors.js +28 -0
- package/src/fixPlugins.js +28 -0
- package/src/helpers.js +71 -4
- package/src/hooks/versionCompare.js +23 -0
- package/src/index.js +44 -0
- package/src/plugins/complianceHeaders/complianceHeaders.js +55 -0
- package/src/plugins/complianceHeaders/index.js +2 -0
- package/src/plugins/httpDetailsExtensions/LICENSE +21 -0
- package/src/plugins/httpDetailsExtensions/index.js +81 -0
- package/src/secrets.js +34 -0
- package/src/served.js +22 -0
- package/src/server.js +36 -198
- package/src/serverUtils.js +3 -3
- package/src/templates/wrangler.toml +14 -0
- package/src/utils/logger.js +42 -0
- package/src/utils/requestId.js +26 -0
- package/src/wranglerServer.js +80 -0
|
@@ -193,7 +193,30 @@ describe('get command tests', () => {
|
|
|
193
193
|
verbose: true,
|
|
194
194
|
});
|
|
195
195
|
expect(initRequestId).toHaveBeenCalled();
|
|
196
|
-
expect(runResult).
|
|
196
|
+
expect(runResult).toMatchInlineSnapshot(`
|
|
197
|
+
{
|
|
198
|
+
"imsOrgId": "1234",
|
|
199
|
+
"mesh": {
|
|
200
|
+
"meshConfig": {
|
|
201
|
+
"sources": [
|
|
202
|
+
{
|
|
203
|
+
"handler": {
|
|
204
|
+
"graphql": {
|
|
205
|
+
"endpoint": "<gql_endpoint>",
|
|
206
|
+
},
|
|
207
|
+
},
|
|
208
|
+
"name": "<api_name>",
|
|
209
|
+
},
|
|
210
|
+
],
|
|
211
|
+
},
|
|
212
|
+
},
|
|
213
|
+
"meshId": "dummy_meshId",
|
|
214
|
+
"meshUrl": "https://edge-sandbox-graph.adobe.io/api/dummy_meshId/graphql",
|
|
215
|
+
"projectId": "5678",
|
|
216
|
+
"workspaceId": "123456789",
|
|
217
|
+
"workspaceName": "Workspace01",
|
|
218
|
+
}
|
|
219
|
+
`);
|
|
197
220
|
expect(logSpy.mock.calls).toMatchInlineSnapshot(`
|
|
198
221
|
[
|
|
199
222
|
[
|
|
@@ -240,7 +263,30 @@ describe('get command tests', () => {
|
|
|
240
263
|
|
|
241
264
|
const runResult = await GetCommand.run();
|
|
242
265
|
|
|
243
|
-
expect(runResult).
|
|
266
|
+
expect(runResult).toMatchInlineSnapshot(`
|
|
267
|
+
{
|
|
268
|
+
"imsOrgId": "1234",
|
|
269
|
+
"mesh": {
|
|
270
|
+
"meshConfig": {
|
|
271
|
+
"sources": [
|
|
272
|
+
{
|
|
273
|
+
"handler": {
|
|
274
|
+
"graphql": {
|
|
275
|
+
"endpoint": "<gql_endpoint>",
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
"name": "<api_name>",
|
|
279
|
+
},
|
|
280
|
+
],
|
|
281
|
+
},
|
|
282
|
+
},
|
|
283
|
+
"meshId": "dummy_meshId",
|
|
284
|
+
"meshUrl": "https://edge-sandbox-graph.adobe.io/api/dummy_meshId/graphql",
|
|
285
|
+
"projectId": "5678",
|
|
286
|
+
"workspaceId": "123456789",
|
|
287
|
+
"workspaceName": "Workspace01",
|
|
288
|
+
}
|
|
289
|
+
`);
|
|
244
290
|
expect(writeFile.mock.calls).toMatchInlineSnapshot(`
|
|
245
291
|
[
|
|
246
292
|
[
|
|
@@ -294,7 +340,30 @@ describe('get command tests', () => {
|
|
|
294
340
|
});
|
|
295
341
|
const runResult = await GetCommand.run();
|
|
296
342
|
|
|
297
|
-
expect(runResult).
|
|
343
|
+
expect(runResult).toMatchInlineSnapshot(`
|
|
344
|
+
{
|
|
345
|
+
"imsOrgId": "1234",
|
|
346
|
+
"mesh": {
|
|
347
|
+
"meshConfig": {
|
|
348
|
+
"sources": [
|
|
349
|
+
{
|
|
350
|
+
"handler": {
|
|
351
|
+
"graphql": {
|
|
352
|
+
"endpoint": "<gql_endpoint>",
|
|
353
|
+
},
|
|
354
|
+
},
|
|
355
|
+
"name": "<api_name>",
|
|
356
|
+
},
|
|
357
|
+
],
|
|
358
|
+
},
|
|
359
|
+
},
|
|
360
|
+
"meshId": "dummy_meshId",
|
|
361
|
+
"meshUrl": "https://edge-sandbox-graph.adobe.io/api/dummy_meshId/graphql",
|
|
362
|
+
"projectId": "5678",
|
|
363
|
+
"workspaceId": "123456789",
|
|
364
|
+
"workspaceName": "Workspace01",
|
|
365
|
+
}
|
|
366
|
+
`);
|
|
298
367
|
expect(writeFile.mock.calls).toMatchInlineSnapshot(`
|
|
299
368
|
[
|
|
300
369
|
[
|
|
@@ -12,7 +12,6 @@ governing permissions and limitations under the License.
|
|
|
12
12
|
|
|
13
13
|
const RunCommand = require('../run');
|
|
14
14
|
const {
|
|
15
|
-
startGraphqlServer,
|
|
16
15
|
interpolateMesh,
|
|
17
16
|
importFiles,
|
|
18
17
|
promptConfirm,
|
|
@@ -20,6 +19,7 @@ const {
|
|
|
20
19
|
initSdk,
|
|
21
20
|
writeSecretsFile,
|
|
22
21
|
} = require('../../../helpers');
|
|
22
|
+
const { runServer } = require('../../../server');
|
|
23
23
|
const { getMeshId, getMeshArtifact } = require('../../../lib/devConsole');
|
|
24
24
|
require('@adobe-apimesh/mesh-builder');
|
|
25
25
|
|
|
@@ -31,7 +31,6 @@ jest.mock('../../../helpers', () => ({
|
|
|
31
31
|
workspaceName: 'mockWorkspaceTitle',
|
|
32
32
|
}),
|
|
33
33
|
initRequestId: jest.fn().mockResolvedValue({}),
|
|
34
|
-
startGraphqlServer: jest.fn().mockResolvedValue({}),
|
|
35
34
|
interpolateMesh: jest.fn().mockResolvedValue({}),
|
|
36
35
|
importFiles: jest.fn().mockResolvedValue(),
|
|
37
36
|
promptConfirm: jest.fn().mockResolvedValue(true),
|
|
@@ -39,6 +38,10 @@ jest.mock('../../../helpers', () => ({
|
|
|
39
38
|
writeSecretsFile: jest.fn().mockResolvedValue(),
|
|
40
39
|
}));
|
|
41
40
|
|
|
41
|
+
jest.mock('../../../server', () => ({
|
|
42
|
+
runServer: jest.fn().mockResolvedValue(),
|
|
43
|
+
}));
|
|
44
|
+
|
|
42
45
|
jest.mock('../../../lib/devConsole', () => ({
|
|
43
46
|
getMeshId: jest.fn().mockResolvedValue('mockMeshId'),
|
|
44
47
|
getMeshArtifact: jest.fn().mockResolvedValue(),
|
|
@@ -91,6 +94,10 @@ describe('run command tests', () => {
|
|
|
91
94
|
platformSpy.mockRestore();
|
|
92
95
|
});
|
|
93
96
|
|
|
97
|
+
beforeAll(() => {
|
|
98
|
+
jest.spyOn(RunCommand.prototype, 'copyMeshContent').mockImplementation(() => {});
|
|
99
|
+
});
|
|
100
|
+
|
|
94
101
|
test('snapshot run command description', () => {
|
|
95
102
|
expect(RunCommand.description).toMatchInlineSnapshot(
|
|
96
103
|
`"Run a local development server that builds and compiles a mesh locally"`,
|
|
@@ -189,11 +196,7 @@ describe('run command tests', () => {
|
|
|
189
196
|
parseSpy.mockResolvedValue(parseOutput);
|
|
190
197
|
|
|
191
198
|
await RunCommand.run();
|
|
192
|
-
expect(
|
|
193
|
-
expect.anything(),
|
|
194
|
-
parseOutput.flags.port,
|
|
195
|
-
false,
|
|
196
|
-
);
|
|
199
|
+
expect(runServer).toHaveBeenCalledWith(parseOutput.flags.port);
|
|
197
200
|
});
|
|
198
201
|
|
|
199
202
|
test('should use the port number provided in the .env file if there is no port', async () => {
|
|
@@ -210,7 +213,7 @@ describe('run command tests', () => {
|
|
|
210
213
|
parseSpy.mockResolvedValue(parseOutput);
|
|
211
214
|
|
|
212
215
|
await RunCommand.run();
|
|
213
|
-
expect(
|
|
216
|
+
expect(runServer).toHaveBeenCalledWith(process.env.PORT);
|
|
214
217
|
});
|
|
215
218
|
|
|
216
219
|
test('should use the default port if port number is not provided explicitly', async () => {
|
|
@@ -226,7 +229,7 @@ describe('run command tests', () => {
|
|
|
226
229
|
parseSpy.mockResolvedValue(parseOutput);
|
|
227
230
|
|
|
228
231
|
await RunCommand.run();
|
|
229
|
-
expect(
|
|
232
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
230
233
|
});
|
|
231
234
|
|
|
232
235
|
test('should return error for run command if the mesh has placeholders and env file provided using --env flag is not found', async () => {
|
|
@@ -393,7 +396,7 @@ describe('run command tests', () => {
|
|
|
393
396
|
});
|
|
394
397
|
|
|
395
398
|
await RunCommand.run();
|
|
396
|
-
expect(
|
|
399
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
397
400
|
});
|
|
398
401
|
|
|
399
402
|
// file import tests
|
|
@@ -439,7 +442,7 @@ describe('run command tests', () => {
|
|
|
439
442
|
});
|
|
440
443
|
|
|
441
444
|
await RunCommand.run();
|
|
442
|
-
expect(
|
|
445
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
443
446
|
});
|
|
444
447
|
|
|
445
448
|
test('should fail if the file name is more than 25 characters', async () => {
|
|
@@ -615,7 +618,7 @@ describe('run command tests', () => {
|
|
|
615
618
|
});
|
|
616
619
|
|
|
617
620
|
await RunCommand.run();
|
|
618
|
-
expect(
|
|
621
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
619
622
|
});
|
|
620
623
|
|
|
621
624
|
test('should override if prompt returns Yes, if there is files array', async () => {
|
|
@@ -662,7 +665,7 @@ describe('run command tests', () => {
|
|
|
662
665
|
|
|
663
666
|
await RunCommand.run();
|
|
664
667
|
|
|
665
|
-
expect(
|
|
668
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
666
669
|
});
|
|
667
670
|
|
|
668
671
|
test('should pass for a fully-qualified meshConfig even if the file does not exist in fileSystem', async () => {
|
|
@@ -709,7 +712,7 @@ describe('run command tests', () => {
|
|
|
709
712
|
});
|
|
710
713
|
|
|
711
714
|
await RunCommand.run();
|
|
712
|
-
expect(
|
|
715
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
713
716
|
});
|
|
714
717
|
|
|
715
718
|
test('should pass if the file is located in subdirectory of mesh directory', async () => {
|
|
@@ -755,7 +758,7 @@ describe('run command tests', () => {
|
|
|
755
758
|
|
|
756
759
|
await RunCommand.run();
|
|
757
760
|
|
|
758
|
-
expect(
|
|
761
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
759
762
|
});
|
|
760
763
|
|
|
761
764
|
test('should fail if the file is outside the workspace directory', async () => {
|
|
@@ -926,7 +929,7 @@ describe('run command tests', () => {
|
|
|
926
929
|
|
|
927
930
|
await RunCommand.run();
|
|
928
931
|
expect(writeSecretsFile).toHaveBeenCalled();
|
|
929
|
-
expect(
|
|
932
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
930
933
|
});
|
|
931
934
|
|
|
932
935
|
test('should return error if ran with secrets against windows platform with batch variables', async () => {
|
|
@@ -964,7 +967,7 @@ describe('run command tests', () => {
|
|
|
964
967
|
|
|
965
968
|
await RunCommand.run();
|
|
966
969
|
expect(writeSecretsFile).toHaveBeenCalled();
|
|
967
|
-
expect(
|
|
970
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
968
971
|
});
|
|
969
972
|
|
|
970
973
|
test('should pass if ran with secrets against darwin(macOS) platform with batch variables', async () => {
|
|
@@ -979,7 +982,7 @@ describe('run command tests', () => {
|
|
|
979
982
|
|
|
980
983
|
await RunCommand.run();
|
|
981
984
|
expect(writeSecretsFile).toHaveBeenCalled();
|
|
982
|
-
expect(
|
|
985
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
983
986
|
});
|
|
984
987
|
|
|
985
988
|
test('should escape variables that are preceded by backslash symbol', async () => {
|
|
@@ -996,6 +999,6 @@ describe('run command tests', () => {
|
|
|
996
999
|
'Home: rootPath\nHomeString: $HOME\nHomeWithSlash: \\rootPath\nHomeStringWithSlash: \\$HOME\n',
|
|
997
1000
|
expect.anything(),
|
|
998
1001
|
);
|
|
999
|
-
expect(
|
|
1002
|
+
expect(runServer).toHaveBeenCalledWith(defaultPort);
|
|
1000
1003
|
});
|
|
1001
1004
|
});
|
|
@@ -59,6 +59,7 @@ class CreateCommand extends Command {
|
|
|
59
59
|
const envFilePath = await flags.env;
|
|
60
60
|
const secretsFilePath = await flags.secrets;
|
|
61
61
|
const {
|
|
62
|
+
imsOrgId,
|
|
62
63
|
imsOrgCode,
|
|
63
64
|
projectId,
|
|
64
65
|
workspaceId,
|
|
@@ -156,7 +157,7 @@ class CreateCommand extends Command {
|
|
|
156
157
|
|
|
157
158
|
// When renaming the return values, make sure to make necessary changes to
|
|
158
159
|
// template adobe/generator-app-api-mesh since it relies on "mesh"
|
|
159
|
-
return { mesh };
|
|
160
|
+
return { ...mesh, meshUrl, imsOrgId, projectId, workspaceId, workspaceName };
|
|
160
161
|
} else {
|
|
161
162
|
this.error(`Unable to create a mesh. Please try again. RequestId: ${global.requestId}`, {
|
|
162
163
|
exit: false,
|
|
@@ -49,7 +49,7 @@ class DescribeCommand extends Command {
|
|
|
49
49
|
this.log('Mesh ID: %s', meshId);
|
|
50
50
|
this.log('Mesh Endpoint: %s', meshUrl);
|
|
51
51
|
|
|
52
|
-
return meshDetails;
|
|
52
|
+
return { ...meshDetails, meshUrl, imsOrgId, projectId, workspaceId, workspaceName };
|
|
53
53
|
} else {
|
|
54
54
|
logger.error(
|
|
55
55
|
`Unable to get mesh details. Please check the details and try again. RequestId: ${global.requestId}`,
|
|
@@ -16,6 +16,7 @@ const logger = require('../../classes/logger');
|
|
|
16
16
|
const { initSdk, initRequestId } = require('../../helpers');
|
|
17
17
|
const { ignoreCacheFlag, jsonFlag } = require('../../utils');
|
|
18
18
|
const { getMeshId, getMesh } = require('../../lib/devConsole');
|
|
19
|
+
const { buildMeshUrl } = require('../../urlBuilder');
|
|
19
20
|
|
|
20
21
|
require('dotenv').config();
|
|
21
22
|
class GetCommand extends Command {
|
|
@@ -37,7 +38,7 @@ class GetCommand extends Command {
|
|
|
37
38
|
const ignoreCache = await flags.ignoreCache;
|
|
38
39
|
const json = await flags.json;
|
|
39
40
|
|
|
40
|
-
const { imsOrgCode, projectId, workspaceId, workspaceName } = await initSdk({
|
|
41
|
+
const { imsOrgId, imsOrgCode, projectId, workspaceId, workspaceName } = await initSdk({
|
|
41
42
|
ignoreCache,
|
|
42
43
|
verbose: !json,
|
|
43
44
|
});
|
|
@@ -59,6 +60,8 @@ class GetCommand extends Command {
|
|
|
59
60
|
if (mesh) {
|
|
60
61
|
this.log('Successfully retrieved mesh %s', JSON.stringify(mesh, null, 2));
|
|
61
62
|
|
|
63
|
+
const meshUrl = buildMeshUrl(meshId, workspaceName);
|
|
64
|
+
|
|
62
65
|
if (args.file) {
|
|
63
66
|
try {
|
|
64
67
|
const { meshConfig } = mesh;
|
|
@@ -72,7 +75,7 @@ class GetCommand extends Command {
|
|
|
72
75
|
}
|
|
73
76
|
}
|
|
74
77
|
|
|
75
|
-
return mesh;
|
|
78
|
+
return { ...mesh, meshUrl, imsOrgId, projectId, workspaceId, workspaceName };
|
|
76
79
|
} else {
|
|
77
80
|
logger.error(
|
|
78
81
|
`Unable to get mesh with the ID ${meshId}. Check the mesh ID and try again. RequestId: ${global.requestId}`,
|
|
@@ -108,6 +108,7 @@ class InitCommand extends Command {
|
|
|
108
108
|
const readmePath = `${getAppRootDir()}/src/templates/readme.md`;
|
|
109
109
|
const sampleMeshConfigPath = `${getAppRootDir()}/src/templates/mesh.json`;
|
|
110
110
|
const newRelicConfigPath = `${getAppRootDir()}/src/templates/newrelic.cjs`;
|
|
111
|
+
const wranglerTomlTemplate = `${getAppRootDir()}/src/templates/wrangler.toml`;
|
|
111
112
|
const shouldCreateWorkspace = await promptConfirm(
|
|
112
113
|
`Do you want to create the workspace in ${absolutePath}`,
|
|
113
114
|
);
|
|
@@ -180,6 +181,7 @@ class InitCommand extends Command {
|
|
|
180
181
|
await this.cloneFile(readmePath, `${absolutePath}/README.md`);
|
|
181
182
|
await this.cloneFile(sampleMeshConfigPath, `${absolutePath}/mesh.json`);
|
|
182
183
|
await this.cloneFile(newRelicConfigPath, `${absolutePath}/newrelic.cjs`);
|
|
184
|
+
await this.cloneFile(wranglerTomlTemplate, `${absolutePath}/wrangler.toml`);
|
|
183
185
|
|
|
184
186
|
this.log(`Installing dependencies`);
|
|
185
187
|
|
|
@@ -26,12 +26,10 @@ const {
|
|
|
26
26
|
} = require('../../utils');
|
|
27
27
|
const meshBuilder = require('@adobe-apimesh/mesh-builder');
|
|
28
28
|
const fs = require('fs');
|
|
29
|
-
const UUID = require('../../uuid');
|
|
30
29
|
const path = require('path');
|
|
31
30
|
const {
|
|
32
31
|
initSdk,
|
|
33
32
|
initRequestId,
|
|
34
|
-
startGraphqlServer,
|
|
35
33
|
importFiles,
|
|
36
34
|
setUpTenantFiles,
|
|
37
35
|
writeSecretsFile,
|
|
@@ -39,6 +37,8 @@ const {
|
|
|
39
37
|
const logger = require('../../classes/logger');
|
|
40
38
|
const { getMeshId, getMeshArtifact } = require('../../lib/devConsole');
|
|
41
39
|
require('dotenv').config();
|
|
40
|
+
const { runServer } = require('../../server');
|
|
41
|
+
const { fixPlugins } = require('../../fixPlugins');
|
|
42
42
|
|
|
43
43
|
const { validateMesh, buildMesh, compileMesh } = meshBuilder.default;
|
|
44
44
|
|
|
@@ -163,13 +163,12 @@ class RunCommand extends Command {
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
165
|
//Generating unique mesh id
|
|
166
|
-
meshId =
|
|
166
|
+
meshId = 'testMesh';
|
|
167
167
|
|
|
168
168
|
await validateMesh(data.meshConfig);
|
|
169
169
|
await buildMesh(meshId, data.meshConfig);
|
|
170
170
|
await compileMesh(meshId);
|
|
171
171
|
}
|
|
172
|
-
|
|
173
172
|
let portNo;
|
|
174
173
|
//secrets management
|
|
175
174
|
if (secretsFilePath) {
|
|
@@ -183,6 +182,8 @@ class RunCommand extends Command {
|
|
|
183
182
|
}
|
|
184
183
|
}
|
|
185
184
|
|
|
185
|
+
await this.copyMeshContent(meshId);
|
|
186
|
+
|
|
186
187
|
//To set the port number using the environment file
|
|
187
188
|
if (process.env.PORT !== undefined) {
|
|
188
189
|
if (isNaN(process.env.PORT) || !Number.isInteger(parseInt(process.env.PORT))) {
|
|
@@ -201,9 +202,9 @@ class RunCommand extends Command {
|
|
|
201
202
|
if (!portNo) {
|
|
202
203
|
portNo = 5000;
|
|
203
204
|
}
|
|
204
|
-
|
|
205
205
|
this.log(`Starting server on port : ${portNo}`);
|
|
206
|
-
await
|
|
206
|
+
await runServer(portNo);
|
|
207
|
+
this.log(`Server is running on http://localhost:${portNo}/graphql`);
|
|
207
208
|
} else {
|
|
208
209
|
throw new Error(
|
|
209
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.',
|
|
@@ -213,6 +214,31 @@ class RunCommand extends Command {
|
|
|
213
214
|
this.error(error.message);
|
|
214
215
|
}
|
|
215
216
|
}
|
|
217
|
+
|
|
218
|
+
async copyMeshContent(meshId) {
|
|
219
|
+
// Remove mesh artifact directory if exists
|
|
220
|
+
if (fs.existsSync('.mesh')) {
|
|
221
|
+
fs.rmSync('.mesh', { recursive: true });
|
|
222
|
+
}
|
|
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 });
|
|
228
|
+
}
|
|
229
|
+
// Move built tenant files if exists
|
|
230
|
+
if (fs.existsSync('mesh-artifact/tenantFiles')) {
|
|
231
|
+
fs.cpSync('mesh-artifact/tenantFiles', '.mesh/tenantFiles', { recursive: true });
|
|
232
|
+
fs.renameSync('mesh-artifact/tenantFiles', 'tenantFiles');
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
await fixPlugins('.mesh/index.js');
|
|
236
|
+
|
|
237
|
+
if (fs.existsSync(`${__dirname}/../../../.mesh`)) {
|
|
238
|
+
fs.rmSync(`${__dirname}/../../../.mesh`, { recursive: true });
|
|
239
|
+
}
|
|
240
|
+
fs.cpSync('.mesh', `${__dirname}/../../../.mesh`, { recursive: true });
|
|
241
|
+
}
|
|
216
242
|
}
|
|
217
243
|
|
|
218
244
|
module.exports = RunCommand;
|
|
@@ -46,6 +46,8 @@ class StatusCommand extends Command {
|
|
|
46
46
|
this.log(''.padEnd(102, '*'));
|
|
47
47
|
await this.displayMeshStatus(mesh, imsOrgCode, projectId, workspaceId);
|
|
48
48
|
this.log(''.padEnd(102, '*'));
|
|
49
|
+
|
|
50
|
+
return mesh;
|
|
49
51
|
} catch (err) {
|
|
50
52
|
// Error occurred while fetching/displaying the mesh status
|
|
51
53
|
this.error(
|
package/src/cors.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Get default CORS options.
|
|
3
|
+
* @param env Environment.
|
|
4
|
+
*/
|
|
5
|
+
const getDefaultCorsOptions = env => {
|
|
6
|
+
return env.CORS_DEFAULT_URL
|
|
7
|
+
? {
|
|
8
|
+
origin: env.CORS_DEFAULT_URL,
|
|
9
|
+
}
|
|
10
|
+
: {};
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get CORS options. Merges default CORS options with custom specific options if present in the mesh configuration.
|
|
15
|
+
* Custom CORS options overwrite the default options to ensure that specific requirements can be met without altering
|
|
16
|
+
* the default configuration.
|
|
17
|
+
* @param env Environment.
|
|
18
|
+
* @param meshConfig Mesh configuration.
|
|
19
|
+
*/
|
|
20
|
+
const getCorsOptions = (env, meshConfig) => {
|
|
21
|
+
const defaultCorsOptions = getDefaultCorsOptions(env);
|
|
22
|
+
return {
|
|
23
|
+
...defaultCorsOptions,
|
|
24
|
+
...meshConfig.responseConfig?.CORS,
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
module.exports = { getCorsOptions };
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/* eslint-disable no-console */
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
/**
|
|
4
|
+
* Modifies `index.js` of a mesh artifact to mutate plugin references for edge compatibility. Current forces
|
|
5
|
+
* `@graphql-mesh/plugin-http-details-extensions` to resolve to local fork instead.
|
|
6
|
+
*/
|
|
7
|
+
async function fixPlugins(meshArtifactPath) {
|
|
8
|
+
try {
|
|
9
|
+
console.log('Modifying mesh artifact to fix plugins for edge compatibility.');
|
|
10
|
+
const data = fs.readFileSync(meshArtifactPath, 'utf8');
|
|
11
|
+
const updatedData = data.replace(
|
|
12
|
+
/@graphql-mesh\/plugin-http-details-extensions/g,
|
|
13
|
+
'../src/plugins/httpDetailsExtensions',
|
|
14
|
+
);
|
|
15
|
+
fs.writeFileSync(meshArtifactPath, updatedData, 'utf8');
|
|
16
|
+
} catch (err) {
|
|
17
|
+
console.error(err);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Execute fixPlugins if run directly from CLI
|
|
22
|
+
if (require.main === module) {
|
|
23
|
+
fixPlugins();
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
module.exports = {
|
|
27
|
+
fixPlugins,
|
|
28
|
+
};
|
package/src/helpers.js
CHANGED
|
@@ -17,15 +17,17 @@ const { getToken, context } = require('@adobe/aio-lib-ims');
|
|
|
17
17
|
const { CLI } = require('@adobe/aio-lib-ims/src/context');
|
|
18
18
|
const libConsoleCLI = require('@adobe/aio-cli-lib-console');
|
|
19
19
|
const { getCliEnv } = require('@adobe/aio-lib-env');
|
|
20
|
-
|
|
21
|
-
const logger = require('../src/classes/logger');
|
|
22
|
-
const { UUID } = require('./classes/UUID');
|
|
23
|
-
const CONSTANTS = require('./constants');
|
|
20
|
+
const axios = require('axios');
|
|
24
21
|
const path = require('path');
|
|
25
22
|
const { exec } = require('child_process');
|
|
26
23
|
const { stdout, stderr } = require('process');
|
|
27
24
|
const jsmin = require('jsmin').jsmin;
|
|
28
25
|
const { resolve: resolveAbsolutePath } = require('path');
|
|
26
|
+
const { compareVersions } = require('compare-versions');
|
|
27
|
+
|
|
28
|
+
const logger = require('../src/classes/logger');
|
|
29
|
+
const { UUID } = require('./classes/UUID');
|
|
30
|
+
const CONSTANTS = require('./constants');
|
|
29
31
|
|
|
30
32
|
const { DEV_CONSOLE_BASE_URL, DEV_CONSOLE_API_KEY, AIO_CLI_API_KEY } = CONSTANTS;
|
|
31
33
|
|
|
@@ -880,6 +882,69 @@ async function writeSecretsFile(secretsData, meshId) {
|
|
|
880
882
|
}
|
|
881
883
|
}
|
|
882
884
|
|
|
885
|
+
/**
|
|
886
|
+
*
|
|
887
|
+
* This function fetches current installed version the system and the latest version from npm
|
|
888
|
+
*
|
|
889
|
+
* @param {*} installedPlugins
|
|
890
|
+
* @returns { currentVersion: string, latestVersion: string }
|
|
891
|
+
*/
|
|
892
|
+
async function getPluginVersionDetails(installedPlugins) {
|
|
893
|
+
try {
|
|
894
|
+
const meshPlugin = installedPlugins.find(
|
|
895
|
+
({ name }) => name === '@adobe/aio-cli-plugin-api-mesh',
|
|
896
|
+
);
|
|
897
|
+
const currentVersion = meshPlugin.version;
|
|
898
|
+
|
|
899
|
+
let config = {
|
|
900
|
+
method: 'get',
|
|
901
|
+
url: 'https://registry.npmjs.org/@adobe/aio-cli-plugin-api-mesh/latest',
|
|
902
|
+
};
|
|
903
|
+
|
|
904
|
+
const response = await axios.request(config);
|
|
905
|
+
const latestVersion = response.data.version;
|
|
906
|
+
|
|
907
|
+
logger.debug(`Latest mesh plugin version: ${latestVersion}`);
|
|
908
|
+
logger.debug(`Installed mesh plugin version: ${currentVersion}`);
|
|
909
|
+
|
|
910
|
+
return {
|
|
911
|
+
currentVersion,
|
|
912
|
+
latestVersion,
|
|
913
|
+
};
|
|
914
|
+
} catch (err) {
|
|
915
|
+
logger.error('Unable to get package version to compare');
|
|
916
|
+
logger.error(err.message);
|
|
917
|
+
|
|
918
|
+
return {
|
|
919
|
+
currentVersion: null,
|
|
920
|
+
latestVersion: null,
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
}
|
|
924
|
+
|
|
925
|
+
/**
|
|
926
|
+
*
|
|
927
|
+
* This function compares current installed version against the latest version from npm and
|
|
928
|
+
* returns true if current version is same as latest. Returns false if the current version
|
|
929
|
+
* is behind the latest version.
|
|
930
|
+
*
|
|
931
|
+
* @param {string} currentVersion
|
|
932
|
+
* @param {string} latestVersion
|
|
933
|
+
* @returns
|
|
934
|
+
*/
|
|
935
|
+
function isCurrentVersionLatest(currentVersion, latestVersion) {
|
|
936
|
+
try {
|
|
937
|
+
logger.debug(`Comparing versions Current: ${currentVersion} against Latest: ${latestVersion}`);
|
|
938
|
+
|
|
939
|
+
return compareVersions(currentVersion, latestVersion) >= 0;
|
|
940
|
+
} catch (err) {
|
|
941
|
+
logger.error('Unable to compare versions');
|
|
942
|
+
logger.error(err.message);
|
|
943
|
+
|
|
944
|
+
return true;
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
|
|
883
948
|
module.exports = {
|
|
884
949
|
objToString,
|
|
885
950
|
promptInput,
|
|
@@ -897,4 +962,6 @@ module.exports = {
|
|
|
897
962
|
startGraphqlServer,
|
|
898
963
|
setUpTenantFiles,
|
|
899
964
|
writeSecretsFile,
|
|
965
|
+
getPluginVersionDetails,
|
|
966
|
+
isCurrentVersionLatest,
|
|
900
967
|
};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
const { getPluginVersionDetails, isCurrentVersionLatest } = require('../helpers');
|
|
2
|
+
const chalk = require('chalk');
|
|
3
|
+
|
|
4
|
+
const hook = async function () {
|
|
5
|
+
const installedPlugins = this.config.plugins;
|
|
6
|
+
|
|
7
|
+
const { currentVersion, latestVersion } = await getPluginVersionDetails(installedPlugins);
|
|
8
|
+
|
|
9
|
+
if (!isCurrentVersionLatest(currentVersion, latestVersion)) {
|
|
10
|
+
this.warn(
|
|
11
|
+
`@adobe/aio-cli-plugin-api-mesh update available from ${chalk.yellowBright(
|
|
12
|
+
currentVersion,
|
|
13
|
+
)} to ${chalk.yellowBright(latestVersion)}`,
|
|
14
|
+
);
|
|
15
|
+
this.warn(
|
|
16
|
+
`Run ${chalk.greenBright(
|
|
17
|
+
'aio plugins:install @adobe/aio-cli-plugin-api-mesh',
|
|
18
|
+
)} to update to the latest`,
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
module.exports = hook;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { ServedTier, addServedHeader } from './served';
|
|
2
|
+
import { bindedlogger as logger } from './utils/logger';
|
|
3
|
+
import { getRequestId } from './utils/requestId';
|
|
4
|
+
import { buildServer } from './wranglerServer';
|
|
5
|
+
|
|
6
|
+
let server;
|
|
7
|
+
|
|
8
|
+
export default {
|
|
9
|
+
setServer(newServer) {
|
|
10
|
+
server = newServer;
|
|
11
|
+
},
|
|
12
|
+
/**
|
|
13
|
+
* Fetch.
|
|
14
|
+
* @param request Request.
|
|
15
|
+
* @param env Environment.
|
|
16
|
+
* @param ctx Event context.
|
|
17
|
+
*/
|
|
18
|
+
async fetch(request, env, ctx) {
|
|
19
|
+
const requestId = getRequestId(request);
|
|
20
|
+
// Retrieve environment variables
|
|
21
|
+
const { MESH_ID: meshId, LOG_LEVEL: logLevel } = env;
|
|
22
|
+
const loggerInstance = logger({ logLevel, meshId, requestId });
|
|
23
|
+
const meshArtifacts = await import('../.mesh');
|
|
24
|
+
const rawMesh = await import('../.mesh/.meshrc.json');
|
|
25
|
+
|
|
26
|
+
if (!server) {
|
|
27
|
+
server = await this.buildAndCacheServer(env, loggerInstance, meshArtifacts, rawMesh);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
loggerInstance.debug('WORKER HOT: Fetching via worker');
|
|
31
|
+
const response = await server.fetch(request, ctx);
|
|
32
|
+
addServedHeader(response, ServedTier.WORKER_HOT);
|
|
33
|
+
return response;
|
|
34
|
+
},
|
|
35
|
+
/**
|
|
36
|
+
* Build and cache mesh instance/server in global variable.
|
|
37
|
+
* @param env
|
|
38
|
+
* @param loggerInstance
|
|
39
|
+
*/
|
|
40
|
+
async buildAndCacheServer(env, loggerInstance, meshArtifacts, meshConfig) {
|
|
41
|
+
server = await buildServer(loggerInstance, env, meshArtifacts, meshConfig);
|
|
42
|
+
return server;
|
|
43
|
+
},
|
|
44
|
+
};
|