@adobe/aio-cli-plugin-api-mesh 5.2.3 → 5.2.4-alpha.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 +5 -10
- package/src/commands/{api-mesh.js → PLUGINNAME/__tests__/index.test.js} +15 -13
- package/src/commands/PLUGINNAME/index.js +32 -0
- package/src/commands/api-mesh/__tests__/cache-purge.test.js +2 -2
- package/src/commands/api-mesh/__tests__/create.test.js +9 -21
- package/src/commands/api-mesh/__tests__/delete.test.js +2 -2
- package/src/commands/api-mesh/__tests__/describe.test.js +2 -2
- package/src/commands/api-mesh/__tests__/get-log-forwarding.test.js +149 -0
- package/src/commands/api-mesh/__tests__/get.test.js +2 -2
- package/src/commands/api-mesh/__tests__/log-get-bulk.test.js +2 -2
- package/src/commands/api-mesh/__tests__/log-get.test.js +2 -2
- package/src/commands/api-mesh/__tests__/log-list.test.js +2 -2
- package/src/commands/api-mesh/__tests__/run.test.js +67 -193
- package/src/commands/api-mesh/__tests__/set-log-forwarding.test.js +246 -0
- package/src/commands/api-mesh/__tests__/status.test.js +2 -2
- package/src/commands/api-mesh/__tests__/update.test.js +4 -6
- package/src/commands/api-mesh/cache/purge.js +1 -1
- package/src/commands/api-mesh/config/get/log-forwarding.js +78 -0
- package/src/commands/api-mesh/config/set/log-forwarding.js +156 -0
- package/src/commands/api-mesh/create.js +4 -3
- package/src/commands/api-mesh/delete.js +1 -1
- package/src/commands/api-mesh/describe.js +1 -1
- package/src/commands/api-mesh/get.js +1 -1
- package/src/commands/api-mesh/log-get-bulk.js +1 -1
- package/src/commands/api-mesh/log-get.js +1 -1
- package/src/commands/api-mesh/log-list.js +1 -1
- package/src/commands/api-mesh/run.js +162 -208
- package/src/commands/api-mesh/source/__tests__/install.test.js +2 -2
- package/src/commands/api-mesh/source/install.js +1 -1
- package/src/commands/api-mesh/status.js +1 -1
- package/src/commands/api-mesh/update.js +4 -3
- package/src/helpers.js +29 -20
- package/src/{worker.js → index.js} +7 -9
- package/src/lib/{devConsole.js → smsClient.js} +186 -1
- package/src/server.js +32 -74
- package/src/utils.js +46 -10
- package/src/wranglerServer.js +80 -0
- package/src/meshArtifact.js +0 -231
- package/src/project.js +0 -56
- package/src/wranglerCli.js +0 -54
- package/wrangler.toml +0 -13
|
@@ -1064,7 +1064,7 @@ const getMeshDeployments = async (organizationCode, projectId, workspaceId, mesh
|
|
|
1064
1064
|
* As a result, we provide the publicKey used for secrets encryption.
|
|
1065
1065
|
* The near-term goal is to stop using Dev Console as a proxy for all routes.
|
|
1066
1066
|
* @param organizationCode
|
|
1067
|
-
* @returns
|
|
1067
|
+
* @returns string
|
|
1068
1068
|
*/
|
|
1069
1069
|
const getPublicEncryptionKey = async organizationCode => {
|
|
1070
1070
|
const { accessToken } = await getDevConsoleConfig();
|
|
@@ -1201,6 +1201,189 @@ const getLogsByRayId = async (organizationCode, projectId, workspaceId, meshId,
|
|
|
1201
1201
|
}
|
|
1202
1202
|
};
|
|
1203
1203
|
|
|
1204
|
+
/**
|
|
1205
|
+
* @param {string} organizationCode - The IMS org code
|
|
1206
|
+
* @param {string} projectId - The project ID
|
|
1207
|
+
* @param {string} workspaceId - The workspace ID
|
|
1208
|
+
* @param {string} meshId - The mesh ID
|
|
1209
|
+
* @param {Object} logConfig - The log forwarding configuration
|
|
1210
|
+
*/
|
|
1211
|
+
const setLogForwarding = async (organizationCode, projectId, workspaceId, meshId, logConfig) => {
|
|
1212
|
+
const { accessToken } = await getDevConsoleConfig();
|
|
1213
|
+
const config = {
|
|
1214
|
+
method: 'POST',
|
|
1215
|
+
url: `${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/log/forwarding`,
|
|
1216
|
+
headers: {
|
|
1217
|
+
'Authorization': `Bearer ${accessToken}`,
|
|
1218
|
+
'Content-Type': 'application/json',
|
|
1219
|
+
'x-request-id': global.requestId,
|
|
1220
|
+
'x-api-key': SMS_API_KEY,
|
|
1221
|
+
},
|
|
1222
|
+
data: JSON.stringify(logConfig),
|
|
1223
|
+
};
|
|
1224
|
+
|
|
1225
|
+
logger.info(
|
|
1226
|
+
'Initiating POST %s',
|
|
1227
|
+
`${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/log/forwarding`,
|
|
1228
|
+
);
|
|
1229
|
+
|
|
1230
|
+
try {
|
|
1231
|
+
const response = await axios(config);
|
|
1232
|
+
|
|
1233
|
+
logger.info('Response from POST %s', response.status);
|
|
1234
|
+
|
|
1235
|
+
if (response?.status === 200) {
|
|
1236
|
+
logger.info(`Log forwarding configuration: ${objToString(response, ['data'])}`);
|
|
1237
|
+
return {
|
|
1238
|
+
result: response.data.result,
|
|
1239
|
+
message: response.data.message,
|
|
1240
|
+
};
|
|
1241
|
+
} else {
|
|
1242
|
+
// not 200 response
|
|
1243
|
+
logger.error(
|
|
1244
|
+
`Something went wrong: ${objToString(
|
|
1245
|
+
response,
|
|
1246
|
+
['data'],
|
|
1247
|
+
'Unable to set log forwarding details.',
|
|
1248
|
+
)}. Received ${response.status}, expected 200`,
|
|
1249
|
+
);
|
|
1250
|
+
throw new Error(response.data.message);
|
|
1251
|
+
}
|
|
1252
|
+
} catch (error) {
|
|
1253
|
+
if (error.response && error.response.status === 400) {
|
|
1254
|
+
// The request was made and the server responded with a 400 status code
|
|
1255
|
+
logger.error('Error setting log forwarding configuration: %j', error.response.data);
|
|
1256
|
+
|
|
1257
|
+
throw new Error('Invalid input parameters.');
|
|
1258
|
+
}
|
|
1259
|
+
// request made but no response received
|
|
1260
|
+
else if (error.request && !error.response) {
|
|
1261
|
+
logger.error('No response received from server when setting log forwarding configuration');
|
|
1262
|
+
throw new Error('Unable to set log forwarding details. Check the details and try again.');
|
|
1263
|
+
}
|
|
1264
|
+
// response received with error
|
|
1265
|
+
else if (error.response && error.response.data) {
|
|
1266
|
+
logger.error(
|
|
1267
|
+
'Error setting log forwarding configuration: %s',
|
|
1268
|
+
objToString(error, ['response', 'data'], 'Unable to set log forwarding'),
|
|
1269
|
+
);
|
|
1270
|
+
|
|
1271
|
+
// response a message or messages field
|
|
1272
|
+
|
|
1273
|
+
if (error.response.data.message || error.response.data.messages) {
|
|
1274
|
+
const message = objToString(
|
|
1275
|
+
error,
|
|
1276
|
+
['response', 'data', 'message' || 'messages'],
|
|
1277
|
+
'Unable to set log forwarding',
|
|
1278
|
+
);
|
|
1279
|
+
throw new Error(message);
|
|
1280
|
+
}
|
|
1281
|
+
// response contains error but no specific message field
|
|
1282
|
+
else {
|
|
1283
|
+
const message = objToString(error, ['response', 'data'], 'Unable to set log forwarding');
|
|
1284
|
+
throw new Error(message);
|
|
1285
|
+
}
|
|
1286
|
+
} else {
|
|
1287
|
+
// Something else happened while setting up the request
|
|
1288
|
+
logger.error('Error setting log forwarding configuration: %s', error.message);
|
|
1289
|
+
throw new Error(`Something went wrong while setting log forwarding. ${error.message}`);
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
};
|
|
1293
|
+
|
|
1294
|
+
/**
|
|
1295
|
+
* @param {string} organizationCode - The IMS org code
|
|
1296
|
+
* @param {string} projectId - The project ID
|
|
1297
|
+
* @param {string} workspaceId - The workspace ID
|
|
1298
|
+
* @param {string} meshId - The mesh ID
|
|
1299
|
+
*/
|
|
1300
|
+
const getLogForwarding = async (organizationCode, projectId, workspaceId, meshId) => {
|
|
1301
|
+
const { accessToken } = await getDevConsoleConfig();
|
|
1302
|
+
const config = {
|
|
1303
|
+
method: 'GET',
|
|
1304
|
+
url: `${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/log/forwarding`,
|
|
1305
|
+
headers: {
|
|
1306
|
+
'Authorization': `Bearer ${accessToken}`,
|
|
1307
|
+
'Content-Type': 'application/json',
|
|
1308
|
+
'x-request-id': global.requestId,
|
|
1309
|
+
'x-api-key': SMS_API_KEY,
|
|
1310
|
+
},
|
|
1311
|
+
};
|
|
1312
|
+
|
|
1313
|
+
logger.info(
|
|
1314
|
+
'Initiating POST %s',
|
|
1315
|
+
`${SMS_BASE_URL}/organizations/${organizationCode}/projects/${projectId}/workspaces/${workspaceId}/meshes/${meshId}/log/forwarding`,
|
|
1316
|
+
);
|
|
1317
|
+
|
|
1318
|
+
try {
|
|
1319
|
+
const response = await axios(config);
|
|
1320
|
+
|
|
1321
|
+
logger.info('Response from GET %s', response.status);
|
|
1322
|
+
|
|
1323
|
+
if (response?.status === 200) {
|
|
1324
|
+
logger.info(`Get log forwarding configuration: ${objToString(response, ['data'])}`);
|
|
1325
|
+
return {
|
|
1326
|
+
data: response.data,
|
|
1327
|
+
};
|
|
1328
|
+
} else {
|
|
1329
|
+
// not 200 response
|
|
1330
|
+
logger.error(
|
|
1331
|
+
`Something went wrong: ${objToString(
|
|
1332
|
+
response,
|
|
1333
|
+
['data'],
|
|
1334
|
+
'Unable to get log forwarding details.',
|
|
1335
|
+
)}. Received ${response.status}, expected 200`,
|
|
1336
|
+
);
|
|
1337
|
+
throw new Error(response.data.message);
|
|
1338
|
+
}
|
|
1339
|
+
} catch (error) {
|
|
1340
|
+
if (error.response && error.response.status === 400) {
|
|
1341
|
+
// The request was made and the server responded with a 400 status code
|
|
1342
|
+
logger.error('Error getting the log forwarding configuration: %j', error.response.data);
|
|
1343
|
+
|
|
1344
|
+
throw new Error('Invalid input parameters.');
|
|
1345
|
+
} else if (error.response && error.response.status === 404) {
|
|
1346
|
+
logger.error('Log forwarding details not found');
|
|
1347
|
+
|
|
1348
|
+
return null;
|
|
1349
|
+
}
|
|
1350
|
+
// request made but no response received
|
|
1351
|
+
else if (error.request && !error.response) {
|
|
1352
|
+
logger.error('No response from server when getting the log forwarding configuration');
|
|
1353
|
+
throw new Error('Unable to get log forwarding details. Check the details and try again.');
|
|
1354
|
+
}
|
|
1355
|
+
// response received with error
|
|
1356
|
+
else if (error.response && error.response.data) {
|
|
1357
|
+
logger.error(
|
|
1358
|
+
'Error getting the log forwarding configuration: %s',
|
|
1359
|
+
objToString(error, ['response', 'data'], 'Unable to get log forwarding'),
|
|
1360
|
+
);
|
|
1361
|
+
|
|
1362
|
+
// response a message or messages field
|
|
1363
|
+
|
|
1364
|
+
if (error.response.data.message || error.response.data.messages) {
|
|
1365
|
+
const message = objToString(
|
|
1366
|
+
error,
|
|
1367
|
+
['response', 'data', 'message' || 'messages'],
|
|
1368
|
+
'Unable to get log forwarding',
|
|
1369
|
+
);
|
|
1370
|
+
throw new Error(message);
|
|
1371
|
+
}
|
|
1372
|
+
// response contains error but no specific message field
|
|
1373
|
+
else {
|
|
1374
|
+
const message = objToString(error, ['response', 'data'], 'Unable to get log forwarding');
|
|
1375
|
+
throw new Error(message);
|
|
1376
|
+
}
|
|
1377
|
+
} else {
|
|
1378
|
+
// Something else happened while setting up the request
|
|
1379
|
+
logger.error('Error getting the log forwarding configuration: %s', error.message);
|
|
1380
|
+
throw new Error(
|
|
1381
|
+
`Something went wrong while getting the log forwarding configuration. ${error.message}`,
|
|
1382
|
+
);
|
|
1383
|
+
}
|
|
1384
|
+
}
|
|
1385
|
+
};
|
|
1386
|
+
|
|
1204
1387
|
module.exports = {
|
|
1205
1388
|
getApiKeyCredential,
|
|
1206
1389
|
describeMesh,
|
|
@@ -1222,4 +1405,6 @@ module.exports = {
|
|
|
1222
1405
|
getPresignedUrls,
|
|
1223
1406
|
getLogsByRayId,
|
|
1224
1407
|
cachePurge,
|
|
1408
|
+
setLogForwarding,
|
|
1409
|
+
getLogForwarding,
|
|
1225
1410
|
};
|
package/src/server.js
CHANGED
|
@@ -1,80 +1,38 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
const
|
|
4
|
-
|
|
5
|
-
const
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
-
const
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (meshConfig.disableIntrospection) {
|
|
29
|
-
options.additionalEnvelopPlugins.push(useDisableIntrospection());
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
return getMesh(options).then(mesh => {
|
|
33
|
-
const id = mesh.pubsub.subscribe('destroy', () => {
|
|
34
|
-
meshInstance$ = undefined;
|
|
35
|
-
mesh.pubsub.unsubscribe(id);
|
|
36
|
-
});
|
|
37
|
-
return mesh;
|
|
1
|
+
const { spawn } = require('child_process');
|
|
2
|
+
const { readSecretsFile } = require('./serverUtils');
|
|
3
|
+
const packageData = require('../package.json');
|
|
4
|
+
|
|
5
|
+
const runServer = portNo => {
|
|
6
|
+
const wranglerPackageNumber = packageData.dependencies.wrangler;
|
|
7
|
+
const wranglerVersion = `wrangler@${wranglerPackageNumber.replace(/^[\^~]/, '')}`;
|
|
8
|
+
const indexFilePath = `${__dirname}/index.js`;
|
|
9
|
+
const filePath = '.mesh';
|
|
10
|
+
const secrets = readSecretsFile(filePath);
|
|
11
|
+
const commandArgs = [
|
|
12
|
+
wranglerVersion,
|
|
13
|
+
'dev',
|
|
14
|
+
indexFilePath,
|
|
15
|
+
'--show-interactive-dev-session',
|
|
16
|
+
'false',
|
|
17
|
+
'--var',
|
|
18
|
+
`Secret:${JSON.stringify(secrets)}`,
|
|
19
|
+
'--port',
|
|
20
|
+
portNo,
|
|
21
|
+
'--inspector-port',
|
|
22
|
+
'9229',
|
|
23
|
+
];
|
|
24
|
+
|
|
25
|
+
const wrangler = spawn('npx', commandArgs, {
|
|
26
|
+
stdio: 'inherit',
|
|
38
27
|
});
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async function getBuiltMesh(meshArtifacts, meshConfig) {
|
|
42
|
-
if (meshInstance$ == null) {
|
|
43
|
-
meshInstance$ = buildMeshInstance(meshArtifacts, meshConfig);
|
|
44
|
-
}
|
|
45
|
-
return meshInstance$;
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
const buildServer = async (loggerInstance, env, meshArtifacts, meshConfig) => {
|
|
49
|
-
const { Secret: secret } = env;
|
|
50
|
-
const tenantMesh = await getBuiltMesh(meshArtifacts, meshConfig);
|
|
51
|
-
const meshSecrets = loadMeshSecrets(loggerInstance, secret);
|
|
52
|
-
return await buildYogaServer(env, tenantMesh, meshConfig, meshSecrets);
|
|
53
|
-
};
|
|
54
28
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return createYoga({
|
|
58
|
-
plugins: tenantMesh.plugins,
|
|
59
|
-
graphqlEndpoint: `/graphql`,
|
|
60
|
-
cors: getCorsOptions(env, meshConfig),
|
|
61
|
-
context: initialContext => ({
|
|
62
|
-
...initialContext,
|
|
63
|
-
secrets: secretsProxy,
|
|
64
|
-
}),
|
|
65
|
-
maskedErrors: {
|
|
66
|
-
maskError: maskError,
|
|
67
|
-
},
|
|
68
|
-
logging: 'debug',
|
|
29
|
+
wrangler.on('close', code => {
|
|
30
|
+
console.log(`wrangler dev process exited with code ${code}`);
|
|
69
31
|
});
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
const maskError = error => {
|
|
73
|
-
if (error instanceof GraphQLError && error.extensions?.http?.headers) {
|
|
74
|
-
delete error.extensions.http.headers;
|
|
75
|
-
}
|
|
76
32
|
|
|
77
|
-
|
|
33
|
+
wrangler.on('error', error => {
|
|
34
|
+
console.error(`Failed to start wrangler dev: ${error.message}`);
|
|
35
|
+
});
|
|
78
36
|
};
|
|
79
37
|
|
|
80
|
-
module.exports = {
|
|
38
|
+
module.exports = { runServer };
|
package/src/utils.js
CHANGED
|
@@ -62,13 +62,6 @@ const secretsFlag = Flags.string({
|
|
|
62
62
|
const portNoFlag = Flags.integer({
|
|
63
63
|
char: 'p',
|
|
64
64
|
description: 'Port number for the local dev server',
|
|
65
|
-
default: 5000,
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
const inspectPortNoFlag = Flags.integer({
|
|
69
|
-
char: 'i',
|
|
70
|
-
description: 'Port number for the local dev server inspector',
|
|
71
|
-
default: 9229,
|
|
72
65
|
});
|
|
73
66
|
|
|
74
67
|
const debugFlag = Flags.boolean({
|
|
@@ -106,6 +99,49 @@ const logFilenameFlag = Flags.string({
|
|
|
106
99
|
required: true,
|
|
107
100
|
});
|
|
108
101
|
|
|
102
|
+
// The `destinations` object to hold the configuration for log forwarding destinations.
|
|
103
|
+
// It prompts for the required inputs for the destination.
|
|
104
|
+
// Each destination can have different key/value pairs of configuration credentials.
|
|
105
|
+
// and applies the validation logic accordingly.
|
|
106
|
+
const destinations = {
|
|
107
|
+
// Configuration for the 'New Relic' destination
|
|
108
|
+
'New Relic': {
|
|
109
|
+
name: 'newrelic', // internal value that will be used
|
|
110
|
+
// Required inputs for the 'New Relic' destination
|
|
111
|
+
inputs: [
|
|
112
|
+
{
|
|
113
|
+
name: 'baseUri',
|
|
114
|
+
promptMessage: 'Enter base URI:',
|
|
115
|
+
isSecret: false,
|
|
116
|
+
validate: value => {
|
|
117
|
+
if (!value) {
|
|
118
|
+
throw new Error('Base URI is required');
|
|
119
|
+
}
|
|
120
|
+
if (!value.startsWith('https://')) {
|
|
121
|
+
throw new Error('The URI value must include the protocol (https://)');
|
|
122
|
+
}
|
|
123
|
+
},
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'licenseKey',
|
|
127
|
+
promptMessage: 'Enter license key:',
|
|
128
|
+
isSecret: true,
|
|
129
|
+
validate: value => {
|
|
130
|
+
if (!value) {
|
|
131
|
+
throw new Error('License key is required');
|
|
132
|
+
}
|
|
133
|
+
if (value.length !== 40) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`The license key is in the wrong format. Expected: 40 characters (received: ${value.length})`,
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
],
|
|
141
|
+
},
|
|
142
|
+
// Additional destinations can be added here
|
|
143
|
+
};
|
|
144
|
+
|
|
109
145
|
/**
|
|
110
146
|
* Parse the meshConfig and get the list of (local) files to be imported
|
|
111
147
|
*
|
|
@@ -284,7 +320,7 @@ function checkPlaceholders(mesh) {
|
|
|
284
320
|
* @param {string} file
|
|
285
321
|
* @param {object} command
|
|
286
322
|
* @param {string} filetype
|
|
287
|
-
* @returns {
|
|
323
|
+
* @returns {string}
|
|
288
324
|
*/
|
|
289
325
|
async function readFileContents(file, command, filetype) {
|
|
290
326
|
try {
|
|
@@ -352,7 +388,7 @@ function validateFileName(filesList) {
|
|
|
352
388
|
* @param {string} inputMeshData
|
|
353
389
|
* @param {string} envFilePath
|
|
354
390
|
* @param {object} command
|
|
355
|
-
* @returns {
|
|
391
|
+
* @returns {string}
|
|
356
392
|
*/
|
|
357
393
|
async function validateAndInterpolateMesh(inputMeshData, envFilePath, command) {
|
|
358
394
|
//Read the environment file
|
|
@@ -767,7 +803,6 @@ module.exports = {
|
|
|
767
803
|
validateAndInterpolateMesh,
|
|
768
804
|
getAppRootDir,
|
|
769
805
|
portNoFlag,
|
|
770
|
-
inspectPortNoFlag,
|
|
771
806
|
debugFlag,
|
|
772
807
|
selectFlag,
|
|
773
808
|
secretsFlag,
|
|
@@ -786,4 +821,5 @@ module.exports = {
|
|
|
786
821
|
validateDateTimeFormat,
|
|
787
822
|
localToUTCTime,
|
|
788
823
|
cachePurgeAllActionFlag,
|
|
824
|
+
destinations,
|
|
789
825
|
};
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { getMesh } from '@graphql-mesh/runtime';
|
|
2
|
+
|
|
3
|
+
const { getCorsOptions } = require('./cors');
|
|
4
|
+
const { createYoga } = require('graphql-yoga');
|
|
5
|
+
const { GraphQLError } = require('graphql/error');
|
|
6
|
+
|
|
7
|
+
const { loadMeshSecrets, getSecretsHandler } = require('./secrets');
|
|
8
|
+
const useComplianceHeaders = require('./plugins/complianceHeaders');
|
|
9
|
+
const UseHttpDetailsExtensions = require('./plugins/httpDetailsExtensions');
|
|
10
|
+
const useSourceHeaders = require('@adobe/plugin-source-headers');
|
|
11
|
+
const { useDisableIntrospection } = require('@envelop/disable-introspection');
|
|
12
|
+
|
|
13
|
+
let meshInstance$;
|
|
14
|
+
|
|
15
|
+
async function buildMeshInstance(meshArtifacts, meshConfig) {
|
|
16
|
+
const { getMeshOptions } = meshArtifacts;
|
|
17
|
+
const options = await getMeshOptions();
|
|
18
|
+
|
|
19
|
+
options.additionalEnvelopPlugins = (options.additionalEnvelopPlugins || []).concat(
|
|
20
|
+
useComplianceHeaders(),
|
|
21
|
+
UseHttpDetailsExtensions({
|
|
22
|
+
// Get the details of responseConfig.includeHTTPDetails and store in Cache
|
|
23
|
+
if: meshConfig.responseConfig?.includeHTTPDetails || false,
|
|
24
|
+
}),
|
|
25
|
+
useSourceHeaders(meshConfig),
|
|
26
|
+
);
|
|
27
|
+
|
|
28
|
+
if (meshConfig.disableIntrospection) {
|
|
29
|
+
options.additionalEnvelopPlugins.push(useDisableIntrospection());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
return getMesh(options).then(mesh => {
|
|
33
|
+
const id = mesh.pubsub.subscribe('destroy', () => {
|
|
34
|
+
meshInstance$ = undefined;
|
|
35
|
+
mesh.pubsub.unsubscribe(id);
|
|
36
|
+
});
|
|
37
|
+
return mesh;
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async function getBuiltMesh(meshArtifacts, meshConfig) {
|
|
42
|
+
if (meshInstance$ == null) {
|
|
43
|
+
meshInstance$ = buildMeshInstance(meshArtifacts, meshConfig);
|
|
44
|
+
}
|
|
45
|
+
return meshInstance$;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const buildServer = async (loggerInstance, env, meshArtifacts, meshConfig) => {
|
|
49
|
+
const { Secret: secret } = env;
|
|
50
|
+
const tenantMesh = await getBuiltMesh(meshArtifacts, meshConfig);
|
|
51
|
+
const meshSecrets = loadMeshSecrets(loggerInstance, secret);
|
|
52
|
+
return await buildYogaServer(env, tenantMesh, meshConfig, meshSecrets);
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
async function buildYogaServer(env, tenantMesh, meshConfig, meshSecrets) {
|
|
56
|
+
const secretsProxy = new Proxy(meshSecrets, getSecretsHandler);
|
|
57
|
+
return createYoga({
|
|
58
|
+
plugins: tenantMesh.plugins,
|
|
59
|
+
graphqlEndpoint: `/graphql`,
|
|
60
|
+
cors: getCorsOptions(env, meshConfig),
|
|
61
|
+
context: initialContext => ({
|
|
62
|
+
...initialContext,
|
|
63
|
+
secrets: secretsProxy,
|
|
64
|
+
}),
|
|
65
|
+
maskedErrors: {
|
|
66
|
+
maskError: maskError,
|
|
67
|
+
},
|
|
68
|
+
logging: 'debug',
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const maskError = error => {
|
|
73
|
+
if (error instanceof GraphQLError && error.extensions?.http?.headers) {
|
|
74
|
+
delete error.extensions.http.headers;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return error;
|
|
78
|
+
};
|
|
79
|
+
|
|
80
|
+
module.exports = { buildServer };
|