@gx-design-vue/create-gx-cli 0.1.15 → 0.1.16

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.
Files changed (123) hide show
  1. package/package.json +1 -1
  2. package/src/main.js +7 -7
  3. package/template-mobile-vant-cli/.env +3 -0
  4. package/template-mobile-vant-cli/.env.development +4 -6
  5. package/template-mobile-vant-cli/.env.pro +16 -7
  6. package/template-mobile-vant-cli/.env.production +21 -9
  7. package/template-mobile-vant-cli/commitlint.config.cjs +32 -0
  8. package/template-mobile-vant-cli/config/default/defaultSettings.ts +70 -0
  9. package/template-mobile-vant-cli/config/default/network.ts +10 -0
  10. package/template-mobile-vant-cli/config/default/proxy.ts +50 -0
  11. package/template-mobile-vant-cli/config/default/theme.ts +3 -0
  12. package/template-mobile-vant-cli/config/index.ts +11 -0
  13. package/template-mobile-vant-cli/eslint.config.js +10 -2
  14. package/template-mobile-vant-cli/index.html +22 -21
  15. package/template-mobile-vant-cli/{build → internal/vite-config/generate}/generateModifyVars.ts +1 -1
  16. package/template-mobile-vant-cli/internal/vite-config/rollupOptions/index.ts +22 -0
  17. package/template-mobile-vant-cli/internal/vite-config/util/hash.ts +17 -0
  18. package/template-mobile-vant-cli/internal/vite-config/util/index.ts +132 -0
  19. package/template-mobile-vant-cli/internal/vite-config/vite/cdn.ts +65 -0
  20. package/template-mobile-vant-cli/{build → internal/vite-config/vite}/optimizer.ts +9 -1
  21. package/template-mobile-vant-cli/internal/vite-config/vite/plugin/appConfig.ts +91 -0
  22. package/template-mobile-vant-cli/{build → internal/vite-config/vite}/plugin/autoImport.ts +7 -3
  23. package/template-mobile-vant-cli/internal/vite-config/vite/plugin/compress.ts +31 -0
  24. package/template-mobile-vant-cli/internal/vite-config/vite/plugin/html.ts +32 -0
  25. package/template-mobile-vant-cli/internal/vite-config/vite/plugin/index.ts +74 -0
  26. package/template-mobile-vant-cli/internal/vite-config/vite/plugin/visualizer.ts +14 -0
  27. package/template-mobile-vant-cli/internal/vite-config/vite/plugin/viteNotice.ts +40 -0
  28. package/template-mobile-vant-cli/mock/config/permissions.ts +15 -0
  29. package/template-mobile-vant-cli/mock/config/user/id.ts +5 -0
  30. package/template-mobile-vant-cli/mock/config/user/index.ts +96 -0
  31. package/template-mobile-vant-cli/mock/index.ts +55 -0
  32. package/template-mobile-vant-cli/mock/routers/table/index.fake.ts +22 -0
  33. package/template-mobile-vant-cli/mock/routers/user/account.fake.ts +52 -0
  34. package/template-mobile-vant-cli/mock/routers/user/index.fake.ts +46 -0
  35. package/template-mobile-vant-cli/mock/utils/crypto.ts +21 -0
  36. package/template-mobile-vant-cli/mock/utils/table.ts +96 -0
  37. package/template-mobile-vant-cli/mock/utils/util.ts +91 -0
  38. package/template-mobile-vant-cli/package.json +51 -34
  39. package/template-mobile-vant-cli/public/css/default.css +54 -0
  40. package/template-mobile-vant-cli/src/App.vue +6 -2
  41. package/template-mobile-vant-cli/src/assets/logo.png +0 -0
  42. package/template-mobile-vant-cli/src/components/PageContainer/ProSkeleton.tsx +1 -1
  43. package/template-mobile-vant-cli/src/components/PageContainer/index.tsx +108 -16
  44. package/template-mobile-vant-cli/src/components/PageContainer/style.module.less +5 -2
  45. package/template-mobile-vant-cli/src/components/TabsMenu/index.vue +45 -0
  46. package/template-mobile-vant-cli/src/core/gx-design/index.ts +1 -1
  47. package/template-mobile-vant-cli/src/core/index.ts +0 -7
  48. package/template-mobile-vant-cli/src/design/color.less +1 -0
  49. package/template-mobile-vant-cli/src/design/config.less +5 -0
  50. package/template-mobile-vant-cli/src/design/index.less +1 -1
  51. package/template-mobile-vant-cli/src/design/mixin.less +65 -0
  52. package/template-mobile-vant-cli/src/design/reset.less +16 -132
  53. package/template-mobile-vant-cli/src/hooks/web/usePageLoading.ts +7 -9
  54. package/template-mobile-vant-cli/src/layout/{BasicLayout.vue → BasicLayout/index.vue} +3 -1
  55. package/template-mobile-vant-cli/src/layout/BasicLayout/style.less +3 -0
  56. package/template-mobile-vant-cli/src/layout/UserLayout/index.vue +18 -0
  57. package/template-mobile-vant-cli/src/layout/UserLayout/style.module.less +36 -0
  58. package/template-mobile-vant-cli/src/main.ts +16 -9
  59. package/template-mobile-vant-cli/src/pages/Account/details.vue +13 -0
  60. package/template-mobile-vant-cli/src/pages/Account/index.vue +102 -0
  61. package/template-mobile-vant-cli/src/pages/{home.vue → Home/index.vue} +5 -5
  62. package/template-mobile-vant-cli/src/pages/user/login/index.vue +74 -0
  63. package/template-mobile-vant-cli/src/plugins/dayjs/index.ts +3 -0
  64. package/template-mobile-vant-cli/src/plugins/index.ts +2 -0
  65. package/template-mobile-vant-cli/src/router/guard/index.ts +18 -0
  66. package/template-mobile-vant-cli/src/router/guard/permissions.ts +41 -0
  67. package/template-mobile-vant-cli/src/router/guard/stateGuard.ts +10 -0
  68. package/template-mobile-vant-cli/src/router/index.ts +21 -15
  69. package/template-mobile-vant-cli/src/router/routes/index.ts +46 -0
  70. package/template-mobile-vant-cli/src/router/routes/modules/dataSource.ts +32 -0
  71. package/template-mobile-vant-cli/src/services/userCenter/account.ts +42 -0
  72. package/template-mobile-vant-cli/src/services/userCenter/index.ts +28 -0
  73. package/template-mobile-vant-cli/src/store/index.ts +4 -1
  74. package/template-mobile-vant-cli/src/store/modules/global.ts +6 -13
  75. package/template-mobile-vant-cli/src/store/modules/user.ts +107 -0
  76. package/template-mobile-vant-cli/src/utils/accessToken.ts +97 -0
  77. package/template-mobile-vant-cli/src/utils/crypto/index.ts +3 -4
  78. package/template-mobile-vant-cli/src/utils/env.ts +2 -2
  79. package/template-mobile-vant-cli/src/utils/pageTitle.ts +12 -6
  80. package/template-mobile-vant-cli/src/utils/request/XHR.ts +9 -11
  81. package/template-mobile-vant-cli/src/utils/request/axiosCancel.ts +5 -5
  82. package/template-mobile-vant-cli/src/utils/request/checkStatus.ts +18 -2
  83. package/template-mobile-vant-cli/src/utils/request/index.ts +36 -23
  84. package/template-mobile-vant-cli/src/utils/storage.ts +49 -32
  85. package/template-mobile-vant-cli/src/utils/validate.ts +31 -36
  86. package/template-mobile-vant-cli/tsconfig.json +17 -9
  87. package/template-mobile-vant-cli/types/auto-imports.d.ts +18 -2
  88. package/template-mobile-vant-cli/types/components.d.ts +2 -7
  89. package/template-mobile-vant-cli/types/config.d.ts +56 -0
  90. package/template-mobile-vant-cli/types/global.d.ts +62 -21
  91. package/template-mobile-vant-cli/types/mock.d.ts +34 -0
  92. package/template-mobile-vant-cli/types/module.d.ts +33 -0
  93. package/template-mobile-vant-cli/types/response.d.ts +3 -1
  94. package/template-mobile-vant-cli/types/system.d.ts +58 -0
  95. package/template-mobile-vant-cli/types/vant-import.d.ts +16 -5
  96. package/template-mobile-vant-cli/unocss.config.ts +120 -66
  97. package/template-mobile-vant-cli/vite.config.ts +78 -81
  98. package/template-mobile-vant-cli/build/cdn.ts +0 -5
  99. package/template-mobile-vant-cli/build/plugin/html.ts +0 -26
  100. package/template-mobile-vant-cli/build/plugin/index.ts +0 -42
  101. package/template-mobile-vant-cli/build/plugin/mock.ts +0 -14
  102. package/template-mobile-vant-cli/build/plugin/viteMock/client.ts +0 -88
  103. package/template-mobile-vant-cli/build/plugin/viteMock/createMockServer.ts +0 -271
  104. package/template-mobile-vant-cli/build/plugin/viteMock/index.ts +0 -69
  105. package/template-mobile-vant-cli/build/plugin/viteMock/types.ts +0 -48
  106. package/template-mobile-vant-cli/build/plugin/viteMock/utils.ts +0 -48
  107. package/template-mobile-vant-cli/build/script/postBuild.ts +0 -14
  108. package/template-mobile-vant-cli/mock/_createProductionServer.ts +0 -19
  109. package/template-mobile-vant-cli/mock/utils.ts +0 -9
  110. package/template-mobile-vant-cli/postcss.config.cjs +0 -8
  111. package/template-mobile-vant-cli/prettier.config.cjs +0 -18
  112. package/template-mobile-vant-cli/public/js/flexible.js +0 -44
  113. package/template-mobile-vant-cli/src/core/vant-design/index.ts +0 -4
  114. package/template-mobile-vant-cli/src/design/vant.less +0 -2
  115. package/template-mobile-vant-cli/src/global.less +0 -1
  116. package/template-mobile-vant-cli/src/layout/basicLayout.less +0 -11
  117. package/template-mobile-vant-cli/src/router/routes.ts +0 -20
  118. package/template-mobile-vant-cli/src/router/typings.ts +0 -8
  119. package/template-mobile-vant-cli/src/settings/index.ts +0 -10
  120. package/template-mobile-vant-cli/src/utils/crypto/base64.ts +0 -101
  121. package/template-mobile-vant-cli/types/ant-design-import.d.ts +0 -13
  122. package/template-mobile-vant-cli/types/plugins-auto-import.d.ts +0 -14
  123. /package/template-mobile-vant-cli/{mock/datasSource/api/index.ts → src/design/vant/index.less} +0 -0
