create-vuetify 0.0.6-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +37 -0
- package/dist/index.mjs +29252 -0
- package/dist/multipart-parser-CbtVsPSq.mjs +175 -0
- package/dist/node-CcjDTqtN.mjs +4007 -0
- package/dist/prompt-CAXcFxNm.mjs +848 -0
- package/package.json +40 -0
- package/src/commands/upgrade.ts +5 -0
- package/src/features/dependencies/package.json +17 -0
- package/src/features/eslint.ts +75 -0
- package/src/features/i18n.ts +108 -0
- package/src/features/index.ts +31 -0
- package/src/features/pinia.ts +84 -0
- package/src/features/router.ts +147 -0
- package/src/features/types.ts +13 -0
- package/src/features/vuetify-nuxt-manual.ts +47 -0
- package/src/features/vuetify-nuxt-module.ts +58 -0
- package/src/index.ts +177 -0
- package/src/prompts.ts +201 -0
- package/src/utils/cli/postinstall/index.ts +1 -0
- package/src/utils/cli/postinstall/pnpm.ts +20 -0
- package/src/utils/cli/preinstall/index.ts +1 -0
- package/src/utils/cli/preinstall/yarn.ts +22 -0
- package/src/utils/convertProjectToJS.ts +98 -0
- package/src/utils/installDependencies.ts +25 -0
- package/src/utils/installFeature.ts +25 -0
- package/test/conflict.test.ts +75 -0
- package/test/index.test.ts +117 -0
- package/tsdown.config.ts +7 -0
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-vuetify",
|
|
3
|
+
"version": "0.0.6-beta.2",
|
|
4
|
+
"description": "Create a new Vuetify project",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"create-vuetify": "./dist/index.mjs"
|
|
8
|
+
},
|
|
9
|
+
"keywords": [],
|
|
10
|
+
"author": "Andrey Yolkin <andreyyolkin@gmail.com>",
|
|
11
|
+
"license": "MIT",
|
|
12
|
+
"devDependencies": {
|
|
13
|
+
"@clack/prompts": "^1.0.0-alpha.8",
|
|
14
|
+
"@types/validate-npm-package-name": "^4.0.2",
|
|
15
|
+
"citty": "^0.1.6",
|
|
16
|
+
"giget": "^2.0.0",
|
|
17
|
+
"kolorist": "^1.8.0",
|
|
18
|
+
"nypm": "^0.6.2",
|
|
19
|
+
"pathe": "^2.0.3",
|
|
20
|
+
"tsdown": "^0.16.6",
|
|
21
|
+
"vitest": "^4.0.16",
|
|
22
|
+
"@vuetify/cli-shared": "0.0.6-beta.2"
|
|
23
|
+
},
|
|
24
|
+
"main": "./dist/index.mjs",
|
|
25
|
+
"module": "./dist/index.mjs",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": "./dist/index.mjs",
|
|
28
|
+
"./package.json": "./package.json"
|
|
29
|
+
},
|
|
30
|
+
"dependencies": {
|
|
31
|
+
"magicast": "^0.5.1",
|
|
32
|
+
"package-manager-detector": "^1.5.0",
|
|
33
|
+
"pkg-types": "^2.3.0",
|
|
34
|
+
"tinyexec": "^1.0.2",
|
|
35
|
+
"validate-npm-package-name": "^7.0.1"
|
|
36
|
+
},
|
|
37
|
+
"scripts": {
|
|
38
|
+
"build": "tsdown"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"dependencies": {
|
|
3
|
+
"pinia": "^3.0.4",
|
|
4
|
+
"eslint": "^9.39.2",
|
|
5
|
+
"eslint-config-vuetify": "^4.3.3",
|
|
6
|
+
"vuetify-nuxt-module": "^0.19.1",
|
|
7
|
+
"@nuxt/eslint": "^1.12.1",
|
|
8
|
+
"@pinia/nuxt": "^0.11.3",
|
|
9
|
+
"@nuxtjs/i18n": "^10.2.1",
|
|
10
|
+
"vue-router": "^4.6.4",
|
|
11
|
+
"vue-i18n": "^11.2.7",
|
|
12
|
+
"unplugin-vue-router": "^0.19.1",
|
|
13
|
+
"vite-plugin-vuetify": "^2.1.2",
|
|
14
|
+
"pathe": "^2.0.3",
|
|
15
|
+
"@vuetify/loader-shared": "^2.1.1"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import type { Feature } from './types'
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { writeFile } from 'node:fs/promises'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { loadFile } from 'magicast'
|
|
6
|
+
import { getDefaultExportOptions } from 'magicast/helpers'
|
|
7
|
+
import rootPkg from './dependencies/package.json' with { type: 'json' }
|
|
8
|
+
|
|
9
|
+
export const eslint: Feature = {
|
|
10
|
+
name: 'eslint',
|
|
11
|
+
apply: async ({ cwd, pkg, isTypescript }) => {
|
|
12
|
+
// Check if Nuxt
|
|
13
|
+
const isNuxt = existsSync(join(cwd, 'nuxt.config.ts'))
|
|
14
|
+
|
|
15
|
+
if (isNuxt) {
|
|
16
|
+
pkg.devDependencies = pkg.devDependencies || {}
|
|
17
|
+
pkg.devDependencies['eslint'] = rootPkg.dependencies.eslint
|
|
18
|
+
pkg.devDependencies['@nuxt/eslint'] = rootPkg.dependencies['@nuxt/eslint']
|
|
19
|
+
pkg.devDependencies['eslint-config-vuetify'] = rootPkg.dependencies['eslint-config-vuetify']
|
|
20
|
+
pkg.scripts = pkg.scripts || {}
|
|
21
|
+
pkg.scripts['lint'] = 'eslint'
|
|
22
|
+
pkg.scripts['lint:fix'] = 'eslint --fix'
|
|
23
|
+
|
|
24
|
+
const configPath = join(cwd, 'nuxt.config.ts')
|
|
25
|
+
const mod = await loadFile(configPath)
|
|
26
|
+
|
|
27
|
+
const options = getDefaultExportOptions(mod)
|
|
28
|
+
if (options) {
|
|
29
|
+
options.modules ||= []
|
|
30
|
+
options.modules.push('@nuxt/eslint')
|
|
31
|
+
|
|
32
|
+
options.eslint = {
|
|
33
|
+
config: {
|
|
34
|
+
import: {
|
|
35
|
+
package: 'eslint-plugin-import-lite',
|
|
36
|
+
},
|
|
37
|
+
},
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
await writeFile(configPath, mod.generate().code)
|
|
42
|
+
await writeFile(join(cwd, 'eslint.config.js'), getNuxtEslintContent(isTypescript))
|
|
43
|
+
} else {
|
|
44
|
+
pkg.devDependencies = pkg.devDependencies || {}
|
|
45
|
+
pkg.devDependencies['eslint'] = rootPkg.dependencies.eslint
|
|
46
|
+
pkg.devDependencies['eslint-config-vuetify'] = rootPkg.dependencies['eslint-config-vuetify']
|
|
47
|
+
pkg.scripts = pkg.scripts || {}
|
|
48
|
+
pkg.scripts['lint'] = 'eslint'
|
|
49
|
+
pkg.scripts['lint:fix'] = 'eslint --fix'
|
|
50
|
+
|
|
51
|
+
await writeFile(join(cwd, 'eslint.config.js'), getVueEslintContent(isTypescript))
|
|
52
|
+
}
|
|
53
|
+
},
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getVueEslintContent (isTypescript: boolean) {
|
|
57
|
+
return `import vuetify from 'eslint-config-vuetify'
|
|
58
|
+
|
|
59
|
+
export default vuetify({
|
|
60
|
+
ts: ${isTypescript},
|
|
61
|
+
})
|
|
62
|
+
`
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function getNuxtEslintContent (isTypescript: boolean) {
|
|
66
|
+
return `import vuetify from 'eslint-config-vuetify'
|
|
67
|
+
import withNuxt from './.nuxt/eslint.config.mjs'
|
|
68
|
+
|
|
69
|
+
export default withNuxt(
|
|
70
|
+
vuetify({
|
|
71
|
+
ts: ${isTypescript},
|
|
72
|
+
}),
|
|
73
|
+
)
|
|
74
|
+
`
|
|
75
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { Feature } from './types'
|
|
2
|
+
import { existsSync, mkdirSync } from 'node:fs'
|
|
3
|
+
import { writeFile } from 'node:fs/promises'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { loadFile } from 'magicast'
|
|
6
|
+
import { getDefaultExportOptions } from 'magicast/helpers'
|
|
7
|
+
import rootPkg from './dependencies/package.json' with { type: 'json' }
|
|
8
|
+
|
|
9
|
+
export const i18n: Feature = {
|
|
10
|
+
name: 'i18n',
|
|
11
|
+
apply: async ({ cwd, pkg, isTypescript }) => {
|
|
12
|
+
const ext = isTypescript ? 'ts' : 'js'
|
|
13
|
+
const isNuxt = existsSync(join(cwd, 'nuxt.config.ts'))
|
|
14
|
+
|
|
15
|
+
if (isNuxt) {
|
|
16
|
+
pkg.dependencies ??= {}
|
|
17
|
+
pkg.dependencies['@nuxtjs/i18n'] = rootPkg.dependencies['@nuxtjs/i18n']
|
|
18
|
+
|
|
19
|
+
const configPath = join(cwd, 'nuxt.config.ts')
|
|
20
|
+
const mod = await loadFile(configPath)
|
|
21
|
+
const options = getDefaultExportOptions(mod)
|
|
22
|
+
|
|
23
|
+
if (options) {
|
|
24
|
+
options.modules ||= []
|
|
25
|
+
options.modules.push('@nuxtjs/i18n')
|
|
26
|
+
|
|
27
|
+
// Add basic configuration
|
|
28
|
+
options.i18n = {
|
|
29
|
+
vueI18n: './i18n.config.ts',
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
await writeFile(configPath, mod.generate().code)
|
|
34
|
+
|
|
35
|
+
// Create i18n.config.ts
|
|
36
|
+
await writeFile(join(cwd, `i18n.config.${ext}`), getNuxtI18nConfig(isTypescript))
|
|
37
|
+
} else {
|
|
38
|
+
pkg.dependencies ??= {}
|
|
39
|
+
pkg.dependencies['vue-i18n'] = rootPkg.dependencies['vue-i18n']
|
|
40
|
+
|
|
41
|
+
// Create i18n plugin file
|
|
42
|
+
if (!existsSync(join(cwd, 'src/plugins'))) {
|
|
43
|
+
mkdirSync(join(cwd, 'src/plugins'), { recursive: true })
|
|
44
|
+
}
|
|
45
|
+
await writeFile(join(cwd, `src/plugins/i18n.${ext}`), getVueI18nContent(isTypescript))
|
|
46
|
+
|
|
47
|
+
// Register in plugins/index.ts
|
|
48
|
+
const pluginsPath = join(cwd, `src/plugins/index.${ext}`)
|
|
49
|
+
if (existsSync(pluginsPath)) {
|
|
50
|
+
const mod = await loadFile(pluginsPath)
|
|
51
|
+
|
|
52
|
+
mod.imports.$prepend({
|
|
53
|
+
from: './i18n',
|
|
54
|
+
imported: 'default',
|
|
55
|
+
local: 'i18n',
|
|
56
|
+
})
|
|
57
|
+
|
|
58
|
+
const registerPlugins = mod.exports.registerPlugins
|
|
59
|
+
if (registerPlugins && registerPlugins.$type === 'function') {
|
|
60
|
+
registerPlugins.$body.push('app.use(i18n)')
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
await writeFile(pluginsPath, mod.generate().code)
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
function getVueI18nContent (_ts: boolean) {
|
|
70
|
+
return `import { createI18n } from 'vue-i18n'
|
|
71
|
+
|
|
72
|
+
const messages = {
|
|
73
|
+
en: {
|
|
74
|
+
message: {
|
|
75
|
+
hello: 'hello world',
|
|
76
|
+
},
|
|
77
|
+
},
|
|
78
|
+
ja: {
|
|
79
|
+
message: {
|
|
80
|
+
hello: 'こんにちは、世界',
|
|
81
|
+
},
|
|
82
|
+
},
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export default createI18n({
|
|
86
|
+
legacy: false,
|
|
87
|
+
locale: 'en',
|
|
88
|
+
fallbackLocale: 'en',
|
|
89
|
+
messages,
|
|
90
|
+
})
|
|
91
|
+
`
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function getNuxtI18nConfig (_ts: boolean) {
|
|
95
|
+
return `export default defineI18nConfig(() => ({
|
|
96
|
+
legacy: false,
|
|
97
|
+
locale: 'en',
|
|
98
|
+
messages: {
|
|
99
|
+
en: {
|
|
100
|
+
welcome: 'Welcome',
|
|
101
|
+
},
|
|
102
|
+
fr: {
|
|
103
|
+
welcome: 'Bienvenue',
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
}))
|
|
107
|
+
`
|
|
108
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { PackageJson } from 'pkg-types'
|
|
2
|
+
import type { Feature } from './types'
|
|
3
|
+
import { eslint } from './eslint'
|
|
4
|
+
import { i18n } from './i18n'
|
|
5
|
+
import { pinia } from './pinia'
|
|
6
|
+
import { fileRouter, router } from './router'
|
|
7
|
+
import { vuetifyNuxtModule } from './vuetify-nuxt-module'
|
|
8
|
+
|
|
9
|
+
export const features: Record<string, Feature> = {
|
|
10
|
+
router,
|
|
11
|
+
'file-router': fileRouter,
|
|
12
|
+
pinia,
|
|
13
|
+
i18n,
|
|
14
|
+
eslint,
|
|
15
|
+
'vuetify-nuxt-module': vuetifyNuxtModule,
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function applyFeatures (
|
|
19
|
+
cwd: string,
|
|
20
|
+
featureNames: string[],
|
|
21
|
+
pkg: PackageJson,
|
|
22
|
+
isTypescript: boolean,
|
|
23
|
+
clientHints?: boolean,
|
|
24
|
+
) {
|
|
25
|
+
for (const name of featureNames) {
|
|
26
|
+
const feature = features[name]
|
|
27
|
+
if (feature) {
|
|
28
|
+
await feature.apply({ cwd, pkg, isTypescript, clientHints })
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import type { Feature } from './types'
|
|
2
|
+
import { existsSync, mkdirSync } from 'node:fs'
|
|
3
|
+
import { writeFile } from 'node:fs/promises'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { loadFile } from 'magicast'
|
|
6
|
+
import { getDefaultExportOptions } from 'magicast/helpers'
|
|
7
|
+
import rootPkg from './dependencies/package.json' with { type: 'json' }
|
|
8
|
+
|
|
9
|
+
export const pinia: Feature = {
|
|
10
|
+
name: 'pinia',
|
|
11
|
+
apply: async ({ cwd, pkg, isTypescript }) => {
|
|
12
|
+
const ext = isTypescript ? 'ts' : 'js'
|
|
13
|
+
|
|
14
|
+
// Check if Nuxt
|
|
15
|
+
const isNuxt = existsSync(join(cwd, 'nuxt.config.ts'))
|
|
16
|
+
|
|
17
|
+
if (isNuxt) {
|
|
18
|
+
pkg.dependencies ??= {}
|
|
19
|
+
pkg.devDependencies ??= {}
|
|
20
|
+
pkg.dependencies['pinia'] = rootPkg.dependencies.pinia
|
|
21
|
+
pkg.devDependencies['@pinia/nuxt'] = rootPkg.dependencies['@pinia/nuxt']
|
|
22
|
+
|
|
23
|
+
// Update nuxt.config.ts
|
|
24
|
+
const configPath = join(cwd, 'nuxt.config.ts')
|
|
25
|
+
const mod = await loadFile(configPath)
|
|
26
|
+
|
|
27
|
+
// Assume defineNuxtConfig structure
|
|
28
|
+
// We need to add to modules array
|
|
29
|
+
// This is hard with magicast if structure varies.
|
|
30
|
+
// But for base template it should be standard.
|
|
31
|
+
const options = getDefaultExportOptions(mod)
|
|
32
|
+
if (options) {
|
|
33
|
+
options.modules ||= []
|
|
34
|
+
options.modules.push('@pinia/nuxt')
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
await writeFile(configPath, mod.generate().code)
|
|
38
|
+
|
|
39
|
+
// Create example store
|
|
40
|
+
const appPath = existsSync(join(cwd, 'app')) ? 'app' : '.'
|
|
41
|
+
if (!existsSync(join(cwd, appPath, 'stores'))) {
|
|
42
|
+
mkdirSync(join(cwd, appPath, 'stores'), { recursive: true })
|
|
43
|
+
}
|
|
44
|
+
await writeFile(join(cwd, appPath, `stores/app.${ext}`), getStoreContent(isTypescript))
|
|
45
|
+
} else {
|
|
46
|
+
pkg.dependencies ??= {}
|
|
47
|
+
pkg.dependencies['pinia'] = rootPkg.dependencies.pinia
|
|
48
|
+
|
|
49
|
+
// Create store file
|
|
50
|
+
if (!existsSync(join(cwd, 'src/stores'))) {
|
|
51
|
+
mkdirSync(join(cwd, 'src/stores'), { recursive: true })
|
|
52
|
+
}
|
|
53
|
+
await writeFile(join(cwd, `src/stores/app.${ext}`), getStoreContent(isTypescript))
|
|
54
|
+
|
|
55
|
+
// Update plugins/index.ts
|
|
56
|
+
const pluginsPath = join(cwd, `src/plugins/index.${ext}`)
|
|
57
|
+
const mod = await loadFile(pluginsPath)
|
|
58
|
+
|
|
59
|
+
mod.imports.$prepend({
|
|
60
|
+
from: 'pinia',
|
|
61
|
+
imported: 'createPinia',
|
|
62
|
+
})
|
|
63
|
+
|
|
64
|
+
const registerPlugins = mod.exports.registerPlugins
|
|
65
|
+
if (registerPlugins && registerPlugins.$type === 'function') {
|
|
66
|
+
registerPlugins.$body.push('app.use(createPinia())')
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
await writeFile(pluginsPath, mod.generate().code)
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function getStoreContent (_ts: boolean) {
|
|
75
|
+
return `// Utilities
|
|
76
|
+
import { defineStore } from 'pinia'
|
|
77
|
+
|
|
78
|
+
export const useAppStore = defineStore('app', {
|
|
79
|
+
state: () => ({
|
|
80
|
+
//
|
|
81
|
+
}),
|
|
82
|
+
})
|
|
83
|
+
`
|
|
84
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { Feature } from './types'
|
|
2
|
+
import { existsSync, mkdirSync } from 'node:fs'
|
|
3
|
+
import { writeFile } from 'node:fs/promises'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { builders, loadFile } from 'magicast'
|
|
6
|
+
import { installFeature } from '../utils/installFeature'
|
|
7
|
+
import rootPkg from './dependencies/package.json' with { type: 'json' }
|
|
8
|
+
|
|
9
|
+
export const router: Feature = {
|
|
10
|
+
name: 'router',
|
|
11
|
+
apply: async ({ cwd, pkg, isTypescript }) => {
|
|
12
|
+
await installFeature('router', cwd)
|
|
13
|
+
|
|
14
|
+
const ext = isTypescript ? 'ts' : 'js'
|
|
15
|
+
pkg.dependencies = pkg.dependencies || {}
|
|
16
|
+
pkg.dependencies['vue-router'] = rootPkg.dependencies['vue-router']
|
|
17
|
+
|
|
18
|
+
// Create router file
|
|
19
|
+
const routerContent = getRouterContent(isTypescript)
|
|
20
|
+
if (!existsSync(join(cwd, 'src/router'))) {
|
|
21
|
+
mkdirSync(join(cwd, 'src/router'), { recursive: true })
|
|
22
|
+
}
|
|
23
|
+
await writeFile(join(cwd, `src/router/index.${ext}`), routerContent)
|
|
24
|
+
|
|
25
|
+
// Update plugins/index.ts
|
|
26
|
+
const pluginsPath = join(cwd, `src/plugins/index.${ext}`)
|
|
27
|
+
const mod = await loadFile(pluginsPath)
|
|
28
|
+
|
|
29
|
+
mod.imports.$prepend({
|
|
30
|
+
from: '../router',
|
|
31
|
+
imported: 'default',
|
|
32
|
+
local: 'router',
|
|
33
|
+
})
|
|
34
|
+
|
|
35
|
+
const registerPlugins = mod.exports.registerPlugins
|
|
36
|
+
if (registerPlugins && registerPlugins.$type === 'function') {
|
|
37
|
+
registerPlugins.$body.push('app.use(router)')
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
await writeFile(pluginsPath, mod.generate().code)
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export const fileRouter: Feature = {
|
|
45
|
+
name: 'file-router',
|
|
46
|
+
apply: async ({ cwd, pkg, isTypescript }) => {
|
|
47
|
+
await installFeature('file-router', cwd)
|
|
48
|
+
|
|
49
|
+
const ext = isTypescript ? 'ts' : 'js'
|
|
50
|
+
pkg.dependencies = pkg.dependencies || {}
|
|
51
|
+
pkg.dependencies['vue-router'] = rootPkg.dependencies['vue-router']
|
|
52
|
+
pkg.devDependencies = pkg.devDependencies || {}
|
|
53
|
+
pkg.devDependencies['unplugin-vue-router'] = rootPkg.dependencies['unplugin-vue-router']
|
|
54
|
+
|
|
55
|
+
// Create router file
|
|
56
|
+
const routerContent = getFileRouterContent(isTypescript)
|
|
57
|
+
if (!existsSync(join(cwd, 'src/router'))) {
|
|
58
|
+
mkdirSync(join(cwd, 'src/router'), { recursive: true })
|
|
59
|
+
}
|
|
60
|
+
await writeFile(join(cwd, `src/router/index.${ext}`), routerContent)
|
|
61
|
+
|
|
62
|
+
// Update plugins/index.ts
|
|
63
|
+
const pluginsPath = join(cwd, `src/plugins/index.${ext}`)
|
|
64
|
+
const mod = await loadFile(pluginsPath)
|
|
65
|
+
|
|
66
|
+
mod.imports.$prepend({
|
|
67
|
+
from: '../router',
|
|
68
|
+
imported: 'default',
|
|
69
|
+
local: 'router',
|
|
70
|
+
})
|
|
71
|
+
|
|
72
|
+
const registerPlugins = mod.exports.registerPlugins
|
|
73
|
+
if (registerPlugins && registerPlugins.$type === 'function') {
|
|
74
|
+
registerPlugins.$body.push('app.use(router)')
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
await writeFile(pluginsPath, mod.generate().code)
|
|
78
|
+
|
|
79
|
+
// Update vite.config.mjs / .mts
|
|
80
|
+
const viteConfigPath = join(cwd, `vite.config.m${ext}`)
|
|
81
|
+
if (existsSync(viteConfigPath)) {
|
|
82
|
+
const viteMod = await loadFile(viteConfigPath)
|
|
83
|
+
|
|
84
|
+
viteMod.imports.$prepend({
|
|
85
|
+
from: 'unplugin-vue-router/vite',
|
|
86
|
+
imported: 'default',
|
|
87
|
+
local: 'VueRouter',
|
|
88
|
+
})
|
|
89
|
+
|
|
90
|
+
// Inject VueRouter() before Vue()
|
|
91
|
+
// This is a bit tricky with magicast if we don't know the structure perfectly.
|
|
92
|
+
// Usually plugins is an array.
|
|
93
|
+
const plugins = viteMod.exports.default.plugins || viteMod.exports.default.$args?.[0]?.plugins
|
|
94
|
+
if (plugins && Array.isArray(plugins)) {
|
|
95
|
+
// We need to insert before 'vue()' or 'Vue()'
|
|
96
|
+
// For simplicity, let's unshift it.
|
|
97
|
+
// Note: unplugin-vue-router MUST be before vue()
|
|
98
|
+
plugins.unshift(builders.raw('VueRouter()'))
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
await writeFile(viteConfigPath, viteMod.generate().code)
|
|
102
|
+
}
|
|
103
|
+
},
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function getRouterContent (ts: boolean) {
|
|
107
|
+
return `/**
|
|
108
|
+
* router/index.${ts ? 'ts' : 'js'}
|
|
109
|
+
*
|
|
110
|
+
* Manual routes for ./src/pages/*.vue
|
|
111
|
+
*/
|
|
112
|
+
|
|
113
|
+
// Composables
|
|
114
|
+
import { createRouter, createWebHistory } from 'vue-router'
|
|
115
|
+
import Index from '@/pages/index.vue'
|
|
116
|
+
|
|
117
|
+
const router = createRouter({
|
|
118
|
+
history: createWebHistory(process.env.BASE_URL),
|
|
119
|
+
routes: [
|
|
120
|
+
{
|
|
121
|
+
path: '/',
|
|
122
|
+
component: Index,
|
|
123
|
+
},
|
|
124
|
+
],
|
|
125
|
+
})
|
|
126
|
+
|
|
127
|
+
export default router
|
|
128
|
+
`
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function getFileRouterContent (ts: boolean) {
|
|
132
|
+
return `/**
|
|
133
|
+
* router/index.${ts ? 'ts' : 'js'}
|
|
134
|
+
*
|
|
135
|
+
* Automatic routes for ./src/pages/*.vue
|
|
136
|
+
*/
|
|
137
|
+
|
|
138
|
+
// Composables
|
|
139
|
+
import { createRouter, createWebHistory } from 'vue-router/auto'
|
|
140
|
+
|
|
141
|
+
const router = createRouter({
|
|
142
|
+
history: createWebHistory(process.env.BASE_URL),
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
export default router
|
|
146
|
+
`
|
|
147
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PackageJson } from 'pkg-types'
|
|
2
|
+
|
|
3
|
+
export interface FeatureContext {
|
|
4
|
+
cwd: string
|
|
5
|
+
pkg: PackageJson
|
|
6
|
+
isTypescript: boolean
|
|
7
|
+
clientHints?: boolean
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface Feature {
|
|
11
|
+
name: string
|
|
12
|
+
apply: (context: FeatureContext) => Promise<void>
|
|
13
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import type { Feature } from './types'
|
|
2
|
+
import { existsSync } from 'node:fs'
|
|
3
|
+
import { writeFile } from 'node:fs/promises'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { builders, loadFile } from 'magicast'
|
|
6
|
+
import { getDefaultExportOptions } from 'magicast/helpers'
|
|
7
|
+
import rootPkg from './dependencies/package.json' with { type: 'json' }
|
|
8
|
+
|
|
9
|
+
export const vuetifyNuxtManual: Feature = {
|
|
10
|
+
name: 'vuetify-nuxt-manual',
|
|
11
|
+
apply: async ({ cwd, pkg }) => {
|
|
12
|
+
// Only applies to Nuxt
|
|
13
|
+
const configPath = join(cwd, 'nuxt.config.ts')
|
|
14
|
+
if (!existsSync(configPath)) {
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pkg.devDependencies = pkg.devDependencies || {}
|
|
19
|
+
pkg.devDependencies['vite-plugin-vuetify'] = rootPkg.dependencies['vite-plugin-vuetify']
|
|
20
|
+
pkg.devDependencies['@vuetify/loader-shared'] = rootPkg.dependencies['@vuetify/loader-shared']
|
|
21
|
+
pkg.devDependencies['pathe'] = rootPkg.dependencies['pathe']
|
|
22
|
+
|
|
23
|
+
const mod = await loadFile(configPath)
|
|
24
|
+
|
|
25
|
+
// Add import { transformAssetUrls } from 'vite-plugin-vuetify'
|
|
26
|
+
mod.imports.$prepend({
|
|
27
|
+
from: 'vite-plugin-vuetify',
|
|
28
|
+
imported: 'transformAssetUrls',
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
const options = getDefaultExportOptions(mod)
|
|
32
|
+
if (options) {
|
|
33
|
+
options.build ||= {}
|
|
34
|
+
options.build.transpile ||= []
|
|
35
|
+
if (!options.build.transpile.includes('vuetify')) {
|
|
36
|
+
options.build.transpile.push('vuetify')
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
options.vite ||= {}
|
|
40
|
+
options.vite.vue ||= {}
|
|
41
|
+
options.vite.vue.template ||= {}
|
|
42
|
+
options.vite.vue.template.transformAssetUrls = builders.raw('transformAssetUrls')
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
await writeFile(configPath, mod.generate().code)
|
|
46
|
+
},
|
|
47
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { Feature } from './types'
|
|
2
|
+
import { existsSync, unlinkSync } from 'node:fs'
|
|
3
|
+
import { writeFile } from 'node:fs/promises'
|
|
4
|
+
import { join } from 'node:path'
|
|
5
|
+
import { loadFile } from 'magicast'
|
|
6
|
+
import { getDefaultExportOptions } from 'magicast/helpers'
|
|
7
|
+
import rootPkg from './dependencies/package.json' with { type: 'json' }
|
|
8
|
+
|
|
9
|
+
export const vuetifyNuxtModule: Feature = {
|
|
10
|
+
name: 'vuetify-nuxt-module',
|
|
11
|
+
apply: async ({ cwd, pkg, clientHints }) => {
|
|
12
|
+
// Only applies to Nuxt
|
|
13
|
+
const isNuxt = existsSync(join(cwd, 'nuxt.config.ts'))
|
|
14
|
+
if (!isNuxt) {
|
|
15
|
+
return
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
pkg.dependencies = pkg.dependencies || {}
|
|
19
|
+
pkg.dependencies['vuetify-nuxt-module'] = rootPkg.dependencies['vuetify-nuxt-module']
|
|
20
|
+
|
|
21
|
+
// Update nuxt.config.ts
|
|
22
|
+
const configPath = join(cwd, 'nuxt.config.ts')
|
|
23
|
+
const mod = await loadFile(configPath)
|
|
24
|
+
|
|
25
|
+
const manualModulePath = join(cwd, 'modules/vuetify.ts')
|
|
26
|
+
if (existsSync(manualModulePath)) {
|
|
27
|
+
unlinkSync(manualModulePath)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const options = getDefaultExportOptions(mod)
|
|
31
|
+
if (options) {
|
|
32
|
+
options.modules ||= []
|
|
33
|
+
options.modules.push('vuetify-nuxt-module')
|
|
34
|
+
|
|
35
|
+
options.vuetify = {
|
|
36
|
+
moduleOptions: {
|
|
37
|
+
/* module options */
|
|
38
|
+
},
|
|
39
|
+
vuetifyOptions: {
|
|
40
|
+
/* vuetify options */
|
|
41
|
+
},
|
|
42
|
+
}
|
|
43
|
+
if (clientHints) {
|
|
44
|
+
options.vuetify.moduleOptions.ssrClientHints = {
|
|
45
|
+
reloadOnFirstRequest: false,
|
|
46
|
+
viewportSize: true,
|
|
47
|
+
prefersColorScheme: true,
|
|
48
|
+
prefersReducedMotion: true,
|
|
49
|
+
prefersColorSchemeOptions: {
|
|
50
|
+
useBrowserThemeOnly: false,
|
|
51
|
+
},
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
await writeFile(configPath, mod.generate().code)
|
|
57
|
+
},
|
|
58
|
+
}
|