Node.js file loading difference between .load and cli arguments


I’m writing a simple server in vanilla JavaScript and Node.js. I made a database.js file which contains abstractions to interact with my database (redis).

I want to automatically set n_users and n_rooms if they are not yet found in the database. To do so, I have the following lines in database.js:

//set n_users if never set in redis
if (await getKey("n_users") == null){
    setKey("n_users", 0);
//set n_rooms if never set in redis
if (await getKey("n_rooms") == null){
    setKey("n_rooms", 0);

This code works as expected when I open a node session and then type .load database.js. However, the code does not work when directly calling node database.js from the terminal:

if (await getKey("n_users") == null){

SyntaxError: Unexpected identifier

I expected javascript files to work similarly to python files, in the sense that the entirety of a python file gets interpreted when called (or imported). I can’t find any information on how exactly node handles its input files to correct what I’m doing wrong.

Ultimately, I want to be able to automatically execute the above lines of code when running node server.js from a terminal, where server.js requires an object from database.js. What is the best way to acomplish this?


Here’s my database.jsfile:

let User = require('./shared/user').User;
let Room = require('./shared/room').Room;
const md5 = require('./stack_md5').MD5;
const redis = require('redis');
const salt = require('./salt').salt;

var prefix = "JS2023:";
const client = redis.createClient();

//should be map of token to user_id
let TOKENS = {};

async function getKey(key) {
    return await client.get(`${prefix}${key}`);

async function setKey(key, value){
    await client.set(`${prefix}${key}`, value);

async function delKey(key){
    await client.del(`${prefix}${key}`);

//set n_users if never set in redis
if (await getKey("n_users") == null){
    setKey("n_users", 0);
//set n_rooms if never set in redis
if (await getKey("n_rooms") == null){
    setKey("n_rooms", 0);

//using local objects because mongodb doesnt work dont know why
const DB = {
    //user should have at least username and password
    //automatically md5's the password
    //TODO refactor for clarity
    create_user: async function(user_data){
        //username must be unique
        console.log(`user data: ${user_data}`);
        if (await DB.get_user_id_by_username(user_data.username) != undefined) return Promise.reject("Username is already taken!");

        let user_id = parseInt(await getKey(`n_users`));

        let username = user_data.username;
        let user_salt = salt(16);

        let password = md5(user_data.password + user_salt);

        let user = new User({id: user_id, username: username, password: password, salt: user_salt});

        let user_string = JSON.stringify(user);

        setKey(username, user_id)
            .then(DB.set_user_by_id(user_id, user_string))
            .then(setKey("n_users", user_id + 1));

        return user_id;

    get_room_by_id: async function (id){


    set_room_by_id: async function (id, room_string){


    //TODO this returns undefined rn
    get_user_by_id: async function (id) {
        //access DB
        //clean data
        //call callback with data
        return await getKey(id);
    }, //TODO enforce unique usernames

    set_user_by_id: async function (id, user_string) {
        await setKey(id, user_string);
    }, //id should be unique

    get_user_id_by_username: async function (username) {
        return await getKey(username);
    }, //verify password is correct and return cool access token

    authenticate: async function (user_id, password) {
        let user = JSON.parse(await getKey(user_id));

        if (user.password !== md5(password + user.salt)) return Promise.reject("Wrong password!");

        //is user already is online, he is in tokens. will not be authenticated
        for (token in TOKENS) {
            if (TOKENS[token] === user_id) return Promise.reject("User is already connected!");

        var user_token = await DB.token(32);
        //check that token is unique and if not create a new one and hope it is
        while (user_token in TOKENS) user_token = await DB.token(32);
        TOKENS[user_token] = user_id;

        console.log(`generated token for ${user_id}: ${user_token}`)

        return user_token;


    //update_obj an object with the fields to update {username, password, whatever else except id and salt}
    update_user: async function (id, update_obj) {
            .then(function (user) {
                for (let field in update_obj) {
                    switch (field) {
                        //password stored as its hash
                        case "password":
                            //salt is stored by user
                            user[field] = md5(update_obj[field] + user.salt);
                        //id is only given by the server and cannot be modified
                        case "id":
                        case "salt":
                        //update inverse key-value in redis db
                        case "username":
                                .then(setKey(`${id}`, update_obj[field]));
                            user[field] = update_obj[field];
                return user;
            }).then(user => DB.set_user_by_id(id, JSON.stringify(user)));

    //make a random token of given length
    token: function (length) {
        return salt(length);

    // delete token associated with user_id (i.e, user no longer online)
    revoke: async function (user_id) {
        for (token in TOKENS) {
            if (TOKENS[token] == user_id) {
                delete (TOKENS[token]);
                console.log(`${token} revoked, user ${user_id} is no longer online.`);
        //for chaining promises
        return user_id;
    }, // this doesn't need to be async since tokens have to be dynamically maintained

     * check if token string is in tokens map
     * @param token
     * @returns {boolean}
    present: function (token) {
        for (let stored_token in TOKENS) {
            if (token === stored_token) {
                return true;
        return false;


module.exports = {DB, TOKENS};

>Solution :

This statement in your file:

//set n_users if never set in redis
if (await getKey("n_users") == null){
    setKey("n_users", 0);

is attempting to use what is referred to as "top level await" (an await statement at the top level scope of a module). That is only supported in recent versions of nodejs in ESM module files. Your module is a CommonJS module and thus you can’t use top level await. That is the source of the error that is being reported.

There are lots of articles on using ESM module files so I won’t attempt to cover all of that here, but nodejs knows whether a file is an ESM module or a CommonJS module either from the module line in package.json or from the file extension and in ESM module files, you use the newer import syntax, not require().

FYI, there is no point to using await in something like this:

return await client.get(`${prefix}${key}`);

That is functionally the same as:

return client.get(`${prefix}${key}`);

Either way, your function is returning a promise that resolves to the eventual value of client.get().

Leave a ReplyCancel reply