Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 6 additions & 9 deletions src/commands/add.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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') {
Expand All @@ -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}`)
},
})
39 changes: 22 additions & 17 deletions src/utils/templates.ts
Original file line number Diff line number Diff line change
@@ -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<string, any>
nuxtOptions: NuxtOptions
}

interface Template {
Expand All @@ -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: `
<script setup lang="ts"></script>

Expand All @@ -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()
Expand All @@ -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: `
<script setup lang="ts"></script>

Expand All @@ -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: `
<script setup lang="ts"></script>

Expand Down
3 changes: 2 additions & 1 deletion test/unit/templates.spec.ts
Original file line number Diff line number Diff line change
@@ -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 = () => {')
}
})
})
Loading