Eslint doesn't recognize "Accounts"

Hai All,

I’m using VSCode with Eslint.

VSCode/Eslint don’t recognize the Accounts object, forcing me to add // eslint-disable-next-line no-undef comments all over the place.

This is my .eslintrc.json file:

{
    "env": {
        "browser": true,
        "es2021": true,
        "node": true
    },
    "extends": [
        "standard",
        "eslint:recommended",
        "plugin:solid/recommended"
    ],
    "parserOptions": {
        "ecmaVersion": "latest",
        "sourceType": "module",
        "ecmaFeatures": {
            "jsx": true
        }
    },
    "plugins": [
        "solid"
    ],
    "rules": {
        "solid/reactivity": "warn",
        "solid/no-destructure": "warn",
        "solid/jsx-no-undef": "error",
        "quotes": [1, "single"],
        "semi": [1, "never"]
    }
}

Is there any way to fix this?

Thank you.

Check the Meteor Guide

1 Like

As long as you are importing the Accounts variable, I’m not sure why eslint would have any issues.

Thanks for your answer, @copleykj

What package should I import it from?

import { Accounts } from 'meteor/accounts-base'

@paulishca, thank you for your answer.

When I applied your suggestion (import...), I got this:

accounts-base:17 Uncaught (in promise) SyntaxError: Unexpected token 'default' (at accounts-base:17:14)

Any idea?

Can you provide your code? This is generally a good idea in most cases, otherwise we don’t have any context to diagnose your issue.

Here’s the code

import { Meteor } from 'meteor/meteor'
// import { Accounts } from 'meteor/accounts-base' <== RUNTIME ERROR
import { BaseCollection } from './BaseCollection'
import { SimpleSchema } from 'meteor/aldeed:simple-schema'
import { UserType, taxIdTypes } from '../helpers/consts'

export const AccountsCollection = new BaseCollection('accounts')

AccountsCollection.schema = new SimpleSchema({
  shortName: { type: String, optional: false },
  legalName: { type: String, optional: false },
  address: { type: String },
  city: { type: String },
  state: { type: String },
  zip: { type: String, optional: true },
  country: { type: String, defaultValue: 'US' },
  techContact: { type: Object, optional: false },
  'techContact.firstName': { type: String, optional: false },
  'techContact.lastName': { type: String, optional: false },
  'techContact.email': { type: String, optional: false },
  'techContact.phone': { type: String, optional: true },
  billingContact: { type: Object },
  'billingContact.firstName': { type: String, optional: false },
  'billingContact.lastName': { type: String, optional: false },
  'billingContact.email': { type: String, optional: false },
  'billingContact.phone': { type: String, optional: true },
  active: { type: Boolean, optional: true, defaultValue: true }
})

AccountsCollection.attachSchema(AccountsCollection.schema)

// Creates the account and adds the admin user with a random password
const createAccount = async (account) => {
  const accountId = await AccountsCollection.insert(account)
  // Add admin user for this account
  const adminUser = {
    username: account.techContact.email,
    email: account.techContact.email,
    profile: {
      type: 'accountAdmin',
      account: accountId,
      firstName: account.techContact.firstName,
      lastName: account.techContact.lastName,
      phone: account.techContact.phone,
      address: account.address,
      city: account.city,
      state: account.state,
      zip: account.zip,
      country: account.country
    }
  }
  if (Meteor.isServer) {
    // eslint-disable-next-line no-undef  <== ESLint doesn't recognize 'Accounts'
    await Accounts.createUserVerifyingEmail(adminUser)  // <== Error when import is present
  }
  return accountId
}

Meteor.methods({
  'account.create' (account) {
    if (!Meteor.userId()) {
      throw new Meteor.Error('Not logged in')
    }
    const user = Meteor.user()
    if (user.profile.type !== UserType.globalAdmin) {
      throw new Meteor.Error('Not authorized')
    }
    try {
      AccountsCollection.schema.validate(account)
    } catch (error) {
      throw new Meteor.Error(`Invalid request: ${error.message}`)
    }
    const checkByShortName = AccountsCollection.findOne({ shortName: account.shortName })
    if (checkByShortName) {
      throw new Meteor.Error('Account with this short name already exists')
    }
    const checkUser = Meteor.users.findOne({ username: account.techContact.email })
    if (checkUser) {
      throw new Meteor.Error('User with this email already exists')
    }
    return createAccount(account)
  }
})

if (Meteor.isServer) {
  AccountsCollection.createIndex({ shortName: 1 }, { unique: true })
  Meteor.publish('accounts', function () {
    if (!this.userId) {
      return this.ready()
    }
    const user = Meteor.users.findOne(this.userId)
    if (!user) {
      return this.ready()
    }
    if (user.profile.type === UserType.globalAdmin) {
      return AccountsCollection.find()
    }
    throw new Meteor.Error('Not authorized')
  })
}

You’ll likely want to import from meteor/accounts-password rather than meteor/accounts-base being that createUserVerifyingEmail is added to the Accounts object in the accounts-password package.

That fixed it for the server.

Now, I get this in the browser console:
Uncaught (in promise) SyntaxError: The requested module '/@id/__x00__meteor/accounts-password' does not provide an export named 'Accounts' (at AccountsCollection.js:2:10)

I’ll just stick to the eslint-disable-next-line no-undef comment with no import.

Thank you all.

This is odd.

import { Accounts } from 'meteor/accounts-base';

The above is what has worked for me. I was going to suggest wrapping in an isServer block but you are already doing that.

As a test, you could try importing within the isServer block (eslint won’t like this so ignore it for the test). If that works ok, it may be that the code (or at least the method) is being pulled into the client code where it shouldn’t be and we can then figure out why.

@hemalr87

It seems the code effectively ends up at the client. In the developer tools I see the code:

As you can see, when enclosing the import in a isServer block it throws a syntax error when loading the page:
Uncaught (in promise) SyntaxError: Unexpected token '{' (at AccountsCollection.jst=1699572376219:60:12)

BTW, I’m using meteor-vite (GitHub - JorgenVatle/meteor-vite: ⚡ Replace Meteor's bundler with Vite for blazing fast build-times) Does it have something to do with this situation?

Another question: This code is in the imports/api folder. Should I put it in another location to hide it from the client?

Thanks!

You have a Meteor method in this file. How do you inform the client about the definition of account.create method?

[Addendum]
Disregard my question if you don’t use client stubs. I immediately see Meteor.isServer in the code and I immediately consider a stub definition.

Eslint? I removed Eslint and Prettier a long time ago, they cause a lot of unnecessary changes, and slow down development.