Search code examples
javascriptgoogle-bigqueryuser-defined-functionsh3

BigQuery JavaScript UDF: How to resolve "Cannot use import statement outside module" for h3-js library


Trying to use the Uber H3 API available on GitHub, there's an option for JavaScript. According to BigQuery documentation, this appears to be pretty straight forward on how to reference an external library and a function within in it. The line number the error is referencing looks like a normal import and not sure what exactly is being referenced as a module. It would appear that there are no other references pointing outside the library itself, and the folder structure is intact. Am I pointing at the wrong thing? How do I make BigQuery happy with using the H3 JavaScript library?

For reference, downloaded the H3 code base and loaded into a visible GCP Storage Bucket as used in the Google documentation.

Sample query

CREATE TEMP FUCNTION latLngToCell(lat FLOAT64, lng FLOAT64, res INT64)
RETURNS STRING
LANGUAGE js
OPTIONS (library = 'gs://gcbucket/h3-js-master/lib/h3core.js')
AS r"""
return latLngToCell(lat, lng, res);
""";

SELECT latLngToCell(37.38475, -122.34857, 7)

SyntaxError: Cannot use import statement outside of module at gs://gcbucket/h3-js-master/lib/h3core.js line 21, columns 0-6

GCP BigQuery JavaScript documentation H3-js git repo


Solution

  • A javascript package is made of multiple files/modules (+ dependencies) and h3core.js is just one of these modules for h3-js package.

    You need to bundle them in a single js file that you can load in BigQuery (or in a browser).

    To do so, webpack is the tool to go. Consider below:

    # Install webpack and h3-js in ./node_modules folder
    npm install webpack webpack-cli h3-js
    
    # Bundle installed h3-js package into file h3.js 
    # and make the library available in variable h3
    npx webpack --mode production --entry ./node_modules/h3-js --output-path . --output-filename h3.js --output-library h3 --output-library-type var
    
    # Copy the generated file in your bucket
    gcloud storage cp h3.js gs://gcbucket/h3-js-master/lib/
    

    Your code then works after minor changes (update js filepath + add h3. prefix to latLngToCell) as below:

    CREATE TEMP FUNCTION latLngToCell(lat FLOAT64, lng FLOAT64, res INT64)
    RETURNS STRING
    LANGUAGE js
    OPTIONS (library = 'gs://gcbucket/h3-js-master/lib/h3.js')
    AS r"""
    return h3.latLngToCell(lat, lng, res);
    """;
    
    SELECT latLngToCell(37.38475, -122.34857, 7)