@@ -1,18 +1,19 @@
1
- import type { ConfigEnv, ProxyOptions, UserConfig } from 'vite'
2
- import { loadEnv } from 'vite'
3
- import { resolve } from 'node:path'
1
+ import type { ConfigEnv, UserConfig } from 'vite'
2
+ import autoprefixer from 'autoprefixer'
4
3
  import dayjs from 'dayjs'
5
- import { isObject, isString } from '@gx-design-vue/pro-utils'
4
+ import viewport from 'postcss-mobile-forever'
5
+ import { loadEnv } from 'vite'
6
6
 
7
- import { configManualChunk } from './build/optimizer'
8
- import { createVitePlugins } from './build/plugin'
9
- import { generateModifyVars } from './build/generateModifyVars'
7
+ import { createProxy, defaultSettings } from './config'
8
+ import { generateModifyVars } from './internal/vite-config/generate/generateModifyVars'
9
+ import createRollupOptions from './internal/vite-config/rollupOptions'
10
+ import { pathResolve, wrapperEnv } from './internal/vite-config/util'
10
11
 
11
- import pkg from './package.json'
12
+ import { createVitePlugins } from './internal/vite-config/vite/plugin'
12
13
 
13
- type ProxyTargetList = ProxyOptions & { rewrite: (path: string) => string }
14
+ import pkg from './package.json'
14
15
 
