Typescript Here Maps for Javascript in PCF

I want to integrate Here Maps for Javascript in PowerApps Code Component which is written in typescript.

I am getting __webpack_require__is not defined error. Because PCF have their own webpack, I added a webpack script and add “bundle”: “webpack” to my package.json.

I am lost at what I should be doing to fix this.

My current output on the web

index.ts

import { IInputs, IOutputs } from "./generated/ManifestTypes";
import "@here/maps-api-for-javascript";

export class heremaps
  implements ComponentFramework.StandardControl<IInputs, IOutputs>
{
  private _container: HTMLDivElement;
  private _map: H.Map | null = null;

  // Hardcoded API key
  private readonly API_KEY: string =
    "api_key"; 

  constructor() {}

  /**
   * @param context The entire property bag available to control via Context Object; It contains values as set up by the customizer mapped to property names defined in the manifest, as well as utility functions.
   * @param notifyOutputChanged A callback method to alert the framework that the control has new outputs ready to be retrieved asynchronously.
   * @param state A piece of data that persists in one session for a single user. Can be set at any point in a controls life cycle by calling 'setControlState' in the Mode interface.
   * @param container If a control is marked control-type='standard', it will receive an empty div element within which it can render its content.
   */

  public init(
    context: ComponentFramework.Context<IInputs>,
    notifyOutputChanged: () => void,
    state: ComponentFramework.Dictionary,
    container: HTMLDivElement
  ): void {
    // Create or reuse the container for the map

    if (!this._container) {
      this._container = document.createElement("div");
      this._container.id = "map";
      this._container.style.width = "100%";
      this._container.style.height = "100%";
      container.appendChild(this._container);
    } else {
      // Clear the container's content to avoid reusing the same element
      this._container.innerHTML = "";
    }

    // Dispose of any existing map instance to prevent "already in use" errors
    if (this._map) {
      this._map.dispose();
      this._map = null;
    }

    // Initialize the map
    this.initializeMap();
  }

  private initializeMap(): void {
    // Initialize communication with the platform
    const platform = new H.service.Platform({
      apikey: this.API_KEY,
    });

    // Create the map instance
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const defaultLayers: any = platform.createDefaultLayers();
    this._map = new H.Map(this._container, defaultLayers.vector.normal.map, {
      center: { lat: 52, lng: 5 },
      zoom: 5,
      pixelRatio: 2,
    });

    // Add a resize listener to ensure the map occupies the whole container
    window.addEventListener("resize", () => this._map?.getViewPort().resize());

    // Make the map interactive
    const behavior = new H.mapevents.Behavior(
      new H.mapevents.MapEvents(this._map)
    );
    const ui = H.ui.UI.createDefault(this._map, defaultLayers);

    // Add the polyline
    this.addPolylineToMap();
  }

  private addPolylineToMap(): void {
    const lineString = new H.geo.LineString();
    lineString.pushPoint({ lat: 53.3477, lng: -6.2597 }); // Dublin
    lineString.pushPoint({ lat: 51.5008, lng: -0.1224 }); // London
    lineString.pushPoint({ lat: 48.8567, lng: 2.3508 }); // Paris
    lineString.pushPoint({ lat: 52.5166, lng: 13.3833 }); // Berlin

    this._map?.addObject(new H.map.Polyline(lineString));
  }

  public updateView(context: ComponentFramework.Context<IInputs>): void {
    // Handle updates if needed, but avoid re-initializing the map
  }

  public getOutputs(): IOutputs {
    return {};
  }

  public destroy(): void {
    // Cleanup map instance
    if (this._map) {
      this._map.dispose();
      this._map = null;
    }
  }
}

webpack.config.js

import { resolve as _resolve } from "path";
import { fileURLToPath } from "url";
import { dirname } from "path";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

export const entry = "./index.ts";
export const module = {
  rules: [
    {
      test: /.tsx?$/,
      use: "ts-loader",
      exclude: /node_modules/,
    },
  ],
};
export const resolve = {
  extensions: [".tsx", ".ts", ".js"],
};
export const output = {
  filename: "index.ts",
  path: _resolve(__dirname, "dist"),
};
export const mode = "production";
export const node = {
  global: false,
};
export const performance = {
  maxEntrypointSize: 2048000,
  maxAssetSize: 2048000,
};

pcfconfig.json

{
  "outDir": "./out/controls",
  "build": {
    "production": {
      "webpack": "./webpack.config.js"
    }
  }
}

package.json

{
  "name": "pcf-project",
  "version": "1.0.0",
  "description": "Project containing your PowerApps Component Framework (PCF) control.",
  "scripts": {
    "build": "pcf-scripts build",
    "clean": "pcf-scripts clean",
    "lint": "pcf-scripts lint",
    "lint:fix": "pcf-scripts lint fix",
    "rebuild": "pcf-scripts rebuild",
    "start": "pcf-scripts start",
    "start:watch": "pcf-scripts start watch",
    "refreshTypes": "pcf-scripts refreshTypes",
    "bundle": "webpack",
    "type": "module"
  },
  "dependencies": {
    "@here/maps-api-for-javascript": "^1.57.0",
    "@microsoft/eslint-plugin-power-apps": "^0.2.33",
    "@types/node": "^18.19.31",
    "@types/powerapps-component-framework": "^1.3.11",
    "@typescript-eslint/eslint-plugin": "^7.7.1",
    "@typescript-eslint/parser": "^7.7.1",
    "eslint": "^8.57.0",
    "eslint-plugin-import": "^2.29.1",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-promise": "^6.1.1",
    "ts-loader": "^9.5.1",
    "webpack": "^5.94.0",
    "webpack-cli": "^5.1.4"
  },
  "devDependencies": {
    "@here/maps-api-for-javascript": "^1.57.0",
    "@microsoft/eslint-plugin-power-apps": "^0.2.33",
    "@types/node": "^18.19.31",
    "@types/powerapps-component-framework": "^1.3.11",
    "@typescript-eslint/eslint-plugin": "^7.7.1",
    "@typescript-eslint/parser": "^7.7.1",
    "eslint": "^8.57.0",
    "eslint-plugin-import": "^2.29.1",
    "eslint-plugin-node": "^11.1.0",
    "eslint-plugin-promise": "^6.1.1",
    "pcf-scripts": "^1",
    "pcf-start": "^1",
    "ts-loader": "^9.5.1",
    "typescript": "^4.9.5",
    "webpack": "^5.94.0",
    "webpack-cli": "^5.1.4"
  }
}