diff --git a/src/commands/add.ts b/src/commands/add.ts index f4a131142..b583829f2 100644 --- a/src/commands/add.ts +++ b/src/commands/add.ts @@ -61,21 +61,18 @@ export default defineCommand({ const config = await kit.loadNuxtConfig({ cwd }) // Resolve template - const res = template({ name, args: ctx.args }) - - // Resolve full path to generated file - const path = resolve(config.srcDir, res.path) + const res = template({ name, args: ctx.args, nuxtOptions: config }) // Ensure not overriding user code - if (!ctx.args.force && existsSync(path)) { + if (!ctx.args.force && existsSync(res.path)) { consola.error( - `File exists: ${path} . Use --force to override or use a different name.`, + `File exists: ${res.path} . Use --force to override or use a different name.`, ) process.exit(1) } // Ensure parent directory exists - const parentDir = dirname(path) + const parentDir = dirname(res.path) if (!existsSync(parentDir)) { consola.info('Creating directory', parentDir) if (templateName === 'page') { @@ -85,7 +82,7 @@ export default defineCommand({ } // Write file - await fsp.writeFile(path, res.contents.trim() + '\n') - consola.info(`🪄 Generated a new ${templateName} in ${path}`) + await fsp.writeFile(res.path, res.contents.trim() + '\n') + consola.info(`🪄 Generated a new ${templateName} in ${res.path}`) }, }) diff --git a/src/utils/templates.ts b/src/utils/templates.ts index 339a3eefc..368b21f16 100644 --- a/src/utils/templates.ts +++ b/src/utils/templates.ts @@ -1,8 +1,11 @@ +import { resolve } from 'pathe' import { camelCase, upperFirst } from 'scule' +import type { NuxtOptions } from '@nuxt/schema' interface TemplateOptions { name: string args: Record + nuxtOptions: NuxtOptions } interface Template { @@ -20,28 +23,30 @@ const httpMethods = [ 'trace', 'patch', ] -const api: Template = ({ name, args }) => ({ - path: `server/api/${name}${applySuffix(args, httpMethods, 'method')}.ts`, - contents: ` +const api: Template = ({ name, args, nuxtOptions }) => { + return { + path: resolve(nuxtOptions.srcDir, nuxtOptions.serverDir, `api/${name}${applySuffix(args, httpMethods, 'method')}.ts`), + contents: ` export default defineEventHandler((event) => { return 'Hello ${name}' }) `, -}) + } +} -const plugin: Template = ({ name, args }) => ({ - path: `plugins/${name}${applySuffix(args, ['client', 'server'], 'mode')}.ts`, +const plugin: Template = ({ name, args, nuxtOptions }) => ({ + path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.plugins, `${name}${applySuffix(args, ['client', 'server'], 'mode')}.ts`), contents: ` export default defineNuxtPlugin((nuxtApp) => {}) `, }) -const component: Template = ({ name, args }) => ({ - path: `components/${name}${applySuffix( +const component: Template = ({ name, args, nuxtOptions }) => ({ + path: resolve(nuxtOptions.srcDir, `components/${name}${applySuffix( args, ['client', 'server'], 'mode', - )}.vue`, + )}.vue`), contents: ` @@ -55,12 +60,12 @@ const component: Template = ({ name, args }) => ({ `, }) -export const composable: Template = ({ name }) => { +export const composable: Template = ({ name, nuxtOptions }) => { const nameWithoutUsePrefix = name.replace(/^use-?/, '') const nameWithUsePrefix = `use${upperFirst(camelCase(nameWithoutUsePrefix))}` return { - path: `composables/${name}.ts`, + path: resolve(nuxtOptions.srcDir, `composables/${name}.ts`), contents: ` export const ${nameWithUsePrefix} = () => { return ref() @@ -69,15 +74,15 @@ export const composable: Template = ({ name }) => { } } -const middleware: Template = ({ name, args }) => ({ - path: `middleware/${name}${applySuffix(args, ['global'])}.ts`, +const middleware: Template = ({ name, args, nuxtOptions }) => ({ + path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.middleware, `${name}${applySuffix(args, ['global'])}.ts`), contents: ` export default defineNuxtRouteMiddleware((to, from) => {}) `, }) -const layout: Template = ({ name }) => ({ - path: `layouts/${name}.vue`, +const layout: Template = ({ name, nuxtOptions }) => ({ + path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.layouts, `${name}.vue`), contents: ` @@ -92,8 +97,8 @@ const layout: Template = ({ name }) => ({ `, }) -const page: Template = ({ name }) => ({ - path: `pages/${name}.vue`, +const page: Template = ({ name, nuxtOptions }) => ({ + path: resolve(nuxtOptions.srcDir, nuxtOptions.dir.pages, `${name}.vue`), contents: ` diff --git a/test/unit/templates.spec.ts b/test/unit/templates.spec.ts index 54f6174f5..d95d9de78 100644 --- a/test/unit/templates.spec.ts +++ b/test/unit/templates.spec.ts @@ -1,10 +1,11 @@ import { describe, expect, it } from 'vitest' +import type { NuxtOptions } from '@nuxt/schema' import { composable } from '../../src/utils/templates' describe('templates', () => { it('composables', () => { for (const name of ['useSomeComposable', 'someComposable', 'use-some-composable', 'use-someComposable', 'some-composable']) { - expect(composable({ name, args: {} }).contents.trim().split('\n')[0]).toBe('export const useSomeComposable = () => {') + expect(composable({ name, args: {}, nuxtOptions: { srcDir: '/src' } as NuxtOptions }).contents.trim().split('\n')[0]).toBe('export const useSomeComposable = () => {') } }) })