@adobe/aio-cli-plugin-api-mesh 5.2.4-alpha.0 → 5.2.4-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. package/oclif.manifest.json +1 -1
  2. package/package.json +13 -6
  3. package/src/commands/api-mesh/__tests__/cache-purge.test.js +1 -2
  4. package/src/commands/api-mesh/__tests__/create.test.js +19 -22
  5. package/src/commands/api-mesh/__tests__/delete-log-forwarding.test.js +106 -0
  6. package/src/commands/api-mesh/__tests__/delete.test.js +1 -2
  7. package/src/commands/api-mesh/__tests__/describe.test.js +1 -3
  8. package/src/commands/api-mesh/__tests__/get.test.js +2 -2
  9. package/src/commands/api-mesh/__tests__/log-get-bulk.test.js +19 -213
  10. package/src/commands/api-mesh/__tests__/run.test.js +191 -65
  11. package/src/commands/api-mesh/__tests__/update.test.js +8 -7
  12. package/src/commands/api-mesh/cache/purge.js +1 -3
  13. package/src/commands/api-mesh/config/delete/log-forwarding.js +80 -0
  14. package/src/commands/api-mesh/create.js +22 -6
  15. package/src/commands/api-mesh/delete.js +1 -3
  16. package/src/commands/api-mesh/describe.js +1 -3
  17. package/src/commands/api-mesh/get.js +1 -3
  18. package/src/commands/api-mesh/log-get-bulk.js +5 -26
  19. package/src/commands/api-mesh/log-get.js +1 -3
  20. package/src/commands/api-mesh/log-list.js +1 -3
  21. package/src/commands/api-mesh/run.js +207 -168
  22. package/src/commands/api-mesh/source/discover.js +2 -9
  23. package/src/commands/api-mesh/source/get.js +1 -8
  24. package/src/commands/api-mesh/source/install.js +1 -2
  25. package/src/commands/api-mesh/status.js +1 -2
  26. package/src/commands/api-mesh/update.js +21 -6
  27. package/src/commands/{PLUGINNAME/__tests__/index.test.js → api-mesh.js} +13 -15
  28. package/src/helpers.js +73 -15
  29. package/src/hooks/initMetadata.js +8 -0
  30. package/src/lib/smsClient.js +115 -1
  31. package/src/meshArtifact.js +231 -0
  32. package/src/project.js +56 -0
  33. package/src/server.js +74 -32
  34. package/src/utils.js +26 -24
  35. package/src/{index.js → worker.js} +9 -7
  36. package/src/wranglerCli.js +54 -0
  37. package/wrangler.toml +13 -0
  38. package/src/commands/PLUGINNAME/index.js +0 -32
  39. package/src/wranglerServer.js +0 -80
