Your first bundle

In map.apps, functions are made available to apps as bundles. So it might not be a surprise that your first extension will be a bundle, too.

In this tutorial
Following this section we will create a brand new bundle to extend map.apps. The bundle will fetch some weather data from the internet and print it into the browser console on startup. We will also create a new app that will use the bundle.

What you need

To follow this guide you need:

Step 1: Create a minimal bundle

map.apps for Developers already contains an extension, the sample_camera bundle located in src/main/js/bundles/sample_camera. As you can see, a bundle is a folder with several files and folders in it, some are optional and some are mandatory. We are going to add a new bundle called weather in a second. It will host the code needed to fetch and print the weather data.

Let’s create the weather bundle from scratch and extend it step by step:

  1. Open map.apps for Developers in VS Code.

  2. Run map.apps by clicking TerminalRun TaskRun map.apps for Developers from VS Code’s top-most menu.

  3. Create the folder weather inside src/main/js/bundles.
    This is the new bundle folder that will contain all code and all other resources making up the bundle.

  4. Create the file src/main/js/bundles/weather/manifest.json.
    Every bundle must have a manifest.json file in its top folder. The file contains all the important information about a bundle.

  5. Open the manifest.json file, set the following content, and save the file:

    {
      "name": "weather",
      "version": "1.0.0"
    }

    Name and version are the minimum required information for a bundle. Here, we defined that the new bundle is identified by the name weather and the version 1.0.

Now it is time to check if everything worked out so far. In a browser open the following URL to list all bundles available in your instance of map.apps for Developers: http://localhost:9090/resources/jsregistry/root.
That’s a pretty long list of bundles! Every bundle in this list implements one of the many functions that are available in map.apps.
As it is sorted alphabetically, we should be able to find our new bundle by its name weather right at the bottom:

jsregistry

Congratulations 🎉

We just created our first map.apps bundle.

Well, it does not do anything, yet, so let’s…​

Step 2: Add some code

  1. Create the file Weather.ts in src/main/js/bundles/weather.

  2. Add the following code to Weather.ts and save the file.

    export class Weather {
        activate(): any {
            fetch('https://api.open-meteo.com/v1/forecast?latitude=51.96&longitude=7.63&current_weather=true')
                .then((response) => response.json())
                .then((data) => {
                    console.info("### Your weather service");
                    console.info(`### Muenster, Germany: ${data.current_weather.temperature} °C`);
                    console.info("### -- Weather data by https://open-meteo.com/,"
                    + " offered under the CC BY 4.0 license (https://creativecommons.org/licenses/by/4.0/)");
                })
                .catch((error) => console.info(`Error requesting weather data: ${error}`));
        }
    }

    When activate() is called, we request the current weather information for the coordinates of Muenster, Germany, from open-meteo.com. As soon as the JSON response data is available, we print the current temperature in the browser console.

  3. After copying the code into Weather.ts, you need to add an empty line at the end of the file. This is necessary because map.apps for Developers defines rules how source code files must be formatted. One rules states that every .ts file must end with an empty line. If the empty line is missing, you will get errors when the project is built later own.

  4. Create the file module.ts in src/main/js/bundles/weather.
    This file is necessary to tell the JavaScript module loader which files to load when the bundle is activated.

  5. Add the following code to module.ts and save the file:

    export { Weather } from "./Weather";

    This will make sure that the runtime environment can find the Weather class defined in Weather.ts when the bundle is started.

  6. And again, add an empty line to the end of module.ts.

  7. Edit the manifest.json file, adding the "i18n" and "components" properties like this:

    {
        "name": "weather",
        "version": "1.0.0",
        "i18n" : [],
        "components": [
            {
                "name": "Weather"
            }
        ]
    }

Now that the code is all there, we just need to make sure, it is used in an app.

Step 3: Create the weather app

