create-young-proj 1.3.0 → 1.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,204 @@
1
+ /*
2
+ * @Author: zhangyang
3
+ * @Date: 2023-11-10 18:02:07
4
+ * @LastEditTime: 2023-11-27 15:01:31
5
+ * @Description:
6
+ */
7
+ import { resolve } from 'node:path'
8
+ import { loadConfig } from 'c12'
9
+ import md5 from 'md5'
10
+
11
+ /**
12
+ * 签名
13
+ * @param params 参与签名的参数
14
+ * @param token 秘钥
15
+ */
16
+ export function signFn(params: Record<string, any>, token: string) {
17
+ const asciiSortedIndexArr = Object.keys(params).sort()
18
+ let str = ''
19
+ const obj: Record<string, any> = {}
20
+ if (asciiSortedIndexArr.length > 0) {
21
+ for (const key of asciiSortedIndexArr) {
22
+ const v = params[key]
23
+ if (v !== null && v !== '') {
24
+ str += `${key}=${encodeURIComponent(v)}&`
25
+ obj[key] = v
26
+ }
27
+ }
28
+ }
29
+ str += `token=${token}`
30
+ return {
31
+ sign: md5(str).toUpperCase(),
32
+ rawValue: obj,
33
+ }
34
+ }
35
+
36
+ /**
37
+ * 服务上报
38
+ */
39
+ export async function useServerReport(port: number) {
40
+ enum ReportURL {
41
+ 上线 = '/register/login',
42
+ 心跳 = '/register/heart',
43
+ }
44
+
45
+ const commonReq = async <T>(url: string, data: Record<string, any>, token: string) => {
46
+ const api_server_url
47
+ = process.env.NUXT_PUBLIC_API_SERVER || `http://${process.env.APIGATEHOST}`
48
+ const { sign, rawValue } = signFn(data, token)
49
+
50
+ console.log('🚀 ~ file: env.ts:41 ~ commonReq ~ api_server_url:', api_server_url, rawValue)
51
+
52
+ const headers = {
53
+ 'Authorization': `Bearer ${token}`,
54
+ 'content-type': 'application/json; charset=utf-8;',
55
+ 'time': `${Math.floor(Date.now() / 1000)}`,
56
+ sign,
57
+ }
58
+
59
+ return $fetch<T>(`${api_server_url}${url}`, {
60
+ method: 'post',
61
+ headers,
62
+ body: JSON.stringify(rawValue),
63
+ })
64
+ }
65
+
66
+ /**
67
+ * auth token
68
+ */
69
+ let token: string
70
+
71
+ /**
72
+ * 登录/获取 token
73
+ */
74
+ const login = async () => {
75
+ const data = {
76
+ serverId: process.env.APP_SERVER_ID,
77
+ serverName: process.env.APP_SERVER_NAME,
78
+ }
79
+
80
+ const { data: _data } = await commonReq<{
81
+ code: number
82
+ message: string
83
+ data: { token: string }
84
+ }>('/account/v1/internal/service/get_token', data, process.env.APP_SERVER_SECERET as string)
85
+
86
+ console.log('🚀 ~ file: env.ts:73 ~ login ~ _data:', _data)
87
+
88
+ const { token } = _data
89
+ console.log('login success, token: ', token, '\ntime: ', new Date().toLocaleString())
90
+ return token
91
+ }
92
+
93
+ /**
94
+ * 获取 auth token
95
+ */
96
+ const getToken = async () => {
97
+ if (!token) {
98
+ token = await login()
99
+ setInterval(() => {
100
+ // 每 23 小时刷一次 token
101
+ token = ''
102
+ }, 1000 * 3600 * 23)
103
+ }
104
+ return token
105
+ }
106
+
107
+ /**
108
+ * 服务上线
109
+ */
110
+ const report = async (url: ReportURL) => {
111
+ const token = await getToken()
112
+ try {
113
+ const res = await commonReq<{
114
+ host: string
115
+ port: string | number
116
+ weight: number
117
+ expire: number
118
+ }>(url, { port }, token)
119
+
120
+ console.log('请求成功:', url, new Date().toLocaleString())
121
+ return res
122
+ }
123
+ catch (error) {
124
+ console.error('请求失败:', url, error)
125
+ }
126
+ }
127
+
128
+ console.log('------------------------服务登录------------------------')
129
+ await login()
130
+ console.log('--------------------------------------------------------')
131
+
132
+ console.log('------------------------服务上线------------------------')
133
+ const info1 = await report(ReportURL.上线)
134
+ console.log('🚀 ~ file: init.ts:156 ~ defineNitroPlugin ~ info', info1)
135
+ console.log('--------------------------------------------------------')
136
+
137
+ console.log('------------------------服务心跳上报----------------------')
138
+ const info2 = await report(ReportURL.心跳)
139
+ console.log('🚀 ~ file: init.ts:163 ~ setInterval ~ info', info2)
140
+ console.log('----------------------------------------------------------')
141
+ setInterval(async () => {
142
+ console.log('------------------------服务心跳上报----------------------')
143
+ const info = await report(ReportURL.心跳)
144
+ console.log('🚀 ~ file: init.ts:163 ~ setInterval ~ info', info)
145
+ console.log('----------------------------------------------------------')
146
+ }, 1e4)
147
+ }
148
+
149
+ export default defineNitroPlugin(async (nitroApp) => {
150
+ const env = (process.env.DEPLOY_ENV as 'dev' | 'test' | 'online') || 'dev'
151
+ const { config } = await loadConfig<Record<string, any>>({
152
+ name: env,
153
+ cwd: resolve(process.cwd(), 'config'),
154
+ defaultConfig: {
155
+ // 此处可以放置通用的环境变量
156
+ // 由于频繁修改 package.json 会浪费 docker 性能,故将版本信息放于此处
157
+ // 优先读取环境变量中的版本信息(自己打的 Tag)
158
+ NUXT_PUBLIC_CURRENT_VERSION: process.env.PROJECT_VERSION || 'v0.0.1',
159
+
160
+ // 服务秘钥,不对前端开放
161
+ APP_SERVER_SECERET: '我是秘钥',
162
+ APP_SERVER_NAME: '我是服务名称',
163
+ APP_SERVER_ID: '我是服务id',
164
+ },
165
+ })
166
+
167
+ for (const key in config) {
168
+ if (process.env[key]) {
169
+ console.log(
170
+ '系统环境变量优先: ',
171
+ key,
172
+ ' = ',
173
+ process.env[key],
174
+ ' -> ',
175
+ config[key],
176
+ ' -> ',
177
+ '覆盖',
178
+ )
179
+ config[key] = process.env[key]
180
+ }
181
+ else {
182
+ process.env[key] = config[key]
183
+ }
184
+ if (!(key.indexOf('NUXT_PUBLIC_') === 0))
185
+ delete config[key]
186
+ }
187
+
188
+ console.log('------------------------读取配置文件------------------------')
189
+ console.log(config)
190
+ console.log('-------------------------------------------------------------')
191
+
192
+ nitroApp.hooks.hook('request', (event) => {
193
+ const headers = event.node.req.headers
194
+ const path = event.node.req.url
195
+ console.log('path', path, 'ua', headers['user-agent'], 'x-forwarded-for', headers['x-forwarded-for'], 'x-real-ip', headers['x-real-ip'])
196
+ })
197
+
198
+ // 本地开发,不上报
199
+ if (process.env.NODE_ENV === 'development')
200
+ return
201
+
202
+ const port = process.env.LISTEN_PORT || 3333
203
+ useServerReport(+port)
204
+ })
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "./.nitro/types/tsconfig.json"
3
+ }
@@ -0,0 +1,66 @@
1
+ /*
2
+ * @Author: zhangyang
3
+ * @Date: 2023-11-08 16:35:24
4
+ * @LastEditTime: 2023-11-08 16:37:49
5
+ * @Description:
6
+ */
7
+ import fs from 'node:fs'
8
+ import type { Plugin } from 'vite'
9
+ import { defineConfig } from 'vite'
10
+ import Components from 'unplugin-vue-components/vite'
11
+ import Unocss from 'unocss/vite'
12
+ import { presetAttributify, presetIcons, presetUno } from 'unocss'
13
+ import { resolve } from 'pathe'
14
+
15
+ export default defineConfig({
16
+ optimizeDeps: {
17
+ // vitepress is aliased with replacement `join(DIST_CLIENT_PATH, '/index')`
18
+ // This needs to be excluded from optimization
19
+ exclude: ['@vueuse/core', 'vitepress'],
20
+ },
21
+ server: {
22
+ host: true,
23
+ hmr: {
24
+ overlay: false,
25
+ },
26
+ },
27
+ plugins: [
28
+ Components({
29
+ include: [/\.vue/, /\.md/],
30
+ dirs: '.vitepress/components',
31
+ dts: '.vitepress/components.d.ts',
32
+ }) as Plugin,
33
+ Unocss({
34
+ shortcuts: [
35
+ ['btn', 'px-4 py-1 rounded inline-flex justify-center gap-2 text-white leading-30px children:mya !no-underline cursor-pointer disabled:cursor-default disabled:bg-gray-600 disabled:opacity-50'],
36
+ ],
37
+ presets: [
38
+ presetUno({
39
+ dark: 'media',
40
+ }),
41
+ presetAttributify(),
42
+ presetIcons({
43
+ scale: 1.2,
44
+ }),
45
+ ],
46
+ }),
47
+ IncludesPlugin(),
48
+ ],
49
+ })
50
+
51
+ function IncludesPlugin(): Plugin {
52
+ return {
53
+ name: 'include-plugin',
54
+ enforce: 'pre',
55
+ transform(code, id) {
56
+ let changed = false
57
+ code = code.replace(/\[@@include\]\((.*?)\)/, (_, url) => {
58
+ changed = true
59
+ const full = resolve(id, url)
60
+ return fs.readFileSync(full, 'utf-8')
61
+ })
62
+ if (changed)
63
+ return code
64
+ },
65
+ }
66
+ }