Using Await in Accounts.onCreateUser for Mv3? [solved]

Here is sample code from the Mv3 docs for Accounts.onCreateUser:

Accounts.onCreateUser((options, user) => {
  const customizedUser = Object.assign(
    {
      dexterity: _.random(1, 6) + _.random(1, 6) + _.random(1, 6),
    },
    user
  );

  // We still want the default hook's 'profile' behavior.
  if (options.profile) {
    customizedUser.profile = options.profile;
  }

  return customizedUser;
});

I tried it like that in my app, but I’m getting an error saying I can’t use await here.

Accounts.onCreateUser((options, user) => {
    [.....]

    const newEPUser = await connectors.epUserData.create(args);

    [.....]
});

I also tried it like this, but got an error:

Accounts.onCreateUser = async (options, user) => {

What is the correct way to access await within Accounts.onCreateUser ?

Did you try this?

Accounts.onCreateUser(async (options, user) => {...})

That seems to be a step in the right direction - it lets me run the function. But I am still getting an error.

If I try it like this:

Accounts.onCreateUser(async (options, user) => {
    debugger;
    async function manageOnCreateUser(options, user){
        debugger;

        let args = {};
        args.id = user._id;

        args.name_first = options.first_name;
        args.name_last = options.last_name;
        args.email = options.email;
        args.home_state = options.profile.home_state;
        args.accepted_user_terms_and_privacy_terms = options.profile.agreesToTerms;
        args.date_accepted_user_terms_and_privacy_terms = sequelizeFn('NOW');

        const newEPUser = await connectors.epUserData.create(args);

        if (args.name_first) {
            let sql = `UPDATE "epUserDatum"
                       SET "epUserNumber" = nextval('epUserNumber_seq')
                       WHERE "id" = '${args.id}';`

            let results = await getQueryResults(sql);
        }

        return user;
    }

    return new Promise((resolve, reject) => {
        resolve(manageOnCreateUser(options, user))
    })
});

… I get:

Exception while invoking method ‘createUser’ TypeError: Promise.await is not a function

Note the error is in 'createUser, which is calling onCreateUser`.

If I try it like this:

Accounts.onCreateUser(async (options, user) => {
    debugger;
    let args = {};
    args.id = user._id;

    args.name_first = options.first_name;
    args.name_last = options.last_name;
    args.email = options.email;
    args.home_state = options.profile.home_state;
    args.accepted_user_terms_and_privacy_terms = options.profile.agreesToTerms;
    args.date_accepted_user_terms_and_privacy_terms = sequelizeFn('NOW');

    const newEPUser = await connectors.epUserData.create(args);

    if (args.name_first) {
        let sql = `UPDATE "epUserDatum"
                   SET "epUserNumber" = nextval('epUserNumber_seq')
                   WHERE "id" = '${args.id}';`

        let results = await getQueryResults(sql);
    }

    return user;
});

… I get:

Internal server error

What am I missing?

Wondering why you are doing it like that instead of like this:

return manageOnCreateUser(options, user));

Anyway, if async functions are not supported for that callback, you can do it like this:

Accounts.onCreateUser((options, user){
    debugger;

    Meteor.defer(async () => {
        const args = {};
        args.id = user._id;

        args.name_first = options.first_name;
        args.name_last = options.last_name;
        args.email = options.email;
        args.home_state = options.profile.home_state;
        args.accepted_user_terms_and_privacy_terms = options.profile.agreesToTerms;
        args.date_accepted_user_terms_and_privacy_terms = sequelizeFn('NOW');

        const newEPUser = await connectors.epUserData.create(args);

        if (args.name_first) {
            const sql = `UPDATE "epUserDatum"
                       SET "epUserNumber" = nextval('epUserNumber_seq')
                       WHERE "id" = '${args.id}';`

            getQueryResults(sql);
        }
    });
     
    return user;
});

I tried it as you suggested, and got:

Exception while invoking method ‘createUser’ TypeError: Promise.await is not a function

I also tried it as copied below, with the same error:

Exception while invoking method ‘createUser’ TypeError: Promise.await is not a function

The two calls to await return without error – it’s when the function returns to the caller, createUser, that the error is thrown.

It seems like createUser wants to get a promise back. Could that be it?

Accounts.onCreateUser((options, user) => {
    debugger;

    Meteor.defer(async () => {
        debugger;

        const args = {};
        args.id = user._id;

        args.name_first = options.first_name;
        args.name_last = options.last_name;
        args.email = options.email;
        args.home_state = options.profile.home_state;
        args.accepted_user_terms_and_privacy_terms = options.profile.agreesToTerms;
        args.date_accepted_user_terms_and_privacy_terms = sequelizeFn('NOW');

        const newEPUser = await connectors.epUserData.create(args);

        let results = []
        if (args.name_first) {
            const sql = `UPDATE "epUserDatum"
                       SET "epUserNumber" = nextval('epUserNumber_seq')
                       WHERE "id" = '${args.id}';`

                results = await getQueryResults(sql);
            let a = 100
        }
    });

    return user;
});

Hmmm… the Accounts.onCreateUser sample code from the Mv3 docs throws the same error. I’ll start a new thread about this.

We do something like this on Galaxy 2 using Meteor v3, and it works fine.

Accounts.onCreateUser(async ({ username }) => {
// more code here
await AccountsCollection.createGalaxyAccount({ username });

// more code here
return {
  username
}
})

@hschmaiske I’m curious why the sample code from the docs throws an error. Can you drop the sample code into your app for a second and see if it throws?

I see what it was. I had a Promise.await call in my Accounts.emailTemplates.verifyEmail template, which was getting called by CreateUser, but not showing up in the stack trace.

Marking this “solved.”

That makes sense. Perhaps you could open an issue and request it to be part of the stack trace.

Interesting. Is that something the Meteor code could put in the stack trace? I guess I thought that was a function of node.js.

Hmmmm… certainly Meteor could issue a console.log warning.