Repository: sequelize/sequelize
File: packages/core/src/import-models.ts (TypeScript)

Code before:
 * @param globPaths
 * @param modelMatch
 */
export async function importModels(globPaths: string | string[], modelMatch?: ModelMatch): Promise<ModelStatic[]> {
  if (Array.isArray(globPaths)) {
    const promises: Array<Promise<ModelStatic[]>> = [];

    for (const globPath of globPaths) {
      promises.push(importModels(globPath, modelMatch));
    }

    return uniq((await Promise.all(promises)).flat(1));
  }

  const promises: Array<Promise<ModelStatic[]>> = [];
  for (const path of await glob(globPaths)) {
    const url = pathToFileURL(path).href;
    promises.push(importModelNoGlob(url, modelMatch));
  }

  return uniq((await Promise.all(promises)).flat(1));
}

async function importModelNoGlob(url: string, modelMatch?: ModelMatch): Promise<ModelStatic[]> {
  const module = await import(url);
  if (module.default && !isModelStatic(module.default) && typeof module.default === 'object') {
    Object.assign(module, module.default);
  }

  return Object.keys(module)
    .filter(exportName => {
      if (!isModelStatic(module[exportName])) {
        return false;
      }

      if (modelMatch) {
        return modelMatch(url, exportName, module[exportName]);
      }

      return true;
    })
    .map(exportName => module[exportName]);
}


Review comment (suggestion):
Adding some info for future maintainers

```suggestion
  // when importing a CJS file, sometimes only the default export is available, as named exports depend on the file's exports being statically analyzable by node. The default exports contains the contents of the file's `module.exports`
  if (module.default && !isModelStatic(module.default) && typeof module.default === 'object') {
```

Code after:
 *
 * @param globPaths
 * @param modelMatch
 */
export async function importModels(globPaths: string | string[], modelMatch?: ModelMatch): Promise<ModelStatic[]> {
  if (Array.isArray(globPaths)) {
    const promises: Array<Promise<ModelStatic[]>> = [];

    for (const globPath of globPaths) {
      promises.push(importModels(globPath, modelMatch));
    }

    return uniq((await Promise.all(promises)).flat(1));
  }

  const promises: Array<Promise<ModelStatic[]>> = [];
  for (const path of await glob(globPaths)) {
    const url = pathToFileURL(path).href;
    promises.push(importModelNoGlob(url, modelMatch));
  }

  return uniq((await Promise.all(promises)).flat(1));
}

async function importModelNoGlob(url: string, modelMatch?: ModelMatch): Promise<ModelStatic[]> {
  let module = await import(url);
  // When importing a CJS file, sometimes only the default export is available,
  // as named exports depend on the file's exports being statically analyzable by node.
  // The default export contains the contents of the file's `module.exports`
  if (module.default && isPlainObject(module.default)) {
    module = { ...module.default, ...module };
  }

  return Object.keys(module)
    .filter(exportName => {
      if (!isModelStatic(module[exportName])) {
        return false;
      }

      if (modelMatch) {
        return modelMatch(url, exportName, module[exportName]);
      }

      return true;
    })
    .map(exportName => module[exportName]);
}