As the weather bundle is now available in your running map.apps instance, apps can start using it. We will now create a new app that is supposed to use the weather bundle.

  1. In VS Code create an empty file src/main/js/apps/weather/app.json.

  2. Add the following JSON to the file and save it:

    {
        "load": {
            "bundleLocations": [
                "localbundles",
                "bundles"
            ],
            "allowedBundles": [
                "system@^4.14.1",
                "splashscreen@^4.14.1",
                "templatelayout@^4.14.1",
                "template-seasons@^4.14.1",
                "theme-everlasting@^4.14.1",
                "map-init@^4.14.1",
                "map-preload-2D@^4.14.1",
                "weather@^1.0.0"
            ]
        },
        "bundles": {
            "map-init": {
                "Config": {
                    "basemaps": [{
                        "id": "satellite",
                        "basemap": "satellite",
                        "selected": true
                    }],
                    "view": {
                        "viewmode": "2D",
                        "zoom": 4
                    }
                }
            }
        }
    }

    You don’t need to understand the details of this app configuration. It sets up a very basic map.apps app with a satellite image background. The most interesting part is the list of bundles defined by the allowedBundles property. This property lists all bundles that an app requires to get loaded when the app is started in a browser. You certainly already noticed, that the weather bundle is part of the list. Please note, that we are using the exact values of the properties "name" and "version" defined in the manifest.json file of the weather bundle. Name and version are separated by a @, and the version is prefixed with a ^.

Step 4: Action!

Now we are going to check, if the "weather" app works a expected.

  1. Load the following URL in a browser: http://localhost:9090?app=weather.

  2. Open the browser console by pressing Ctrl+Shift+J.

  3. Watch the console while the weather app is loading. It will generate plenty of log lines, but eventually it will print out the weather data as expected like this:

    Browser console with weather information

Congratulations 🎉

You just contributed a new feature to map.apps by implementing a bundle that can be used in a map.apps app.

Wouldn’t it be nice to expand the bundle’s capabilities to print other information or even better: display some weather data in the app title bar?

Check out the Next steps to get deeper into map.apps development.

If it didn’t work out…​

If you do not get any weather data, first check that https://api.open-meteo.com/v1/forecast?latitude=51.96&longitude=7.63&current_weather=true is available from your browser. If JSON-formatted weather information is returned, there might be a typo or similar elsewhere. We recommend to make a fresh start and follow the steps of this tutorial again. First, you need to remove the weather folder we created in src/main/js/bundles. Then start this tutorial from the beginning. Be sure to use upper and lower case exactly as in the instructions. Also, make sure that your edits result in valid JSON. It’s too easy to miss a comma when adding properties to it, for example.

Recap

In this tutorial, we…​

  • …​ created a bundle called weather to host functionality for a weather service.

  • …​ browsed the list of all bundles available in map.apps for Developers to find the new weather bundle.

  • …​ added the operational TypeScript code to the file Weather.ts.

  • …​ added the some mystical lines to the files module.ts and manifest.json.
    See What does actually happen here?, right after this recap, for some more details.

  • …​ referenced the bundle in the new weather app.

  • …​ loaded the weather app to check the browser console for the expected output.

That was a lot.

Maybe you want to know a bit more about the mystical lines you added to module.ts and manifest.json. If not, have a look at the next steps.

What does actually happen here?

After adding the code to Weather.ts we also edited module.ts, manifest.json, and app.json. How are these files related?

This is a rough description of what happens, when the weather app is started by map.apps:

  1. map.apps loads every bundle listed in the property allowedBundles of app.json. So, map.apps loads the weather bundle, too.

  2. map.apps reads the manifest.json file of the weather bundle.

  3. map.apps loads the modules.ts file of the weather bundle.
    This exports the Weather class of the Weather.ts file.

  4. For any components entry in the manifest.json file, map.apps tries to activate the component, that is:

    • map.apps tries to find a class within this bundle that matches the name of the component (Weather).

    • map.apps instantiates the class.

    • map.apps calls activate() on the instantiated class.

The last step will execute the code that requests the current weather data from the open-meteo web service.

Some things to remember, but don’t worry if your memory is overloaded:

  • A bundle cannot only declare one but an arbitrary number of components in its manifest.json. Actually, most bundles declare more than one component.

  • A module.ts file can export more than one class from any number of modules (TypeScript or JavaScript files) available in a bundle.

  • Components defined in the manifest.json file are the building blocks of map.apps bundles. In this tutorial we just used the very most simple form of them. If you dare, take a look at the components reference documentation.

Next steps

You just created a new bundle in a development environment provided by the map.apps for Developers project. Well…​, that means that the bundle can be used by the weather app in your development environment.

Typically you want to deploy the bundle to a central map.apps instance, where all the "real" apps of your organization or project are hosted. And they are waiting to finally use your weather bundle! In Deploy a bundle to a map.apps instance we will explore the different ways to make a bundle available on another map.apps instance.