From bdf0d55fff4d1dd10b1430c8d2b6a189aa5259b1 Mon Sep 17 00:00:00 2001 From: kazuya kawaguchi Date: Sun, 27 Nov 2022 02:50:13 +0900 Subject: [PATCH] fix: API type completion (#1682) --- package.json | 9 +++++++-- src/alias.ts | 40 ++++++++++-------------------------- src/dirs.ts | 47 ++++++++++++++++++++++++++++++++++++++----- src/module.ts | 25 +++++++++++++---------- src/runtime/plugin.ts | 11 ++++++++++ 5 files changed, 85 insertions(+), 47 deletions(-) diff --git a/package.json b/package.json index 6704a27e7..6bf2d5e05 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,13 @@ "exports": { ".": { "import": "./dist/module.mjs", - "require": "./dist/module.cjs" - } + "require": "./dist/module.cjs", + "types": "./dist/types.d.ts" + }, + "./package.json": "./package.json" + }, + "imports": { + "#i18n": "./dist/runtime/composables.mjs" }, "main": "./dist/module.cjs", "module": "./dist/module.mjs", diff --git a/src/alias.ts b/src/alias.ts index dac8c9ed5..9e4218b57 100644 --- a/src/alias.ts +++ b/src/alias.ts @@ -1,11 +1,11 @@ import createDebug from 'debug' import { resolvePath } from '@nuxt/kit' -import { resolveVueI18nPkgPath, pkgModulesDir } from './dirs' +import { resolveVueI18nPkgPath, pkgModulesDir, getPackageManagerType } from './dirs' import { resolve, parse as parsePath } from 'pathe' -import { resolveLockfile } from 'pkg-types' import { VUE_I18N_PKG, VUE_I18N_BRIDGE_PKG, VUE_ROUTER_BRIDGE_PKG, VUE_I18N_ROUTING_PKG } from './constants' import type { Nuxt } from '@nuxt/schema' +import type { PackageManager } from './dirs' const debug = createDebug('@nuxtjs/i18n:alias') @@ -39,60 +39,42 @@ export async function setupAlias(nuxt: Nuxt) { debug('vue-i18n-routing alias', nuxt.options.alias[VUE_I18N_ROUTING_PKG]) } -const PackageManagerLockFiles = { - 'npm-shrinkwrap.json': 'npm-legacy', - 'package-lock.json': 'npm', - 'yarn.lock': 'yarn', - 'pnpm-lock.yaml': 'pnpm' -} as const - -type LockFile = keyof typeof PackageManagerLockFiles -type _PackageManager = typeof PackageManagerLockFiles[LockFile] -type PackageManager = _PackageManager | 'unknown' - -async function getPackageManagerType(): Promise { - try { - const parsed = parsePath(await resolveLockfile()) - const lockfile = `${parsed.name}${parsed.ext}` as LockFile - debug('getPackageManagerType: lockfile', lockfile) - if (lockfile == null) { - return 'unknown' - } - const type = PackageManagerLockFiles[lockfile] - return type == null ? 'unknown' : type - } catch (e) { - debug('getPackageManagerType: resolveLockfile error', e) - throw e - } -} - async function resolveVueI18nAlias(nuxt: Nuxt) { return resolve(await resolveVueI18nPkgPath(), nuxt.options.dev ? 'dist/vue-i18n.mjs' : 'dist/vue-i18n.runtime.mjs') } async function resolveVueI18nBridgeAlias(pkgModuleDir: string, pkgMgr: PackageManager) { if (pkgMgr === 'npm') { + debug( + 'resolveVueI18nBridgeAlias on npm', + `${VUE_I18N_ROUTING_PKG}/node_modules/${VUE_I18N_BRIDGE_PKG}/lib/index.mjs` + ) return resolve(pkgModuleDir, `${VUE_I18N_ROUTING_PKG}/node_modules/${VUE_I18N_BRIDGE_PKG}/lib/index.mjs`) } else { const parsed = parsePath(await resolvePath(VUE_I18N_BRIDGE_PKG)) + debug(`resolveVueI18nBridgeAlias on ${pkgMgr}`, parsed) return `${parsed.dir}/${parsed.name}.mjs` } } async function resolveVueRouterBridgeAlias(pkgModuleDir: string, pkgMgr: PackageManager) { if (pkgMgr === 'npm') { + debug('resolveVueRouterBridgeAlias on npm', `${VUE_ROUTER_BRIDGE_PKG}/lib/index.mjs`) return resolve(pkgModuleDir, `${VUE_ROUTER_BRIDGE_PKG}/lib/index.mjs`) } else { const parsed = parsePath(await resolvePath(VUE_ROUTER_BRIDGE_PKG)) + debug(`resolveVueRouterBridgeAlias on ${pkgMgr}`, parsed) return `${parsed.dir}/${parsed.name}.mjs` } } async function resolveVueI18nRoutingAlias(pkgModuleDir: string, pkgMgr: PackageManager) { if (pkgMgr === 'npm') { + debug('resolveVueI18nRoutingAlias on npm', `${VUE_I18N_ROUTING_PKG}/dist/vue-i18n-routing.mjs`) return resolve(pkgModuleDir, `${VUE_I18N_ROUTING_PKG}/dist/vue-i18n-routing.mjs`) } else if (pkgMgr === 'pnpm' || pkgMgr === 'yarn') { const parsed = parsePath(await resolvePath(VUE_I18N_ROUTING_PKG)) + debug(`resolveVueI18nRoutingAlias on ${pkgMgr}`, parsed) return `${parsed.dir}/dist/vue-i18n-routing.mjs` } else { return await resolvePath(VUE_I18N_ROUTING_PKG) diff --git a/src/dirs.ts b/src/dirs.ts index f4d6410a5..46c39c9fe 100644 --- a/src/dirs.ts +++ b/src/dirs.ts @@ -1,7 +1,9 @@ import createDebug from 'debug' import { fileURLToPath } from 'node:url' -import { dirname, resolve } from 'pathe' +import { dirname, resolve, parse as parsePath } from 'pathe' import { resolvePath } from '@nuxt/kit' +import { resolveLockfile } from 'pkg-types' +import { VUE_I18N_ROUTING_PKG } from './constants' const debug = createDebug('@nuxtjs/i18n:dirs') @@ -10,19 +12,54 @@ export const runtimeDir = fileURLToPath(new URL('./runtime', import.meta.url)) const pkgDir = resolve(distDir, '..') export const pkgModulesDir = resolve(pkgDir, './node_modules') +const PackageManagerLockFiles = { + 'npm-shrinkwrap.json': 'npm-legacy', + 'package-lock.json': 'npm', + 'yarn.lock': 'yarn', + 'pnpm-lock.yaml': 'pnpm' +} as const + +type LockFile = keyof typeof PackageManagerLockFiles +type _PackageManager = typeof PackageManagerLockFiles[LockFile] +export type PackageManager = _PackageManager | 'unknown' + debug('distDir', distDir) debug('runtimeDir', runtimeDir) debug('pkgDir', pkgDir) debug('pkgModulesDir', pkgModulesDir) +export async function getPackageManagerType(): Promise { + try { + const parsed = parsePath(await resolveLockfile()) + const lockfile = `${parsed.name}${parsed.ext}` as LockFile + debug('getPackageManagerType: lockfile', lockfile) + if (lockfile == null) { + return 'unknown' + } + const type = PackageManagerLockFiles[lockfile] + return type == null ? 'unknown' : type + } catch (e) { + debug('getPackageManagerType: resolveLockfile error', e) + throw e + } +} + export async function resolveVueI18nPkgPath() { const p = await resolvePath('vue-i18n') debug('vue-i18n resolved path', p) return resolve(p, '../..') } -export async function resolveVueI18nRoutingPkgPath() { - const p = await resolvePath('vue-i18n-routing') - debug('vue-i18n-routing resolved path', p) - return resolve(p, '..') +export async function resolveVueI18nRoutingDtsPath(id: string) { + const pkgMgr = await getPackageManagerType() + if (pkgMgr === 'npm') { + debug('resolveVueI18nRoutingDtsPath on npm', `${VUE_I18N_ROUTING_PKG}/dist/${id}`) + return resolve(pkgModulesDir, `${VUE_I18N_ROUTING_PKG}/dist/${id}`) + } else if (pkgMgr === 'pnpm' || pkgMgr === 'yarn') { + const parsed = parsePath(await resolvePath(VUE_I18N_ROUTING_PKG)) + debug(`resolveVueI18nRoutingDtsPath on ${pkgMgr}`, parsed) + return `${parsed.dir}/${id}` + } else { + throw new Error(`Not supported package manager`) + } } diff --git a/src/module.ts b/src/module.ts index b0ac10f4d..36d2c4e30 100644 --- a/src/module.ts +++ b/src/module.ts @@ -9,7 +9,7 @@ import { extendBundler } from './bundler' import { generateLoaderOptions } from './gen' import { NUXT_I18N_MODULE_ID, DEFAULT_OPTIONS } from './constants' import { formatMessage, getNormalizedLocales, resolveLocales } from './utils' -import { distDir, runtimeDir, resolveVueI18nPkgPath, resolveVueI18nRoutingPkgPath } from './dirs' +import { distDir, runtimeDir, resolveVueI18nPkgPath, resolveVueI18nRoutingDtsPath } from './dirs' import type { NuxtI18nOptions } from './types' import type { DefineLocaleMessage, LocaleMessages } from 'vue-i18n' @@ -116,12 +116,7 @@ export default defineNuxtModule({ addPlugin(resolve(runtimeDir, 'plugin')) // for compoables - const i18nPath = addTemplate({ - filename: 'i18n.mjs', - src: resolve(distDir, 'runtime/composables.mjs') - }) - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - nuxt.options.alias['#i18n'] = i18nPath.dst! + nuxt.options.alias['#i18n'] = resolve(distDir, 'runtime/composables.mjs') nuxt.options.build.transpile.push('#i18n') // TODO: We don't want to resolve the following as a template, @@ -204,8 +199,8 @@ export default defineNuxtModule({ : false } const nuxtAppExtendFilename = 'types/i18n-nuxt-app.d.ts' - const vueI18nDir = await resolveVueI18nPkgPath() - const vueI18nRoutingDir = await resolveVueI18nRoutingPkgPath() + const vueI18nRoutingVueI18nDtsPath = await resolveVueI18nRoutingDtsPath('vue-i18n') + const vueI18nRoutingMixinDtsPath = await resolveVueI18nRoutingDtsPath('vue') addTemplate({ filename: nuxtAppExtendFilename, getContents: () => { @@ -213,13 +208,20 @@ export default defineNuxtModule({ `import type { ${isLegacyMode() ? 'VueI18n' : 'ExportedGlobalComposer'} } from 'vue-i18n'`, // prettier-ignore `import type { NuxtI18nRoutingCustomProperties } from '${resolve(runtimeDir, 'types')}'`, - `import type { I18nRoutingCustomProperties } from 'vue-i18n-routing/dist/vue-i18n'`, - isLegacyMode() ? `import '${resolve(vueI18nRoutingDir, 'dist/vue')}'` : '', + `import type { I18nRoutingCustomProperties } from '${vueI18nRoutingVueI18nDtsPath}'`, + // import legacy mixins + isLegacyMode() ? `import '${vueI18nRoutingMixinDtsPath}'` : '', `declare module '#app' {`, ' interface NuxtApp {', // prettier-ignore ` $i18n: ${isLegacyMode() ? 'VueI18n' : 'ExportedGlobalComposer'} & NuxtI18nRoutingCustomProperties & I18nRoutingCustomProperties`, ' }', + '}', + `declare module 'nuxt/dist/app/nuxt' {`, + ' interface NuxtApp {', + // prettier-ignore + ` $i18n: ${isLegacyMode() ? 'VueI18n' : 'ExportedGlobalComposer'} & NuxtI18nRoutingCustomProperties & I18nRoutingCustomProperties`, + ' }', '}' ].join('\n') } @@ -244,6 +246,7 @@ export default defineNuxtModule({ * auto imports */ + const vueI18nDir = await resolveVueI18nPkgPath() await addImports([ { name: 'useI18n', from: resolve(vueI18nDir, 'dist/vue-i18n') }, ...[ diff --git a/src/runtime/plugin.ts b/src/runtime/plugin.ts index df53d1c52..a67983887 100644 --- a/src/runtime/plugin.ts +++ b/src/runtime/plugin.ts @@ -401,3 +401,14 @@ declare module '#app' { $switchLocalePath: (...args: Parameters) => ReturnType } } + +// @ts-ignore +declare module 'nuxt/dist/app/nuxt' { + interface NuxtApp { + $getRouteBaseName: (...args: Parameters) => ReturnType + $localePath: (...args: Parameters) => ReturnType + $localeRoute: (...args: Parameters) => ReturnType + $localeHead: (...args: Parameters) => ReturnType + $switchLocalePath: (...args: Parameters) => ReturnType + } +}