1 | const fs = require('fs')
|
2 | const cloneDeep = require('lodash.clonedeep')
|
3 | const { getRcPath } = require('./util/rcPath')
|
4 | const { exit } = require('@vue/cli-shared-utils/lib/exit')
|
5 | const { error } = require('@vue/cli-shared-utils/lib/logger')
|
6 | const { createSchema, validate } = require('@vue/cli-shared-utils/lib/validate')
|
7 |
|
8 | const rcPath = exports.rcPath = getRcPath('.vuerc')
|
9 |
|
10 | const presetSchema = createSchema(joi => joi.object().keys({
|
11 | vueVersion: joi.string().only(['2', '3']),
|
12 | bare: joi.boolean(),
|
13 | useConfigFiles: joi.boolean(),
|
14 |
|
15 | router: joi.boolean(),
|
16 | routerHistoryMode: joi.boolean(),
|
17 | vuex: joi.boolean(),
|
18 | cssPreprocessor: joi.string().only(['sass', 'dart-sass', 'node-sass', 'less', 'stylus']),
|
19 | plugins: joi.object().required(),
|
20 | configs: joi.object()
|
21 | }))
|
22 |
|
23 | const schema = createSchema(joi => joi.object().keys({
|
24 | latestVersion: joi.string().regex(/^\d+\.\d+\.\d+(-(alpha|beta|rc)\.\d+)?$/),
|
25 | lastChecked: joi.date().timestamp(),
|
26 | packageManager: joi.string().only(['yarn', 'npm', 'pnpm']),
|
27 | useTaobaoRegistry: joi.boolean(),
|
28 | presets: joi.object().pattern(/^/, presetSchema)
|
29 | }))
|
30 |
|
31 | exports.validatePreset = preset => validate(preset, presetSchema, msg => {
|
32 | error(`invalid preset options: ${msg}`)
|
33 | })
|
34 |
|
35 | exports.defaultPreset = {
|
36 | useConfigFiles: false,
|
37 | cssPreprocessor: undefined,
|
38 | plugins: {
|
39 | '@vue/cli-plugin-babel': {},
|
40 | '@vue/cli-plugin-eslint': {
|
41 | config: 'base',
|
42 | lintOn: ['save']
|
43 | }
|
44 | }
|
45 | }
|
46 |
|
47 | exports.defaults = {
|
48 | lastChecked: undefined,
|
49 | latestVersion: undefined,
|
50 |
|
51 | packageManager: undefined,
|
52 | useTaobaoRegistry: undefined,
|
53 | presets: {
|
54 | 'default': Object.assign({ vueVersion: '2' }, exports.defaultPreset),
|
55 | '__default_vue_3__': Object.assign({ vueVersion: '3' }, exports.defaultPreset)
|
56 | }
|
57 | }
|
58 |
|
59 | let cachedOptions
|
60 |
|
61 | exports.loadOptions = () => {
|
62 | if (cachedOptions) {
|
63 | return cachedOptions
|
64 | }
|
65 | if (fs.existsSync(rcPath)) {
|
66 | try {
|
67 | cachedOptions = JSON.parse(fs.readFileSync(rcPath, 'utf-8'))
|
68 | } catch (e) {
|
69 | error(
|
70 | `Error loading saved preferences: ` +
|
71 | `~/.vuerc may be corrupted or have syntax errors. ` +
|
72 | `Please fix/delete it and re-run vue-cli in manual mode.\n` +
|
73 | `(${e.message})`
|
74 | )
|
75 | exit(1)
|
76 | }
|
77 | validate(cachedOptions, schema, () => {
|
78 | error(
|
79 | `~/.vuerc may be outdated. ` +
|
80 | `Please delete it and re-run vue-cli in manual mode.`
|
81 | )
|
82 | })
|
83 | return cachedOptions
|
84 | } else {
|
85 | return {}
|
86 | }
|
87 | }
|
88 |
|
89 | exports.saveOptions = toSave => {
|
90 | const options = Object.assign(cloneDeep(exports.loadOptions()), toSave)
|
91 | for (const key in options) {
|
92 | if (!(key in exports.defaults)) {
|
93 | delete options[key]
|
94 | }
|
95 | }
|
96 | cachedOptions = options
|
97 | try {
|
98 | fs.writeFileSync(rcPath, JSON.stringify(options, null, 2))
|
99 | return true
|
100 | } catch (e) {
|
101 | error(
|
102 | `Error saving preferences: ` +
|
103 | `make sure you have write access to ${rcPath}.\n` +
|
104 | `(${e.message})`
|
105 | )
|
106 | }
|
107 | }
|
108 |
|
109 | exports.savePreset = (name, preset) => {
|
110 | const presets = cloneDeep(exports.loadOptions().presets || {})
|
111 | presets[name] = preset
|
112 | return exports.saveOptions({ presets })
|
113 | }
|