15
- const proxyTarget: string | Record<string, any> = 'http://127.0.0.1:3000'
16
+ const { proxy, cdn, build, servive } = defaultSettings
16
17
 
17
18
  const { dependencies, devDependencies, name, version } = pkg
18
19
 
@@ -21,82 +22,40 @@ const __APP_INFO__ = {
21
22
  lastBuildTime: dayjs().format('YYYY-MM-DD HH:mm:ss')
22
23
  }
23
24
 
24
- function pathResolve(dir: string) {
25
- return resolve(process.cwd(), '.', dir)
26
- }
27
-
28
- function createProxy(prefix) {
29
- const ret = {
30
- dev: {},
31
- test: {},
32
- pre: {}
33
- }
34
-
35
- if (isObject(proxyTarget)) {
36
- Object.keys(proxyTarget).forEach((prefix) => {
37
- const proxy = {
38
- target: `${proxyTarget[prefix]}`,
39
- changeOrigin: true,
40
- ws: true,
41
- rewrite: path => path.replace(new RegExp(`^${prefix}`), '')
42
- } as ProxyTargetList
43
-
44
- ret.dev[prefix] = proxy
45
- ret.test[prefix] = proxy
46
- ret.pre[prefix] = proxy
47
- })
48
- } else if (isString(proxyTarget)) {
49
- const proxy = {
50
- target: `${proxyTarget}`,
51
- changeOrigin: true,
52
- ws: true,
53
- rewrite: path => path.replace(new RegExp(`^${prefix}`), '')
54
- }
55
- ret.dev[prefix] = proxy
56
- ret.test[prefix] = proxy
57
- ret.pre[prefix] = proxy
58
- }
25
+ process.env.VUE_APP_VERSION = version
59
26
 
60
- return ret
61
- }
62
-
63
- function wrapperEnv(envConf: RecordType): ViteEnv {
64
- const ret: any = {}
65
-
66
- for (const envName of Object.keys(envConf)) {
67
- let realName = envConf[envName].replace(/\\n/g, '\n')
68
- realName = realName === 'true' ? true : realName === 'false' ? false : realName
69
-
70
- ret[envName] = realName
71
- process.env[envName] = realName
72
- }
73
- return ret
74
- }
75
-
76
- export default ({ mode, command }: ConfigEnv): UserConfig => {
27
+ export default async ({ command, mode }: ConfigEnv): Promise<UserConfig> => {
77
28
  const root = process.cwd()
78
29
 
79
30
  const env = loadEnv(mode, root)
80
31
 
81
- // The boolean type read by loadEnv is a string. This function can be converted to boolean type
82
32
  const viteEnv = wrapperEnv(env)
83
33
 
84
- const { VITE_BASE_URL, VITE_DROP_CONSOLE } = viteEnv
34
+ const { VITE_DROP_CONSOLE, VITE_APP_ENV, VITE_PROXY_PREFIX } = viteEnv
85
35
 
86
36
  const isBuild = command === 'build'
87
37
 
88
38
  return {
89
- base: './',
39
+ base: build.publicPath,
40
+ root,
90
41
  resolve: {
91
42
  alias: [
92
43
  {
93
44
  find: '@',
94
45
  replacement: pathResolve('src') + '/'
95
46
  },
47
+ {
48
+ find: '@gx-mock',
49
+ replacement: pathResolve('mock') + '/index.ts'
50
+ },
96
51
  {
97
52
  find: '@gx-mock',
98
53
  replacement: pathResolve('mock') + '/'
99
54
  },
55
+ {
56
+ find: '@gx-config',
57
+ replacement: pathResolve('config') + '/index.ts'
58
+ },
100
59
  {
101
60
  find: '@gx-vuex',
102
61
  replacement: pathResolve('src/store') + '/index.ts'
@@ -105,34 +64,59 @@ export default ({ mode, command }: ConfigEnv): UserConfig => {
105
64
  find: '@gx-mobile/hooks',
106
65
  replacement: pathResolve('src/hooks')
107
66
  },
108
- { find: /^~/, replacement: '' }
67
+ {
68
+ find: '@gx-admin/vite-config',
69
+ replacement: pathResolve('internal/vite-config') + '/'
70
+ }
109
71
  ]
110
72
  },
111
73
  server: {
74
+ open: false,
112
75
  host: true,
113
- port: 3000,
114
- proxy: createProxy(VITE_BASE_URL)
115
- },
116
- plugins: createVitePlugins(viteEnv, isBuild),
117
- define: {
118
- __INTLIFY_PROD_DEVTOOLS__: false,
119
- __APP_INFO__: JSON.stringify(__APP_INFO__)
76
+ port: servive.port,
77
+ warmup: {
78
+ // 预热文件
79
+ clientFiles: [
80
+ './index.html',
81
+ './src/{views,layout,router,store,components}/*',
82
+ ],
83
+ },
84
+ proxy: proxy.use ? createProxy(VITE_PROXY_PREFIX)[VITE_APP_ENV] : {}
120
85
  },
121
86
  esbuild: {
122
87
  drop: VITE_DROP_CONSOLE ? [ 'console', 'debugger' ] : []
123
88
  },
124
89
  build: {
125
- assetsDir: 'assets',
126
- chunkSizeWarningLimit: 2500,
127
- rollupOptions: {
128
- output: {
129
- manualChunks: configManualChunk as any
130
- }
131
- }
90
+ cssTarget: 'chrome80',
91
+ outDir: build.outputDir,
92
+ assetsDir: build.assetsDir,
93
+ chunkSizeWarningLimit: 4000,
94
+ rollupOptions: createRollupOptions(cdn.use) as any
95
+ },
96
+ define: {
97
+ __INTLIFY_PROD_DEVTOOLS__: false,
98
+ __APP_INFO__: JSON.stringify(__APP_INFO__)
132
99
  },
133
100
  css: {
101
+ postcss: {
102
+ plugins: [
103
+ autoprefixer({
104
+ grid: true
105
+ }),
106
+ viewport({
107
+ appSelector: '#app',
108
+ viewportWidth: 375,
109
+ maxDisplayWidth: 600,
110
+ rootContainingBlockSelectorList: [
111
+ 'van-tabbar',
112
+ 'van-popup',
113
+ ],
114
+ border: true,
115
+ }),
116
+ ]
117
+ },
134
118
  modules: {
135
- generateScopedName: 'gx-mobile-[local]-[hash:base64:5]'
119
+ generateScopedName: 'gx-pro-[local]-[hash:base64:5]'
136
120
  },
137
121
  preprocessorOptions: {
138
122
  less: {
@@ -140,6 +124,19 @@ export default ({ mode, command }: ConfigEnv): UserConfig => {
140
124
  javascriptEnabled: true
141
125
  }
142
126
  }
127
+ },
128
+
129
+ plugins: await createVitePlugins(viteEnv, isBuild),
130
+
131
+ optimizeDeps: {
132
+ include: [
133
+ 'qs',
134
+ 'dayjs',
135
+ 'axios',
136
+ 'pinia',
137
+ 'echarts',
138
+ '@vueuse/core'
139
+ ]
143
140
  }
144
141
  }
145
142
  }
@@ -1,5 +0,0 @@
1
- const css = []
2
-
3
- const js = []
4
-
5
- export const cdnConf = { css, js }
@@ -1,26 +0,0 @@
1
- /**
2
- * Plugin to minimize and use ejs template syntax in index.html.
3
- * https://github.com/anncwb/vite-plugin-html
4
- */
5
- import { PluginOption } from 'vite'
6
-
7
- import { createHtmlPlugin } from 'vite-plugin-html'
8
-
9
- import { cdnConf } from '../cdn'
10
-
11
- export function configHtmlPlugin(env: ViteEnv, isBuild: boolean) {
12
-
13
- const htmlPlugin: PluginOption[] = createHtmlPlugin({
14
- minify: isBuild,
15
- inject: {
16
- data: {
17
- injectScript: env.VITE_USE_CDN ? cdnConf.js : [],
18
- injectLink: env.VITE_USE_CDN ? cdnConf.css : [],
19
- injectVlogScript: env.VITE_USE_V_CONSOLE
20
- ? `<script src="https://unpkg.com/vconsole@latest/dist/vconsole.min.js"></script><script>var vConsole = new window.VConsole();</script>`
21
- : ''
22
- }
23
- }
24
- })
25
- return htmlPlugin
26
- }
@@ -1,42 +0,0 @@
1
- import type { Plugin, PluginOption } from 'vite'
2
-
3
- import vue from '@vitejs/plugin-vue'
4
- import vueJsx from '@vitejs/plugin-vue-jsx'
5
-
6
- import vueSetupExtend from 'vite-plugin-vue-setup-extend'
7
-
8
- import Unocss from 'unocss/vite'
9
-
10
- import { configHtmlPlugin } from './html'
11
- import { configMockPlugin } from './mock'
12
- import { createAutoImport } from './autoImport'
13
-
14
- export function createVitePlugins(viteEnv: ViteEnv, isBuild: boolean) {
15
- const {
16
- VITE_USE_MOCK
17
- } = viteEnv
18
-
19
- const vitePlugins: (Plugin | PluginOption[])[] = [
20
- // have to
21
- vue(),
22
- // have to
23
- vueJsx()
24
- ]
25
-
26
- // unocss
27
- vitePlugins.push(Unocss())
28
-
29
- // vite-plugin-vue-setup-extend
30
- vitePlugins.push(vueSetupExtend())
31
-
32
- // vite-plugin-html
33
- vitePlugins.push(configHtmlPlugin(viteEnv, isBuild))
34
-
35
- // vite-plugin-mock
36
- VITE_USE_MOCK && vitePlugins.push(configMockPlugin())
37
-
38
- // unplugin-auto-import/vite
39
- vitePlugins.push(createAutoImport())
40
-
41
- return vitePlugins
42
- }
@@ -1,14 +0,0 @@
1
- import { viteMockServe } from './viteMock'
2
-
3
- export function configMockPlugin() {
4
- return viteMockServe({
5
- ignore: /^_/,
6
- mockPath: 'mock',
7
- enable: true,
8
- injectCode: `
9
- import { setupProdMockServer } from '../mock/_createProductionServer';
10
-
11
- setupProdMockServer();
12
- `,
13
- })
14
- }
@@ -1,88 +0,0 @@
1
- import mockJs from 'mockjs'
2
- import { pathToRegexp } from 'path-to-regexp'
3
-
4
- const Mock = mockJs as any
5
-
6
- export function createProdMockServer(mockList: any[]) {
7
- Mock.XHR.prototype.__send = Mock.XHR.prototype.send
8
- Mock.XHR.prototype.send = function () {
9
- if (this.custom.xhr) {
10
- this.custom.xhr.withCredentials = this.withCredentials || false
11
-
12
- if (this.responseType) {
13
- this.custom.xhr.responseType = this.responseType
14
- }
15
- }
16
- if (this.custom.requestHeaders) {
17
- const headers: any = {}
18
- for (let k in this.custom.requestHeaders) {
19
- headers[k.toString().toLowerCase()] = this.custom.requestHeaders[k]
20
- }
21
- this.custom.options = Object.assign({}, this.custom.options, { headers })
22
- }
23
- this.__send.apply(this, arguments)
24
- }
25
-
26
- Mock.XHR.prototype.proxy_open = Mock.XHR.prototype.open
27
-
28
- Mock.XHR.prototype.open = function () {
29
- let responseType = this.responseType
30
- this.proxy_open(...arguments)
31
- if (this.custom.xhr) {
32
- if (responseType) {
33
- this.custom.xhr.responseType = responseType
34
- }
35
- }
36
- }
37
-
38
- for (const { url, method, response, timeout } of mockList) {
39
- __setupMock__(timeout)
40
- Mock.mock(
41
- pathToRegexp(url, undefined, { end: false }),
42
- method || 'get',
43
- __XHR2ExpressReqWrapper__(response)
44
- )
45
- }
46
- }
47
-
48
- function __param2Obj__(url: string) {
49
- const search = url.split('?')[1]
50
- if (!search) {
51
- return {}
52
- }
53
- return JSON.parse(
54
- '{"' +
55
- decodeURIComponent(search)
56
- .replace(/"/g, '\\"')
57
- .replace(/&/g, '","')
58
- .replace(/=/g, '":"')
59
- .replace(/\+/g, ' ') +
60
- '"}'
61
- )
62
- }
63
-
64
- function __XHR2ExpressReqWrapper__(handle: (d: any) => any) {
65
- return function (options: any) {
66
- let result = null
67
- if (typeof handle === 'function') {
68
- const { body, type, url, headers } = options
69
- result = handle({
70
- method: type,
71
- body: JSON.parse(body),
72
- query: __param2Obj__(url),
73
- headers
74
- })
75
- } else {
76
- result = handle
77
- }
78
-
79
- return Mock.mock(result)
80
- }
81
- }
82
-
83
- function __setupMock__(timeout = 0) {
84
- timeout &&
85
- Mock.setup({
86
- timeout
87
- })
88
- }
@@ -1,271 +0,0 @@
1
- import type { MockMethod, Recordable, RespThisType, ViteMockOptions } from './types'
2
- import path from 'node:path'
3
- import fs from 'node:fs'
4
- import chokidar from 'chokidar'
5
- import colors from 'picocolors'
6
- import url from 'node:url'
7
- import fg from 'fast-glob'
8
- import Mock from 'mockjs'
9
- import type { ResolvedConfig } from 'vite'
10
- import { match, pathToRegexp } from 'path-to-regexp'
11
- import type { IncomingMessage, NextHandleFunction } from 'connect'
12
- import type { GetOutputFile } from 'bundle-require'
13
- import { bundleRequire, JS_EXT_RE } from 'bundle-require'
14
- import { isAbsPath, isArray, isFunction, isRegExp, sleep } from './utils'
15
-
16
- export let mockData: MockMethod[] = []
17
-
18
- export async function createMockServer(
19
- opt: ViteMockOptions = { mockPath: 'mock', configPath: 'vite.mock.config' },
20
- config: ResolvedConfig,
21
- ) {
22
- opt = {
23
- mockPath: 'mock',
24
- watchFiles: true,
25
- configPath: 'vite.mock.config.ts',
26
- logger: true,
27
- cors: true,
28
- ...opt,
29
- }
30
-
31
- if (mockData.length > 0)
32
- return
33
- mockData = await getMockConfig(opt, config)
34
- await createWatch(opt, config)
35
- }
36
-
37
- // request match
38
- export async function requestMiddleware(opt: ViteMockOptions) {
39
- const { logger = true } = opt
40
- const middleware: NextHandleFunction = async (req, res, next) => {
41
- let queryParams: {
42
- query?: {
43
- [key: string]: any
44
- }
45
- pathname?: string | null
46
- } = {}
47
-
48
- if (req.url) {
49
- queryParams = url.parse(req.url, true)
50
- }
51
-
52
- const reqUrl = queryParams.pathname
53
-
54
- const matchRequest = mockData.find((item) => {
55
- if (!reqUrl || !item || !item.url) {
56
- return false
57
- }
58
- if (item.method && item.method.toUpperCase() !== req.method) {
59
- return false
60
- }
61
- return pathToRegexp(item.url).test(reqUrl)
62
- })
63
-
64
- if (matchRequest) {
65
- const isGet = req.method && req.method.toUpperCase() === 'GET'
66
- const { response, rawResponse, timeout, statusCode, url } = matchRequest
67
-
68
- if (timeout) {
69
- await sleep(timeout)
70
- }
71
-
72
- const urlMatch = match(url, { decode: decodeURIComponent })
73
-
74
- let query = queryParams.query as any
75
- if (reqUrl) {
76
- if ((isGet && JSON.stringify(query) === '{}') || !isGet) {
77
- const params = (urlMatch(reqUrl) as any).params
78
- if (JSON.stringify(params) !== '{}') {
79
- query = (urlMatch(reqUrl) as any).params || {}
80
- } else {
81
- query = queryParams.query || {}
82
- }
83
- }
84
- }
85
-
86
- const self: RespThisType = { req, res, parseJson: parseJson.bind(null, req) }
87
- if (isFunction(rawResponse)) {
88
- await rawResponse.bind(self)(req, res)
89
- } else {
90
- const body = await parseJson(req)
91
- res.setHeader('Content-Type', 'application/json')
92
- if (opt) {
93
- res.setHeader('Access-Control-Allow-Credentials', true)
94
- res.setHeader('Access-Control-Allow-Origin', req.headers.origin || '*')
95
- }
96
- res.statusCode = statusCode || 200
97
- const mockResponse = isFunction(response)
98
- ? response.bind(self)({ url: req.url as any, body, query, headers: req.headers })
99
- : response
100
- res.end(JSON.stringify(Mock.mock(mockResponse)))
101
- }
102
-
103
- logger && loggerOutput('request invoke', req.url!)
104
- return
105
- }
106
- next()
107
- }
108
- return middleware
109
- }
110
-
111
- // create watch mock
112
- function createWatch(opt: ViteMockOptions, config: ResolvedConfig) {
113
- const { configPath, logger, watchFiles } = opt
114
-
115
- if (!watchFiles) {
116
- return
117
- }
118
-
119
- const { absConfigPath, absMockPath } = getPath(opt)
120
-
121
- if (process.env.VITE_DISABLED_WATCH_MOCK === 'true') {
122
- return
123
- }
124
-
125
- const watchDir = []
126
- const exitsConfigPath = fs.existsSync(absConfigPath)
127
-
128
- exitsConfigPath && configPath ? watchDir.push(absConfigPath) : watchDir.push(absMockPath)
129
-
130
- const watcher = chokidar.watch(watchDir, {
131
- ignoreInitial: true,
132
- // ignore files generated by `bundle require`
133
- ignored: '**/_*.bundled_*.(mjs|cjs)',
134
- })
135
-
136
- watcher.on('all', async (event, file) => {
137
- logger && loggerOutput(`mock file ${event}`, file)
138
- mockData = await getMockConfig(opt, config)
139
- })
140
- }
141
-
142
- // clear cache
143
- // function cleanRequireCache(opt: ViteMockOptions) {
144
- // if (typeof require === 'undefined' || !require.cache) {
145
- // return
146
- // }
147
- // const { absConfigPath, absMockPath } = getPath(opt)
148
- // Object.keys(require.cache).forEach((file) => {
149
- // if (file === absConfigPath || file.indexOf(absMockPath) > -1) {
150
- // delete require.cache[file]
151
- // }
152
- // })
153
- // }
154
-
155
- function parseJson(req: IncomingMessage): Promise<Recordable> {
156
- return new Promise((resolve) => {
157
- let body = ''
158
- let jsonStr = ''
159
- req.on('data', function (chunk) {
160
- body += chunk
161
- })
162
- req.on('end', function () {
163
- try {
164
- jsonStr = JSON.parse(body)
165
- } catch (err) {
166
- jsonStr = ''
167
- }
168
- resolve(jsonStr as any)
169
- return
170
- })
171
- })
172
- }
173
-
174
- // load mock .ts files and watch
175
- async function getMockConfig(opt: ViteMockOptions, config: ResolvedConfig) {
176
- const { absConfigPath, absMockPath } = getPath(opt)
177
- const { ignore, configPath, logger } = opt
178
-
179
- let ret: MockMethod[] = []
180
- if (configPath && fs.existsSync(absConfigPath)) {
181
- logger && loggerOutput(`load mock data from`, absConfigPath)
182
- ret = await resolveModule(absConfigPath, config)
183
- return ret
184
- }
185
-
186
- const mockFiles = fg
187
- .sync(`**/*.{ts,mjs,js}`, {
188
- cwd: absMockPath,
189
- })
190
- .filter((item) => {
191
- if (!ignore) {
192
- return true
193
- }
194
- if (isFunction(ignore)) {
195
- return !ignore(item)
196
- }
197
- if (isRegExp(ignore)) {
198
- return !ignore.test(path.basename(item))
199
- }
200
- return true
201
- })
202
- try {
203
- ret = []
204
- const resolveModulePromiseList = []
205
-
206
- for (let index = 0; index < mockFiles.length; index++) {
207
- const mockFile = mockFiles[index]
208
- resolveModulePromiseList.push(resolveModule(path.join(absMockPath, mockFile), config))
209
- }
210
- const loadAllResult = await Promise.all(resolveModulePromiseList)
211
- for (const resultModule of loadAllResult) {
212
- let mod = resultModule
213
- if (!isArray(mod)) {
214
- mod = [mod]
215
- }
216
- ret = [...ret, ...mod]
217
- }
218
- } catch (error: any) {
219
- loggerOutput(`mock reload error`, error)
220
- ret = []
221
- }
222
- return ret
223
- }
224
-
225
- // fixed file generation format
226
- // use a random path to avoid import cache
227
- const getOutputFile: GetOutputFile = (filepath, format) => {
228
- const dirname = path.dirname(filepath)
229
- const basename = path.basename(filepath)
230
- const randomname = `${Date.now()}_${Math.random().toString(36).substring(2, 15)}`
231
- return path.resolve(
232
- dirname,
233
- `_${basename.replace(JS_EXT_RE, `.bundled_${randomname}.${format === 'esm' ? 'mjs' : 'cjs'}`)}`,
234
- )
235
- }
236
-
237
- // Inspired by vite
238
- // support mock .ts files
239
- async function resolveModule(p: string, config: ResolvedConfig): Promise<any> {
240
- const mockData = await bundleRequire({
241
- filepath: p,
242
- getOutputFile,
243
- })
244
-
245
- let mod = mockData.mod.default || mockData.mod
246
- if (isFunction(mod)) {
247
- mod = await mod({ env: config.env, mode: config.mode, command: config.command })
248
- }
249
- return mod
250
- }
251
-
252
- // get custom config file path and mock dir path
253
- function getPath(opt: ViteMockOptions) {
254
- const { mockPath, configPath } = opt
255
- const cwd = process.cwd()
256
- const absMockPath = isAbsPath(mockPath) ? mockPath! : path.join(cwd, mockPath || '')
257
- const absConfigPath = path.join(cwd, configPath || '')
258
- return {
259
- absMockPath,
260
- absConfigPath,
261
- }
262
- }
263
-
264
- function loggerOutput(title: string, msg: string, type: 'info' | 'error' = 'info') {
265
- const tag = type === 'info' ? colors.cyan(`[vite:mock]`) : colors.red(`[vite:mock-server]`)
266
- return console.log(
267
- `${colors.dim(new Date().toLocaleTimeString())} ${tag} ${colors.green(title)} ${colors.dim(
268
- msg,
269
- )}`,
270
- )
271
- }