@@ -0,0 +1,231 @@
1
+ const path = require('path');
2
+ const fs = require('fs');
3
+ const { fixPlugins } = require('./fixPlugins');
4
+ const logger = require('../src/classes/logger');
5
+
6
+ /**
7
+ * Whether file is TypeScript
8
+ * @param filePath Filepath
9
+ */
10
+ function isTypeScriptFile(filePath) {
11
+ const ext = path.extname(filePath);
12
+ return ext === '.ts' || ext === '.tsx';
13
+ }
14
+
15
+ /**
16
+ * Gets
17
+ * @param builtMeshTenantDir
18
+ * @returns {string}
19
+ */
20
+ function getBuiltMeshEntrypoint(builtMeshTenantDir) {
21
+ let builtMeshIndexPath = path.join(builtMeshTenantDir, 'index');
22
+ return fs.existsSync(`${builtMeshIndexPath}.ts`)
23
+ ? `${builtMeshIndexPath}.ts`
24
+ : `${builtMeshIndexPath}.js`;
25
+ }
26
+
27
+ /**
28
+ * Converts composer string to static imports compatible with bundling
29
+ * @param data {string} Data read from the built mesh
30
+ * @returns {string} Updated data
31
+ * @example Converts composer string
32
+ * ```
33
+ * "beforeAll": {
34
+ * "composer": "/Users/user/project/hooks.js#isAuth",
35
+ * "blocking": true
36
+ * }
37
+ * ```
38
+ * To:
39
+ * ```
40
+ * "beforeAll": {
41
+ * "module": await import("/Users/user/project/hooks.js"), "fn": "isAuth",
42
+ * "blocking": true
43
+ * }
44
+ * ```
45
+ */
46
+ function resolveComposerAsTypeScriptModule(data) {
47
+ return data.replace(
48
+ /"composer":\s*"([^#]+)#([^"]+)"/,
49
+ `"module": await import("$1"), "fn": "$2"`,
50
+ );
51
+ }
52
+
53
+ /**
54
+ * Converts composer string to static imports compatible with bundling
55
+ * @param data {string} Data read from the built mesh
56
+ * @returns {string} Updated data
57
+ * @example Converts composer string
58
+ * ```
59
+ * "beforeAll": {
60
+ * "composer": "/Users/user/project/hooks.js#isAuth",
61
+ * "blocking": true
62
+ * }
63
+ * ```
64
+ * To:
65
+ * ```
66
+ * "beforeAll": {
67
+ * "module": __importStar(require("/Users/user/project/hooks.js")), "fn": "isAuth",
68
+ * "blocking": true
69
+ * }
70
+ * ```
71
+ */
72
+ function resolveComposerAsJavaScriptModule(data) {
73
+ return data.replace(
74
+ /"composer":\s*"([^#]+)#([^"]+)"/,
75
+ `"module": __importStar(require("$1")), "fn": "$2"`,
76
+ );
77
+ }
78
+
79
+ /**
80
+ * Takes a mesh artifact and converts composer configuration to static imports
81
+ * compatible with bundling
82
+ * @param meshArtifactPath Path to the mesh artifact used to determine extension
83
+ * @param data {string} Data read from the built mesh
84
+ * @returns {string} Updated data
85
+ * @see {@link resolveComposerAsJavaScriptModule}
86
+ * @see {@link resolveComposerAsTypeScriptModule}
87
+ */
88
+ function resolveComposerAsStaticImport(meshArtifactPath, data) {
89
+ return isTypeScriptFile(meshArtifactPath)
90
+ ? resolveComposerAsTypeScriptModule(data)
91
+ : resolveComposerAsJavaScriptModule(data);
92
+ }
93
+
94
+ // /**
95
+ // * Converts handler string to static imports compatible with bundling
96
+ // * @param data {string} Data read from the built mesh
97
+ // * @returns {string} Updated data
98
+ // * @example Converts composer string
99
+ // * ```
100
+ // * "onFetch": {
101
+ // * "handler": "/Users/user/project/fetch.js",
102
+ // * "blocking": true
103
+ // * }
104
+ // * ```
105
+ // * To:
106
+ // * ```
107
+ // * "onFetch": {
108
+ // * "handler": await import("/Users/user/project/fetch.js"),
109
+ // * "blocking": true
110
+ // * }
111
+ // * ```
112
+ // */
113
+ // function resolveHandlerAsTypeScriptModule(data) {
114
+ // return data.replace(/"handler":\s*"([^"]+)"/, `"handler": await import("$1")`);
115
+ // }
116
+
117
+ // /**
118
+ // * Converts handler string to static imports compatible with bundling
119
+ // * @param data {string} Data read from the built mesh
120
+ // * @returns {string} Updated data
121
+ // * @example Converts composer string
122
+ // * ```
123
+ // * "onFetch": {
124
+ // * "handler": "/Users/user/project/fetch.js",
125
+ // * "blocking": true
126
+ // * }
127
+ // * ```
128
+ // * To:
129
+ // * ```
130
+ // * "onFetch": {
131
+ // * "module": __importStar(require("/Users/user/project/fetch.js")),
132
+ // * "blocking": true
133
+ // * }
134
+ // * ```
135
+ // */
136
+ // function resolveHandlerAsJavaScriptModule(data) {
137
+ // return data.replace(/"handler":\s*"([^"]+)"/, `"handler": __importStar(require("$1"))`);
138
+ // }
139
+
140
+ // /**
141
+ // * Takes a mesh artifact and converts handler configuration to static imports
142
+ // * compatible with bundling
143
+ // * @param meshArtifactPath Path to the mesh artifact used to determine extension
144
+ // * @param data {string} Data read from the built mesh
145
+ // * @returns {string} Updated data
146
+ // * @see {@link resolveHandlerAsJavaScriptModule}
147
+ // * @see {@link resolveHandlerAsTypeScriptModule}
148
+ // */
149
+ // TODO: onFetch support - requires plugin changes
150
+ // function resolveHandlerAsStaticImport(meshArtifactPath, data) {
151
+ // return isTypeScriptFile(meshArtifactPath)
152
+ // ? resolveHandlerAsTypeScriptModule(data)
153
+ // : resolveHandlerAsJavaScriptModule(data);
154
+ // }
155
+
156
+ const resolveRelativeSources = async builtMeshTenantDir => {
157
+ let builtMeshPath = getBuiltMeshEntrypoint(builtMeshTenantDir);
158
+
159
+ // Fix http details extensions plugin for edge compatibility
160
+ await fixPlugins(builtMeshPath);
161
+
162
+ // Read tenant files inventory
163
+ const artifactFilesPath = path.join(builtMeshTenantDir, 'files.json');
164
+ if (fs.existsSync(artifactFilesPath)) {
165
+ // Read mesh artifact
166
+ let builtMeshData = fs.readFileSync(builtMeshPath).toString();
167
+
168
+ const parentDirRegex = new RegExp('../tenantFiles'.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
169
+ builtMeshData = builtMeshData.replace(parentDirRegex, './tenantFiles');
170
+
171
+ // Write the modified mesh artifact
172
+ fs.writeFileSync(builtMeshPath, builtMeshData, 'utf8');
173
+ }
174
+ };
175
+
176
+ /**
177
+ * Resolve original sources to materialized files in mesh artifact for local development and debugging
178
+ * @param builtMeshTenantDir Built mesh tenant directory
179
+ * @param localFileOverrides Local file overrides
180
+ */
181
+ const resolveOriginalSources = async (builtMeshTenantDir, localFileOverrides) => {
182
+ let builtMeshPath = getBuiltMeshEntrypoint(builtMeshTenantDir);
183
+
184
+ // Read tenant files inventory
185
+ const artifactFilesPath = path.join(builtMeshTenantDir, 'files.json');
186
+ if (fs.existsSync(artifactFilesPath)) {
187
+ let files = {};
188
+ try {
189
+ files = JSON.parse(fs.readFileSync(artifactFilesPath).toString());
190
+ } catch (err) {
191
+ logger.error('Malformed "files.json" file. Skipping original source resolution.');
192
+ }
193
+
194
+ // Read mesh artifact
195
+ let builtMeshData = fs.readFileSync(builtMeshPath).toString();
196
+ files.files.forEach(file => {
197
+ // Skip replacement of files for local development when the user was prompted
198
+ // to override and answered no
199
+ if (
200
+ Object.keys(localFileOverrides).includes(file.path) &&
201
+ localFileOverrides[file.path] === false
202
+ ) {
203
+ return;
204
+ }
205
+
206
+ // When the source exists in project use it instead of the materialized file
207
+ const absoluteFilePath = path.resolve(file.path);
208
+
209
+ // Replace all occurrences of the materialized path with the fully qualified original path when it exists
210
+ if (fs.existsSync(absoluteFilePath)) {
211
+ const regex = new RegExp(file.materializedPath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'), 'g');
212
+ builtMeshData = builtMeshData.replace(regex, absoluteFilePath);
213
+ builtMeshData = resolveComposerAsStaticImport(builtMeshPath, builtMeshData);
214
+ // TODO: onFetch support - requires plugin changes
215
+ // builtMeshData = resolveHandlerAsStaticImport(builtMeshPath, builtMeshData);
216
+ }
217
+ });
218
+
219
+ // Write the modified mesh artifact
220
+ fs.writeFileSync(builtMeshPath, builtMeshData, 'utf8');
221
+ }
222
+ };
223
+
224
+ module.exports = {
225
+ isTypeScriptFile,
226
+ resolveComposerAsTypeScriptModule,
227
+ resolveComposerAsJavaScriptModule,
228
+ resolveComposerAsStaticImport,
229
+ resolveRelativeSources,
230
+ resolveOriginalSources,
231
+ };
package/src/project.js ADDED
@@ -0,0 +1,56 @@
1
+ const { cpSync, existsSync, renameSync, rmSync } = require('node:fs');
2
+ const { join } = require('node:path');
3
+ const { resolveOriginalSources } = require('./meshArtifact');
4
+
5
+ const BUILT_MESH_ARTIFACT_DIRECTORY = 'mesh-artifact';
6
+ const BUILT_MESH_TENANT_FILES_DIRECTORY = join(BUILT_MESH_ARTIFACT_DIRECTORY, 'tenantFiles');
7
+ const PACKAGED_MESH_DIR = '.mesh';
8
+ const PACKAGED_MESH_DIR_TENANT_FILES_DIRECTORY = join(PACKAGED_MESH_DIR, 'tenantFiles');
9
+ const PACKAGED_MESH_CLI_MIRROR_DIR = `${__dirname}/../${PACKAGED_MESH_DIR}`;
10
+ const TEMP_FILES_DIRECTORY = 'tempfiles';
11
+ const getBuiltMeshTenantDirectory = meshId => join(BUILT_MESH_ARTIFACT_DIRECTORY, meshId);
12
+
13
+ /**
14
+ * Copy built mesh artifact to packaged directory that runs local development.
15
+ * @param builtMeshTenantDir Built mesh directory path
16
+ * @returns {Promise<void>}
17
+ */
18
+ const copyBuiltMeshToPackage = async builtMeshTenantDir => {
19
+ // Reset packaged directories
20
+ safeDelete(PACKAGED_MESH_DIR);
21
+ safeDelete(PACKAGED_MESH_CLI_MIRROR_DIR);
22
+
23
+ // Copy the built mesh to the packaged directory for in-project SDK
24
+ safeRename(builtMeshTenantDir, PACKAGED_MESH_DIR);
25
+ safeRename(BUILT_MESH_TENANT_FILES_DIRECTORY, PACKAGED_MESH_DIR_TENANT_FILES_DIRECTORY);
26
+
27
+ // Copy the packaged mesh to the CLI mirror directory for local server
28
+ safeCopy(PACKAGED_MESH_DIR, PACKAGED_MESH_CLI_MIRROR_DIR);
29
+ };
30
+
31
+ const safeDelete = path => {
32
+ if (existsSync(path)) {
33
+ rmSync(path, { recursive: true });
34
+ }
35
+ };
36
+
37
+ const safeRename = (oldPath, newPath) => {
38
+ if (existsSync(oldPath)) {
39
+ renameSync(oldPath, newPath);
40
+ }
41
+ };
42
+
43
+ const safeCopy = (source, destination) => {
44
+ if (existsSync(source)) {
45
+ cpSync(source, destination, { recursive: true });
46
+ }
47
+ };
48
+
49
+ module.exports = {
50
+ BUILT_MESH_ARTIFACT_DIRECTORY,
51
+ safeDelete,
52
+ copyBuiltMeshToPackage,
53
+ resolveOriginalSources,
54
+ TEMP_FILES_DIRECTORY,
55
+ getBuiltMeshTenantDirectory,
56
+ };
package/src/server.js CHANGED
@@ -1,38 +1,80 @@
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',
27
- });
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
+ );
28
27
 
