Javascript SDK without node.js/npm

I try to decode my fit files wirh the Javascript SDK. I have to use it solely from a server in my browser without node.js and npm. So how can I do that? I have to say that I am not a Javascript expert, although I am able to write some code. How do I have to import the SDK without npm? The official document only gives instructions for npm, although it says it works also without node.js in a browser. Can someone give me some lines of basic code please that imports the SDK and a fit file and then decodes the fit file? That would really be of enormous help for me.

I even trtied the code from the documentation with npm in a VM to have at least a small sense of achievement, but all I get is "Cannot use import statement outside a module" ...

Thanks in advance for helping!

  • Put type = “module” in the script tag

  • Thanks for your answer. But unfortunaltely this does not match with my question. I know that I could put "module" in the script tag, but the step before is missing: How do I  import the SDK without npm? What would be the correct syntax for that?

    And if your answer is related to the error I get with the example code from the official documentation and nodejs: there is no script tag where I could enter "module" when I do "node test,js" on the CLI (where test.js is just copy/paste from the official documentation (developer.garmin.com/.../).

  • The FIT JavaScript SDK is not available in a CDN, so you can not import it using a <script/> tag in an html flie. But that is not to say that the SDK can not run client-side in a browser. I am aware of multiple projects that use the SDK in a static web-app. But to do that, you need to use a JavaScript Bundler. That requires creating a Node project, so packages can be imported and used. But that does not mean that the bundled code needs to execute under Node.The bundler will create an html file and a minified JavaScript file that can be deployed as a static website. Search for "javascript bundler 2024" and you should find multiple articles on the subject.

  • You host it yourself but still can use import / export natively in modern browsers.  You don't need to bundle it with native support, that's only required for older browsers.  Combined it with http2 or http3 and there no real overhead compared to a bundled file anyway.  Webpack is a bit last decade way of doing things really.

  • That is fairly trivial, all the JavaScript files are in the JS folder in the FIT SDK zipped download from Garmin.  Add them to your project source where your HTML sits

    Then you can do (with no changes to the FIT SDK JavaScript files)

    <!DOCTYPE html>
    <html>
      <head>
        <title>Example Fit SDK in browser</title>
        <script type="importmap">
          {
            "imports": {
              "Decoder": "./fitsdk/decoder.js",
              "Profile": "./fitsdk/profile.js",
              "Stream": "./fitsdk/stream.js",
              "Utils": "./fitsdk/utils.js"
            }
          }
        </script>
        <script type="module">
          import Decoder from "Decoder";
          import Stream from "Stream";
    
          document.addEventListener("DOMContentLoaded", (e) => {
            const inputNode = document.getElementById("file");
            inputNode.addEventListener("change", processFit);
          });
    
          const processFit = async (e) => {
           // Convert fit file into format decoder can process
            const selectedFile = e.target.files[0];
            const arrayBuffer = await readFile(selectedFile);
            const streamFit = Stream.fromArrayBuffer(arrayBuffer);
           // Decode
            if (Decoder.isFIT(streamFit)) {
              console.log("Processing fit file");
              let d = new Decoder(streamFit);
              const { messages, errors } = d.read();
              // Write JSON output to console as just an example
              console.log(messages);
            } else {
              console.log("Selected file is not a fit file");
            }
          };
         
          const readFile = (file) => {
            return new Promise((resolve, reject) => {
              // Create file reader
              let reader = new FileReader();
              // Register event listeners
              reader.addEventListener("loadend", (e) => resolve(e.target.result));
              reader.addEventListener("error", reject);
              // Read file
              reader.readAsArrayBuffer(file);
            });
          };
        </script>
      </head>
      <body>
        <input id="file" type="file" />
      </body>
    </html>

    With the output in messages as JSON for processing

    {
        "fileIdMesgs": [
            {
                "serialNumber": 3421548093,
                "timeCreated": "2023-12-19T19:02:14.000Z",
                "manufacturer": "garmin",
                "product": 3589,
                "type": "activity",
                "garminProduct": "fr745"
            }
        ],
        "fileCreatorMesgs": [
            {
                "softwareVersion": 1300
            }
        ],
        "eventMesgs": [
            {
                "timestamp": "2023-12-19T19:02:14.000Z",
                "data": 0,
                "event": "timer",
                "eventType": "start",
                "eventGroup": 0,
                "timerTrigger": "manual"
            },
            {
                "timestamp": "2023-12-19T19:12:50.000Z",
                "data": 0,
                "event": "timer",
                "eventType": "stopAll",
                "eventGroup": 0,
                "timerTrigger": "manual"
            },
            {
                "timestamp": "2023-12-19T19:13:23.000Z",
                "data": 0,
                "event": "timer",
                "eventType": "start",
                "eventGroup": 0,
                "timerTrigger": "manual"
            },

  • Thank you so much @Ultra That was exactly what I was looking for. To be honest I did not know this syntax with "importmap". Learned something again ... Now I can move on and generate my analyzes.