@adobe/aio-cli-plugin-api-mesh 5.0.0-alpha → 5.0.0-beta

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.
@@ -193,7 +193,30 @@ describe('get command tests', () => {
193
193
  verbose: true,
194
194
  });
195
195
  expect(initRequestId).toHaveBeenCalled();
196
- expect(runResult).toEqual({ meshId: 'dummy_meshId', mesh: mockGetMeshConfig });
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).toEqual({ meshId: 'dummy_meshId', mesh: mockGetMeshConfig });
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).toEqual({ meshId: 'dummy_meshId', mesh: mockGetMeshConfig });
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(startGraphqlServer).toHaveBeenCalledWith(
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), process.env.PORT, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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(startGraphqlServer).toHaveBeenCalledWith(expect.anything(), defaultPort, false);
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 = UUID.newUuid().toString();
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 startGraphqlServer(meshId, portNo, flags.debug);
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
+ };