29
- wrangler.on('close', code => {
30
- console.log(`wrangler dev process exited with code ${code}`);
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;
31
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
+ };
32
54
 
33
- wrangler.on('error', error => {
34
- console.error(`Failed to start wrangler dev: ${error.message}`);
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',
35
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;
36
78
  };
37
79
 
38
- module.exports = { runServer };
80
+ module.exports = { buildServer };
package/src/utils.js CHANGED
@@ -6,7 +6,6 @@ const { readFile } = require('fs/promises');
6
6
  const { interpolateMesh } = require('./helpers');
7
7
  const dotenv = require('dotenv');
8
8
  const YAML = require('yaml');
9
- const ms = require('ms');
10
9
  const parseEnv = require('envsub/js/envsub-parser');
11
10
  const os = require('os');
12
11
  const chalk = require('chalk');
@@ -62,6 +61,13 @@ const secretsFlag = Flags.string({
62
61
  const portNoFlag = Flags.integer({
63
62
  char: 'p',
64
63
  description: 'Port number for the local dev server',
64
+ default: 5000,
65
+ });
66
+
67
+ const inspectPortNoFlag = Flags.integer({
68
+ char: 'i',
69
+ description: 'Port number for the local dev server inspector',
70
+ default: 9229,
65
71
  });
66
72
 
67
73
  const debugFlag = Flags.boolean({
@@ -87,11 +93,7 @@ const endTimeFlag = Flags.string({
87
93
  });
88
94
 
89
95
  const pastFlag = Flags.string({
90
- description: 'Past time window in mins',
91
- });
92
-
93
- const fromFlag = Flags.string({
94
- description: `The from time in YYYY-MM-DD:HH:MM:SS format based on your system's time zone. It is used to fetch logs from the past and is the starting time for the past time duration.`,
96
+ description: 'Past time window in minutes',
95
97
  });
96
98
 
97
99
  const logFilenameFlag = Flags.string({
@@ -320,7 +322,7 @@ function checkPlaceholders(mesh) {
320
322
  * @param {string} file
321
323
  * @param {object} command
322
324
  * @param {string} filetype
323
- * @returns {string}
325
+ * @returns {Promise<string>}
324
326
  */
325
327
  async function readFileContents(file, command, filetype) {
326
328
  try {
@@ -388,7 +390,7 @@ function validateFileName(filesList) {
388
390
  * @param {string} inputMeshData
389
391
  * @param {string} envFilePath
390
392
  * @param {object} command
391
- * @returns {string}
393
+ * @returns {Promise<string>}
392
394
  */
393
395
  async function validateAndInterpolateMesh(inputMeshData, envFilePath, command) {
394
396
  //Read the environment file
@@ -658,23 +660,21 @@ function suggestCorrectedDateFormat(inputDate) {
658
660
  /**
659
661
  * Parses a duration string representing a past time window and converts it to milliseconds.
660
662
  *
661
- * @param {string} pastTimeWindow - The past time duration to parse, e.g., "20 mins", "15 minutes".
663
+ * @param {string} pastTimeWindow - The past time duration in minutes, e.g., "20", "15".
662
664
  * @returns {number} The duration in milliseconds.
663
665
  */
664
666
  function parsePastDuration(pastTimeWindow) {
665
- // Regular expression to match various formats of minute abbreviations
666
- const pastDurationRegex = /^(\d+)\s*(m|mins?|minutes?)$/i;
667
- const match = pastTimeWindow.match(pastDurationRegex);
667
+ // Check if pastTimeWindow contains non-numeric characters
668
+ const match = pastTimeWindow.match(/^(\d+)$/);
669
+
670
+ const durationInMs = Number(pastTimeWindow) * 60 * 1000;
668
671
 
669
- if (!match) {
672
+ if (isNaN(durationInMs) || !match) {
670
673
  throw new Error(
671
- 'Invalid format. The past time window should be in minutes, for example, "20 mins", "15 minutes".',
674
+ 'Invalid format. The time window must be an integer, for example "20" or "15".',
672
675
  );
673
676
  }
674
677
 
675
- // Convert the matched duration to milliseconds
676
- const durationInMs = ms(pastTimeWindow);
677
-
678
678
  return durationInMs;
679
679
  }
680
680
 
@@ -714,14 +714,15 @@ function validateDateTimeRange(startTime, endTime) {
714
714
  throw new Error('endTime cannot be in the future. Provide a valid endTime.');
715
715
  }
716
716
 
717
- if (start.getTime() === end.getTime()) {
718
- throw new Error('The minimum duration is 1 minutes. The current duration is 0 minutes.');
719
- }
720
-
721
- // Check if the duration between start and end times is greater than 30 minutes (1800 seconds)
722
717
  const timeDifferenceInSeconds = (end.getTime() - start.getTime()) / 1000;
723
718
 
724
- if (timeDifferenceInSeconds > 1800) {
719
+ if (timeDifferenceInSeconds < 60) {
720
+ // Check if the duration between start and end times is less than 1 minute (60 seconds)
721
+ throw new Error(
722
+ `The minimum duration is 1 minute. The current duration is ${timeDifferenceInSeconds} seconds.`,
723
+ );
724
+ } else if (timeDifferenceInSeconds > 1800) {
725
+ // Check if the duration between start and end times is greater than 30 minutes (1800 seconds)
725
726
  const hours = Math.floor(timeDifferenceInSeconds / 3600); // Hours calculation
726
727
  const minutes = Math.floor((timeDifferenceInSeconds % 3600) / 60); // Minutes calculation
727
728
  const seconds = timeDifferenceInSeconds % 60; // Seconds calculation
@@ -762,6 +763,7 @@ function validateDateTimeFormat(time) {
762
763
  return timeString.replace(/-|:|Z/g, '').replace('T', 'T');
763
764
  }
764
765
 
766
+ // can be used later if we want to take --startTime and --endTime in local time
765
767
  /**
766
768
  * Convert a given local time string to UTC time string
767
769
  * @param {string} timeString - The time string in the format YYYY-MM-DD:HH:MM:SS
@@ -803,6 +805,7 @@ module.exports = {
803
805
  validateAndInterpolateMesh,
804
806
  getAppRootDir,
805
807
  portNoFlag,
808
+ inspectPortNoFlag,
806
809
  debugFlag,
807
810
  selectFlag,
808
811
  secretsFlag,
@@ -814,7 +817,6 @@ module.exports = {
814
817
  endTimeFlag,
815
818
  logFilenameFlag,
816
819
  pastFlag,
817
- fromFlag,
818
820
  suggestCorrectedDateFormat,
819
821
  parsePastDuration,
820
822
  validateDateTimeRange,
@@ -1,7 +1,7 @@
1
1
  import { ServedTier, addServedHeader } from './served';
2
+ import { buildServer } from './server';
2
3
  import { bindedlogger as logger } from './utils/logger';
3
4
  import { getRequestId } from './utils/requestId';
4
- import { buildServer } from './wranglerServer';
5
5
 
6
6
  let server;
7
7
 
@@ -21,10 +21,10 @@ export default {
21
21
  const { MESH_ID: meshId, LOG_LEVEL: logLevel } = env;
22
22
  const loggerInstance = logger({ logLevel, meshId, requestId });
23
23
  const meshArtifacts = await import('../.mesh');
24
- const rawMesh = await import('../.mesh/.meshrc.json');
24
+ const meshConfig = await import('../.mesh/.meshrc.json');
25
25
 
26
26
  if (!server) {
27
- server = await this.buildAndCacheServer(env, loggerInstance, meshArtifacts, rawMesh);
27
+ server = await this.buildAndCacheServer(env, loggerInstance, meshArtifacts, meshConfig);
28
28
  }
29
29
 
30
30
  loggerInstance.debug('WORKER HOT: Fetching via worker');
@@ -34,11 +34,13 @@ export default {
34
34
  },
35
35
  /**
36
36
  * Build and cache mesh instance/server in global variable.
37
- * @param env
38
- * @param loggerInstance
37
+ * @param env Environment
38
+ * @param logger Logger
39
+ * @param meshArtifacts Mesh artifact
40
+ * @param meshConfig Mesh config
39
41
  */
40
- async buildAndCacheServer(env, loggerInstance, meshArtifacts, meshConfig) {
41
- server = await buildServer(loggerInstance, env, meshArtifacts, meshConfig);
42
+ async buildAndCacheServer(env, logger, meshArtifacts, meshConfig) {
43
+ server = await buildServer(logger, env, meshArtifacts, meshConfig);
42
44
  return server;
43
45
  },
44
46
  };
@@ -0,0 +1,54 @@
1
+ const { spawn } = require('child_process');
2
+ const { readSecretsFile } = require('./serverUtils');
3
+ const packageData = require('../package.json');
4
+ const { join } = require('node:path');
5
+
6
+ /**
7
+ * Starts the wrangler dev server
8
+ * @param command {Command} CLI command
9
+ * @param port Port number
10
+ * @param debug Whether debug mode is enabled
11
+ * @param inspectPort Port number for local dev server inspector
12
+ */
13
+ const start = (command, port, debug, inspectPort) => {
14
+ const wranglerPackageNumber = packageData.dependencies.wrangler;
15
+ const wranglerVersion = `wrangler@${wranglerPackageNumber.replace(/^[\^~]/, '')}`;
16
+ const wranglerToml = join(__dirname, '..', 'wrangler.toml');
17
+ const meshDir = '.mesh';
18
+ const secrets = readSecretsFile(meshDir);
19
+ const entrypoint = join(__dirname, 'worker.js');
20
+
21
+ const commandArgs = [
22
+ wranglerVersion,
23
+ '--config',
24
+ wranglerToml,
25
+ '--cwd',
26
+ process.cwd(),
27
+ 'dev',
28
+ entrypoint,
29
+ '--show-interactive-dev-session',
30
+ 'false',
31
+ '--var',
32
+ `Secret:${JSON.stringify(secrets)}`,
33
+ '--port',
34
+ port,
35
+ '--inspector-port',
36
+ debug ? inspectPort : 0,
37
+ ];
38
+
39
+ const wrangler = spawn('npx', commandArgs, {
40
+ stdio: 'inherit',
41
+ });
42
+
43
+ wrangler.on('close', code => {
44
+ // eslint-disable-next-line no-console
45
+ console.log(`wrangler dev process exited with code ${code}`);
46
+ });
47
+
48
+ wrangler.on('error', error => {
49
+ // eslint-disable-next-line no-console
50
+ console.error(`Failed to start wrangler dev: ${error.message}`);
51
+ });
52
+ };
53
+
54
+ module.exports = { start };
package/wrangler.toml ADDED
@@ -0,0 +1,13 @@
1
+ # Tenant worker core definition. For platform workers metadata configs are used to set bindings.
2
+ name = "tenant-worker-core"
3
+ compatibility_date = "2024-06-03"
4
+
5
+ find_additional_modules = true
6
+ base_dir = ".mesh"
7
+ rules = [
8
+ { type = "CommonJS", globs = ["tenantFiles/**/*.js"] }
9
+ ]
10
+
11
+
12
+ [[migrations]]
13
+ tag = "v1"
@@ -1,32 +0,0 @@
1
- /*
2
- Copyright 2020 Adobe. All rights reserved.
3
- This file is licensed to you under the Apache License, Version 2.0 (the "License");
4
- you may not use this file except in compliance with the License. You may obtain a copy
5
- of the License at http://www.apache.org/licenses/LICENSE-2.0
6
-
7
- Unless required by applicable law or agreed to in writing, software distributed under
8
- the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR REPRESENTATIONS
9
- OF ANY KIND, either express or implied. See the License for the specific language
10
- governing permissions and limitations under the License.
11
- */
12
-
13
- const { Command, flags } = require('@oclif/command');
14
- const aioLogger = require('@adobe/aio-lib-core-logging')('PLUGINNAME', { provider: 'debug' });
15
-
16
- class IndexCommand extends Command {
17
- async run() {
18
- // const { args, flags } = this.parse(IndexCommand)
19
- aioLogger.debug('this is the index command.');
20
- }
21
- }
22
-
23
- IndexCommand.flags = {
24
- someflag: flags.string({ char: 'f', description: 'this is some flag' }),
25
- };
26
-
27
- // this is set in package.json, see https://github.com/oclif/oclif/issues/120
28
- // if not set it will get the first (alphabetical) topic's help description
29
- IndexCommand.description = 'Your description here';
30
- IndexCommand.examples = ['$ aio PLUGINNAME:some_command'];
31
-
32
- module.exports = IndexCommand;