Skip to content

Commit 97ded7d

Browse files
committed
refactor(module): edit nuxt.config modules with oxc instead of magicast
1 parent ea82130 commit 97ded7d

13 files changed

Lines changed: 1477 additions & 284 deletions

File tree

‎packages/nuxi/tsdown.config.ts‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,13 @@ import { purgePolyfills } from 'unplugin-purge-polyfills'
66

77
constisAnalysingSize=process.env.BUNDLE_SIZE==='true'
88

9+
constPARSERS=['rolldown','oxc-parser']
10+
911
exportdefaultdefineConfig({
1012
entry: ['src/index.ts','src/cli.ts','src/dev/index.ts'],
1113
shims: true,
1214
fixedExtension: true,
13-
deps: {onlyBundle: false},
15+
deps: {onlyBundle: false,neverBundle: PARSERS},
1416
dts: !isAnalysingSize&&{
1517
oxc: true,
1618
entry: ['src/index.ts'],

‎packages/nuxt-cli/package.json‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
"peerDependencies": {
3636
"@nuxt/schema": "^4.4.6",
3737
"jiti": "^2.7.0",
38+
"oxc-parser": ">=0.56.3",
39+
"rolldown": "^1.0.0-rc.16 || ^1.0.0",
3840
"serve": "^14.0.0"
3941
},
4042
"peerDependenciesMeta": {
@@ -44,6 +46,12 @@
4446
"jiti": {
4547
"optional": true
4648
},
49+
"oxc-parser": {
50+
"optional": true
51+
},
52+
"rolldown": {
53+
"optional": true
54+
},
4755
"serve": {
4856
"optional": true
4957
}
@@ -60,7 +68,6 @@
6068
"fzf": "^0.5.2",
6169
"get-port-please": "^3.2.0",
6270
"giget": "^3.3.0",
63-
"magicast": "^0.5.3",
6471
"nypm": "^0.6.8",
6572
"obug": "^2.1.1",
6673
"ohash": "^2.0.11",
@@ -92,6 +99,7 @@
9299
"jiti": "^2.7.0",
93100
"nitro": "^3.0.1-alpha.2",
94101
"nitropack": "^2.13.4",
102+
"rolldown": "^1.0.0-rc.16",
95103
"rollup": "^4.62.2",
96104
"rollup-plugin-visualizer": "^7.0.1",
97105
"tsdown": "^0.22.7",

‎packages/nuxt-cli/src/commands/module/add.ts‎

Lines changed: 22 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
importtype{PackageManager}from'nypm'
22
importtype{PackageJson}from'pkg-types'
33

4+
importtype{ConfigEntries}from'../../utils/config'
45
importtype{RegistryMeta}from'../../utils/registry'
56
importtype{NuxtModule}from'./_utils'
67
importprocessfrom'node:process'
@@ -15,7 +16,7 @@ import { joinURL } from 'ufo'
1516
import{satisfies}from'verkit'
1617

1718
import{runCommandDefasrunCommand}from'../../run-command'
18-
import{updateConfig}from'../../utils/config'
19+
import{addNuxtConfigEntries,createNuxtConfig,readNuxtConfig}from'../../utils/config'
1920
import{fetchJson}from'../../utils/fetch'
2021
import{createInstallLog,resolvePackageManagerDescriptor,runInstall,takeUnreportedIgnoredBuilds}from'../../utils/install'
2122
import{logger}from'../../utils/logger'
@@ -231,45 +232,33 @@ async function addModules(modules: ResolvedModule[], { skipInstall = false, skip
231232

232233
// Update nuxt.config.ts
233234
if(!skipConfig){
234-
awaitupdateConfig({
235-
cwd,
236-
configFile: 'nuxt.config',
237-
asynconCreate(){
235+
try{
236+
letconfig=awaitreadNuxtConfig(cwd)
237+
if(!config){
238238
logger.info(`Creating ${colors.cyan('nuxt.config.ts')}`)
239+
config=awaitcreateNuxtConfig(cwd,getDefaultNuxtConfig())
240+
}
239241

240-
returngetDefaultNuxtConfig()
241-
},
242-
asynconUpdate(config){
243-
if(!config.modules&&modules.some(module=>!module.isLayer)){
244-
config.modules=[]
245-
}
246-
247-
for(constresolvedofmodules){
248-
constkey=resolved.isLayer ? 'extends' : 'modules'
249-
if(resolved.isLayer&&!Array.isArray(config.extends)){
250-
// `extends` also accepts a single layer as a string
251-
config.extends=config.extends ? [config.extends] : []
252-
}
253-
254-
consttarget: unknown[]=resolved.isLayer ? config.extends : config.modules
242+
consttoAdd: ConfigEntries={}
243+
for(constresolvedofmodules){
244+
constkey=resolved.isLayer ? 'extends' : 'modules'
245+
if(config[key].includes(resolved.specifier)){
246+
logger.info(`${colors.cyan(resolved.specifier)} is already in the ${colors.cyan(key)}`)
255247

256-
if(target.includes(resolved.specifier)){
257-
logger.info(`${colors.cyan(resolved.specifier)} is already in the ${colors.cyan(key)}`)
248+
continue
249+
}
258250

259-
continue
260-
}
251+
logger.info(`Adding ${colors.cyan(resolved.specifier)} to the ${colors.cyan(key)}`)
261252

262-
logger.info(`Adding ${colors.cyan(resolved.specifier)} to the ${colors.cyan(key)}`)
253+
toAdd[key]=[...toAdd[key]??[],resolved.specifier]
254+
}
263255

264-
target.push(resolved.specifier)
265-
}
266-
},
267-
}).catch((error)=>{
268-
logger.error(`Failed to update ${colors.cyan('nuxt.config')}: ${error.message}`)
256+
awaitaddNuxtConfigEntries(config,toAdd)
257+
}
258+
catch(error){
259+
logger.error(`Failed to update ${colors.cyan('nuxt.config')}: ${(errorasError).message}`)
269260
logger.error(`Please manually add ${colors.cyan(modules.map(module=>module.specifier).join(', '))} to ${colors.cyan('nuxt.config.ts')}`)
270-
271-
returnnull
272-
})
261+
}
273262
}
274263

275264
returntrue

‎packages/nuxt-cli/src/commands/module/remove.ts‎

Lines changed: 40 additions & 81 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
importtype{PackageJson}from'pkg-types'
22

3+
importtype{ConfigEntries}from'../../utils/config'
34
importtype{NuxtModule}from'./_utils'
45

56
importprocessfrom'node:process'
@@ -12,7 +13,8 @@ import colors from 'picocolors'
1213
import{readPackageJSON}from'pkg-types'
1314

1415
import{runCommandDefasrunCommand}from'../../run-command'
15-
import{updateConfig}from'../../utils/config'
16+
import{readNuxtConfig,removeNuxtConfigEntries}from'../../utils/config'
17+
import{CONFIG_KEYS}from'../../utils/config-parse'
1618
import{logger}from'../../utils/logger'
1719
import{logNetworkError}from'../../utils/network'
1820
import{relativeToProcess}from'../../utils/paths'
@@ -98,88 +100,55 @@ async function removeModules(modules: string[], { skipInstall = false, skipConfi
98100
constdependencies=getProjectDependencies(projectPkg)
99101

100102
if(!skipConfig){
101-
letconfigMissing=false
102-
letcancelled=false
103-
104-
awaitupdateConfig({
105-
cwd,
106-
configFile: 'nuxt.config',
107-
onCreate(){
108-
configMissing=true
109-
returnfalse
110-
},
111-
asynconUpdate(config){
112-
constarrays=([['modules',config.modules],['extends',config.extends]]asconst)
113-
.filter(([,value])=>Array.isArray(value))asArray<[string,unknown[]]>
114-
115-
if(arrays.length===0){
116-
return
117-
}
103+
constconfig=awaitreadNuxtConfig(cwd).catch((error)=>{
104+
logger.error(`Failed to read ${colors.cyan('nuxt.config')}: ${(errorasError).message}`)
105+
returnundefined
106+
})
118107

119-
constpresent: string[]=[]
120-
for(const[,items]ofarrays){
121-
for(constitemofitems){
122-
constname=readModuleName(item)
123-
if(name){
124-
present.push(name)
125-
}
126-
}
127-
}
108+
constpresent=config ? CONFIG_KEYS.flatMap(key=>config[key]) : []
128109

129-
lettoRemove: Set<string>
130-
if(modules.length===0){
131-
if(present.length===0){
132-
return
133-
}
110+
lettoRemove=newSet(modules)
111+
if(config&&modules.length===0&&present.length>0){
112+
constpicked=awaitmultiselect({
113+
message: 'Select modules to remove:',
114+
options: present.map(m=>({value: m,label: m})),
115+
required: true,
116+
})
134117

135-
constpicked=awaitmultiselect({
136-
message: 'Select modules to remove:',
137-
options: present.map(m=>({value: m,label: m})),
138-
required: true,
139-
})
118+
if(isCancel(picked)){
119+
cancel('No modules selected.')
120+
returnfalse
121+
}
140122

141-
if(isCancel(picked)){
142-
cancelled=true
143-
return
144-
}
123+
toRemove=newSet(pickedasstring[])
124+
}
145125

146-
toRemove=newSet(pickedasstring[])
147-
}
148-
else{
149-
toRemove=newSet(modules)
126+
if(config){
127+
constdoomed: ConfigEntries={}
128+
for(constkeyofCONFIG_KEYS){
129+
// A package may be configured through a subpath (`maz-ui/nuxt`) while the
130+
// user asks to remove the package itself.
131+
constnames=config[key].filter(name=>toRemove.has(name)||toRemove.has(basePackageName(name)))
132+
if(!names.length){
133+
continue
150134
}
151-
152-
for(const[key,items]ofarrays){
153-
for(leti=items.length-1;i>=0;i--){
154-
constname=readModuleName(items[i])
155-
// A package may be configured through a subpath (`maz-ui/nuxt`) while the
156-
// user asks to remove the package itself.
157-
if(!name||!(toRemove.has(name)||toRemove.has(basePackageName(name)))){
158-
continue
159-
}
160-
logger.info(`Removing ${colors.cyan(name)} from the ${colors.cyan(key)}`)
161-
items.splice(i,1)
162-
removedFromConfig.push(name)
163-
}
135+
for(constnameofnames){
136+
logger.info(`Removing ${colors.cyan(name)} from the ${colors.cyan(key)}`)
164137
}
165-
},
166-
}).catch((error)=>{
167-
if(configMissing){
168-
return
138+
doomed[key]=names
139+
removedFromConfig.push(...names)
169140
}
170-
logger.error(`Failed to update ${colors.cyan('nuxt.config')}: ${error.message}`)
171-
logger.error(`Please manually remove ${colors.cyan(modules.join(', ')||'the relevant modules')} from ${colors.cyan('nuxt.config.ts')}`)
172-
})
173141

174-
if(cancelled){
175-
cancel('No modules selected.')
176-
returnfalse
142+
awaitremoveNuxtConfigEntries(config,doomed).catch((error)=>{
143+
logger.error(`Failed to update ${colors.cyan('nuxt.config')}: ${(errorasError).message}`)
144+
logger.error(`Please manually remove ${colors.cyan(modules.join(', ')||'the relevant modules')} from ${colors.cyan('nuxt.config.ts')}`)
145+
})
177146
}
178147

179148
if(modules.length===0&&removedFromConfig.length===0){
180-
cancel(configMissing
181-
? `No ${colors.cyan('nuxt.config')} found in ${colors.cyan(relativeToProcess(cwd))}.`
182-
: `No modules configured in ${colors.cyan('nuxt.config')}.`)
149+
cancel(config
150+
? `No modules configured in ${colors.cyan('nuxt.config')}.`
151+
: `No ${colors.cyan('nuxt.config')} found in ${colors.cyan(relativeToProcess(cwd))}.`)
183152
returnfalse
184153
}
185154
}
@@ -263,16 +232,6 @@ async function removeModules(modules: string[], { skipInstall = false, skipConfi
263232
returntrue
264233
}
265234

266-
functionreadModuleName(item: unknown): string|null{
267-
if(typeofitem==='string'){
268-
returnitem
269-
}
270-
if(Array.isArray(item)&&typeofitem[0]==='string'){
271-
returnitem[0]
272-
}
273-
returnnull
274-
}
275-
276235
functionresolveModuleName(input: string,modulesDB: NuxtModule[],installed: Set<string>): string{
277236
if(installed.has(input)){
278237
returninput

0 commit comments

Comments
 (0)