Repository: elastic/synthetics (ts)

Issue:
[Project monitors] Push command unable to parse TypeScript
While Typescript is able to be successfully parsed when running journeys locally, journeys written in TypeScript are unable to be parsed and pushed. 

Example error when pushing types:
```
⚠ lightweight monitors schedule < 1 minute resolution are not supported, will get reset to their nearest minute interval.
--
  | > preparing all monitors
  | Error: Build failed with 1 error:
  | asset:/var/lib/buildkite-agent/builds/bk-agent-elastic-gcp-1666026982627556377/elastic/synthetics-stack-e2e-ci/journeys/create.journey.ts:163:26: ERROR: Expected ")" but found ":"
  | at failureErrorWithLog (/var/lib/buildkite-agent/builds/bk-agent-elastic-gcp-1666026982627556377/elastic/synthetics-stack-e2e-ci/node_modules/esbuild/lib/main.js:1624:15)
  | at /var/lib/buildkite-agent/builds/bk-agent-elastic-gcp-1666026982627556377/elastic/synthetics-stack-e2e-ci/node_modules/esbuild/lib/main.js:1266:28
  | at runOnEndCallbacks (/var/lib/buildkite-agent/builds/bk-agent-elastic-gcp-1666026982627556377/elastic/synthetics-stack-e2e-ci/node_modules/esbuild/lib/main.js:1046:63)
  | at buildResponseToResult (/var/lib/buildkite-agent/builds/bk-agent-elastic-gcp-1666026982627556377/elastic/synthetics-stack-e2e-ci/node_modules/esbuild/lib/main.js:1264:7)
  | at /var/lib/buildkite-agent/builds/bk-agent-elastic-gcp-1666026982627556377/elastic/synthetics-stack-e2e-ci/node_modules/esbuild/lib/main.js:1377:14
  | at /var/lib/buildkite-agent/builds/bk-agent-elastic-gcp-1666026982627556377/elastic/synthetics-stack-e2e-ci/node_modules/esbuild/lib/main.js:678:9
  | at handleIncomingPacket (/var/lib/buildkite-agent/builds/bk-agent-elastic-gcp-1666026982627556377/elastic/synthetics-stack-e2e-ci/node_modules/esbuild/lib/main.js:775:9)
  | at Socket.readFromStdout (/var/lib/buildkite-agent/builds/bk-agent-elastic-gcp-1666026982627556377/elastic/synthetics-stack-e2e-ci/node_modules/esbuild/lib/main.js:644:7)
  | at Socket.emit (node:events:513:28)
  | at Socket.emit (node:domain:489:12) {
  | errors: [
  | {
  | detail: undefined,
  | id: '',
  | location: [Object],
  | notes: [],
  | pluginName: '',
  | text: 'Expected ")" but found ":"'
  | }
  | ],
  | warnings: []
  | }
```

Pull request:
fix: use correct loader for journey files
-  fix #625 
- When journey files are pushed, We treat these files differently when bundling 
    1. Entry paths - Journey files
    2. Imported paths - Other deps / local files imported by the journey files itself. 

- When the journey files are loaded by the bundler, the underlying loader in the `ES build` was defaulting to `JS` which throws error when `Typescript types` are used inside the journey files. This PR fixes the problem by using appropriate loader for the journey files when `push` command is invoked. The test is also added to ensure this does not break in the future. 

### Testing
1. Build the PR - `npm run build`
2. Create an example journey, `example.journey.ts`
3. Use the example below which relies on TS typings 
```ts
const createJourney = (name: string) => {  // TS types
  journey(name, ({ page, params }) => {
    step('launch application', async () => {
      await page.goto(params.url);
    });
  });
};

['a', 'b'].forEach(a => createJourney(a));
``` 
4. Run `SYNTHETICS_API_KEY="" npm run push`



Patch:
diff --git a/src/push/plugin.ts b/src/push/plugin.ts
index 385c19f..fdf677f 100644
--- a/src/push/plugin.ts
+++ b/src/push/plugin.ts
@@ -39,6 +39,11 @@ export function commonOptions(): esbuild.BuildOptions {
     bundle: true,
     external: ['@elastic/synthetics'],
     minify: false,
+    minifyIdentifiers: false,
+    minifySyntax: false,
+    minifyWhitespace: false,
+    treeShaking: false,
+    keepNames: false,
     platform: 'node',
     logLevel: 'silent',
     format: 'esm',
@@ -108,7 +113,7 @@ export function MultiAssetPlugin(callback: PluginCallback): esbuild.Plugin {
         if (args.kind === 'entry-point') {
           return {
             path: args.path,
-            namespace: 'asset',
+            namespace: 'journey',
           };
         }
 
@@ -142,10 +147,21 @@ export function MultiAssetPlugin(callback: PluginCallback): esbuild.Plugin {
         };
       });
 
-      build.onLoad({ filter: /.*?/, namespace: 'asset' }, async args => {
+      build.onLoad({ filter: /.*?/, namespace: 'journey' }, async args => {
         const contents = await fs.readFile(args.path, 'utf-8');
         callback({ path: args.path, contents });
-        return { contents };
+
+        // Use correct loader for the journey entry path
+        let loader: esbuild.Loader = 'default';
+        const ext = extname(args.path).slice(1);
+        if (ext === 'cjs' || ext === 'mjs') {
+          loader = 'js';
+        } else if (ext === 'cts' || ext === 'mts') {
+          loader = 'ts';
+        } else {
+          loader = ext as esbuild.Loader;
+        }
+        return { contents, loader };
       });
     },
   };


Test patch:
diff --git a/__tests__/push/bundler.test.ts b/__tests__/push/bundler.test.ts
index 8a263a7..e791c43 100644
--- a/__tests__/push/bundler.test.ts
+++ b/__tests__/push/bundler.test.ts
@@ -78,11 +78,15 @@ describe('Bundler', () => {
 import isPositive from 'is-positive';
 
 journey('journey 1', () => {
-  monitor.use({ id: 'duplicate id' })
+  monitor.use({ id: 'duplicate id' });
+  launchStep(-1);
+});
+
+const launchStep = (no: number) => {
   step("step1", () => {
-    isPositive(-1);
+    isPositive(no);
   })
-});`
+};`
     );
   });