Skip to content

Commit 8928d35

Browse files
atinuxdanielroe
andauthored
fix(add): add better error fallbacks (#1177)
Co-authored-by: Daniel Roe <daniel@roe.dev>
1 parent 562abd5 commit 8928d35

File tree

4 files changed

+422
-5
lines changed

4 files changed

+422
-5
lines changed

packages/nuxi/src/commands/_utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import type { commands } from '.'
33
// Inlined list of nuxi commands to avoid including `commands` in bundle if possible
44
export const nuxiCommands = [
55
'add',
6+
'add-template',
67
'analyze',
78
'build',
89
'cleanup',

packages/nuxi/src/commands/module/add.ts

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -84,10 +84,15 @@ export default defineCommand({
8484
}
8585
}
8686

87-
const maybeResolvedModules = await Promise.all(modules.map(moduleName => resolveModule(moduleName, cwd)))
88-
const resolvedModules = maybeResolvedModules.filter((x: ModuleResolution): x is ResolvedModule => !!x)
87+
const resolvedModules: ResolvedModule[] = []
88+
for (const moduleName of modules) {
89+
const resolvedModule = await resolveModule(moduleName, cwd)
90+
if (resolvedModule) {
91+
resolvedModules.push(resolvedModule)
92+
}
93+
}
8994

90-
if (!resolvedModules.length) {
95+
if (resolvedModules.length === 0) {
9196
cancel('No modules to add.')
9297
process.exit(1)
9398
}
@@ -313,7 +318,11 @@ async function resolveModule(moduleName: string, cwd: string): Promise<ModuleRes
313318
}
314319

315320
// TODO: spinner
316-
const pkgDetails = await $fetch(joinURL(meta.registry, `${pkgName}`), { headers })
321+
const pkgDetails = await $fetch(joinURL(meta.registry, `${pkgName}`), { headers }).catch(() => null)
322+
if (!pkgDetails) {
323+
logger.error(`Failed to fetch package details for ${colors.cyan(pkgName)}.`)
324+
return false
325+
}
317326

318327
// fully resolve the version
319328
if (pkgDetails['dist-tags']?.[version]) {
@@ -323,7 +332,7 @@ async function resolveModule(moduleName: string, cwd: string): Promise<ModuleRes
323332
version = Object.keys(pkgDetails.versions)?.findLast(v => satisfies(v, version)) || version
324333
}
325334

326-
const pkg = pkgDetails.versions[version!]
335+
const pkg = pkgDetails.versions[version!] || {}
327336

328337
const pkgDependencies = Object.assign(
329338
pkg.dependencies || {},
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
import { existsSync } from 'node:fs'
2+
import { rm } from 'node:fs/promises'
3+
import { join } from 'node:path'
4+
import { fileURLToPath } from 'node:url'
5+
import { x } from 'tinyexec'
6+
import { describe, expect, it } from 'vitest'
7+
8+
const fixtureDir = fileURLToPath(new URL('../../../../../playground', import.meta.url))
9+
const nuxi = fileURLToPath(new URL('../../../bin/nuxi.mjs', import.meta.url))
10+
11+
describe('nuxt add backwards compatibility', () => {
12+
it('should create middleware file using deprecated syntax', async () => {
13+
const file = join(fixtureDir, 'app/middleware/auth.ts')
14+
await rm(file, { force: true })
15+
16+
const res = await x(nuxi, ['add', 'middleware', 'auth'], {
17+
nodeOptions: { stdio: 'pipe', cwd: fixtureDir },
18+
})
19+
20+
// Should show deprecation warning (check both stdout and stderr)
21+
const output = res.stdout + res.stderr
22+
expect(output).toContain('Deprecated')
23+
expect(output).toContain('add-template')
24+
25+
// Should still create the file
26+
expect(existsSync(file)).toBe(true)
27+
28+
await rm(file, { force: true })
29+
})
30+
31+
it('should create page file using deprecated syntax', async () => {
32+
const file = join(fixtureDir, 'app/pages/test-page.vue')
33+
await rm(file, { force: true })
34+
35+
const res = await x(nuxi, ['add', 'page', 'test-page'], {
36+
nodeOptions: { stdio: 'pipe', cwd: fixtureDir },
37+
})
38+
39+
const output = res.stdout + res.stderr
40+
expect(output).toContain('Deprecated')
41+
expect(existsSync(file)).toBe(true)
42+
43+
await rm(file, { force: true })
44+
})
45+
46+
it('should create composable file using deprecated syntax', async () => {
47+
const file = join(fixtureDir, 'app/composables/useTestComposable.ts')
48+
await rm(file, { force: true })
49+
50+
const res = await x(nuxi, ['add', 'composable', 'useTestComposable'], {
51+
nodeOptions: { stdio: 'pipe', cwd: fixtureDir },
52+
})
53+
54+
const output = res.stdout + res.stderr
55+
expect(output).toContain('Deprecated')
56+
expect(existsSync(file)).toBe(true)
57+
58+
await rm(file, { force: true })
59+
})
60+
})

0 commit comments

Comments
 (0)