Repository: nuxt/nuxt
File: packages/nuxt/src/core/app.ts (TypeScript)

Code before:
      `${middlewareDir}/*{${extGlob}}`,
      ...nuxt.options.future.compatibilityVersion === 4
        ? [`${middlewareDir}/*/index{${extGlob}}`]
        : [],
    ])
    for (const file of middlewareFiles) {
      const name = getNameFromPath(file)
      if (!name) {
        // Ignore files like `~/middleware/index.vue` which end up not having a name at all
        logger.warn(`No middleware name could be resolved for \`~/${relative(nuxt.options.srcDir, file)}\`. Bear in mind that \`index\` is ignored for the purpose of creating a middleware name.`)
        continue
      }
      app.middleware.push({ name, path: file, global: hasSuffix(file, '.global') })
    }
  }

  // Resolve plugins, first extended layers and then base
  app.plugins = []
  for (const config of reversedConfigs) {
    const pluginDir = (config.rootDir === nuxt.options.rootDir ? nuxt.options.dir : config.dir)?.plugins || 'plugins'
    app.plugins.push(...[
      ...(config.plugins || []),
      ...config.srcDir
        ? await resolveFiles(config.srcDir, [
          `${pluginDir}/*{${extGlob}}`,
          `${pluginDir}/*/index{${extGlob}}`,
        ])
        : [],
    ].map(plugin => normalizePlugin(plugin as NuxtPlugin)))
  }

  // Add back plugins not specified in layers or user config
  for (const p of [...nuxt.options.plugins].reverse()) {
    const plugin = normalizePlugin(p)
    if (!app.plugins.some(p => p.src === plugin.src)) {
      app.plugins.unshift(plugin)
    }
  }

  // Normalize and de-duplicate plugins and middleware
  app.middleware = uniqueBy(await resolvePaths(nuxt, [...app.middleware].reverse(), 'path'), 'name').reverse()
  app.plugins = uniqueBy(await resolvePaths(nuxt, app.plugins, 'src'), 'src')

  // Resolve app.config
  app.configs = []
  for (const config of layerConfigs) {
    const appConfigPath = await findPath(resolve(config.srcDir, 'app.config'))
    if (appConfigPath) {
      app.configs.push(appConfigPath)
    }
  }

Review comment (suggestion):
Similarly, the glob pattern for plugins may be malformed due to double braces. Consider using `${pluginDir}/*${extGlob}` instead.
```suggestion
          `${pluginDir}/*${extGlob}`,
          `${pluginDir}/*/index${extGlob}`,
```

Code after:
        : [],
    ])
    for (const file of middlewareFiles) {
      const name = getNameFromPath(file)
      if (!name) {
        // Ignore files like `~/middleware/index.vue` which end up not having a name at all
        logger.warn(`No middleware name could be resolved for \`~/${relative(nuxt.options.srcDir, file)}\`. Bear in mind that \`index\` is ignored for the purpose of creating a middleware name.`)
        continue
      }
      app.middleware.push({ name, path: file, global: hasSuffix(file, '.global') })
    }
  }

  // Resolve plugins, first extended layers and then base
  app.plugins = []
  for (const config of reversedConfigs) {
    const pluginDir = (config.rootDir === nuxt.options.rootDir ? nuxt.options.dir : config.dir)?.plugins || 'plugins'
    app.plugins.push(...[
      ...(config.plugins || []),
      ...config.srcDir
        ? await resolveFiles(config.srcDir, [
          `${pluginDir}/*{${extensionGlob}}`,
          `${pluginDir}/*/index{${extensionGlob}}`,
        ])
        : [],
    ].map(plugin => normalizePlugin(plugin as NuxtPlugin)))
  }

  // Add back plugins not specified in layers or user config
  for (const p of [...nuxt.options.plugins].reverse()) {
    const plugin = normalizePlugin(p)
    if (!app.plugins.some(p => p.src === plugin.src)) {
      app.plugins.unshift(plugin)
    }
  }

  // Normalize and de-duplicate plugins and middleware
  app.middleware = uniqueBy(await resolvePaths(nuxt, [...app.middleware].reverse(), 'path'), 'name').reverse()
  app.plugins = uniqueBy(await resolvePaths(nuxt, app.plugins, 'src'), 'src')

  // Resolve app.config
  app.configs = []
  for (const config of layerConfigs) {
    const appConfigPath = await findPath(resolve(config.srcDir, 'app.config'))
    if (appConfigPath) {
      app.configs.push(appConfigPath)
    }
  }

  // Extend app
  await nuxt.callHook('app:resolve', app)