vitrify 0.2.5 → 0.5.0
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 +2 -2
- package/dist/app-urls.js +1 -2
- package/dist/bin/build.js +9 -51
- package/dist/bin/cli.js +31 -9
- package/dist/bin/dev.js +72 -70
- package/dist/frameworks/vue/fastify-csr-plugin.js +38 -0
- package/dist/frameworks/vue/fastify-ssr-plugin.js +83 -25
- package/dist/frameworks/vue/prerender.js +3 -3
- package/dist/frameworks/vue/server.js +10 -11
- package/dist/helpers/collect-css-ssr.js +61 -0
- package/dist/helpers/logger.js +0 -72
- package/dist/index.js +310 -130
- package/dist/plugins/quasar.js +34 -111
- package/dist/types/bin/build.d.ts +2 -2
- package/dist/types/bin/dev.d.ts +42 -4
- package/dist/types/frameworks/vue/fastify-csr-plugin.d.ts +17 -0
- package/dist/types/frameworks/vue/fastify-ssr-plugin.d.ts +6 -3
- package/dist/types/frameworks/vue/prerender.d.ts +3 -3
- package/dist/types/frameworks/vue/server.d.ts +10 -5
- package/dist/types/helpers/collect-css-ssr.d.ts +14 -0
- package/dist/types/helpers/logger.d.ts +0 -19
- package/dist/types/helpers/routes.d.ts +1 -1
- package/dist/types/index.d.ts +4 -2
- package/dist/types/plugins/index.d.ts +1 -1
- package/dist/types/vitrify-config.d.ts +33 -17
- package/package.json +33 -32
- package/src/node/app-urls.ts +1 -2
- package/src/node/bin/build.ts +11 -57
- package/src/node/bin/cli.ts +38 -10
- package/src/node/bin/dev.ts +106 -80
- package/src/node/bin/test.ts +0 -3
- package/src/node/frameworks/vue/fastify-csr-plugin.ts +72 -0
- package/src/node/frameworks/vue/fastify-ssr-plugin.ts +99 -28
- package/src/node/frameworks/vue/prerender.ts +5 -5
- package/src/node/frameworks/vue/server.ts +24 -17
- package/src/node/helpers/collect-css-ssr.ts +85 -0
- package/src/node/helpers/logger.ts +0 -87
- package/src/node/index.ts +353 -146
- package/src/node/plugins/index.ts +1 -1
- package/src/node/plugins/quasar.ts +39 -116
- package/src/node/vitrify-config.ts +44 -17
- package/src/vite/fastify/entry.ts +11 -0
- package/src/vite/fastify/server.ts +12 -0
- package/src/vite/vue/csr/app.ts +25 -0
- package/src/vite/vue/csr/fastify-csr-plugin.ts +3 -0
- package/src/vite/vue/csr/server.ts +8 -0
- package/src/vite/vue/index.html +1 -0
- package/src/vite/vue/main.ts +5 -20
- package/src/vite/vue/ssr/app.ts +25 -0
- package/src/vite/vue/ssr/entry-server.ts +13 -1
- package/src/vite/vue/ssr/fastify-ssr-plugin.ts +2 -118
- package/src/vite/vue/ssr/prerender.ts +2 -2
- package/src/vite/vue/ssr/server.ts +24 -15
- package/src/node/helpers/ssr.ts.bak +0 -52
|
@@ -3,11 +3,11 @@ import type {
|
|
|
3
3
|
FastifyRequest,
|
|
4
4
|
FastifyReply
|
|
5
5
|
} from 'fastify'
|
|
6
|
-
import fastifyStatic from 'fastify
|
|
6
|
+
import fastifyStatic from '@fastify/static'
|
|
7
7
|
import { readFileSync } from 'fs'
|
|
8
|
-
|
|
8
|
+
import type { OnRenderedHook } from '../../vitrify-config.js'
|
|
9
|
+
import { componentsModules, collectCss } from '../../helpers/collect-css-ssr.js'
|
|
9
10
|
import type { ViteDevServer } from 'vite'
|
|
10
|
-
import type { SsrFunction } from '../../vitrify-config.js'
|
|
11
11
|
|
|
12
12
|
export interface FastifySsrOptions {
|
|
13
13
|
baseUrl?: string
|
|
@@ -15,11 +15,14 @@ export interface FastifySsrOptions {
|
|
|
15
15
|
req: FastifyRequest,
|
|
16
16
|
res: FastifyReply
|
|
17
17
|
) => Promise<Record<string, unknown>>
|
|
18
|
+
vitrifyDir?: URL
|
|
18
19
|
vite?: ViteDevServer
|
|
19
|
-
|
|
20
|
+
// frameworkDir?: URL
|
|
20
21
|
appDir?: URL
|
|
22
|
+
publicDir?: URL
|
|
21
23
|
productName?: string
|
|
22
|
-
|
|
24
|
+
onRendered?: OnRenderedHook[]
|
|
25
|
+
mode?: string
|
|
23
26
|
}
|
|
24
27
|
|
|
25
28
|
const fastifySsrPlugin: FastifyPluginCallback<FastifySsrOptions> = async (
|
|
@@ -27,29 +30,89 @@ const fastifySsrPlugin: FastifyPluginCallback<FastifySsrOptions> = async (
|
|
|
27
30
|
options,
|
|
28
31
|
done
|
|
29
32
|
) => {
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
33
|
+
options.vitrifyDir =
|
|
34
|
+
options.vitrifyDir || (await import('vitrify')).vitrifyDir
|
|
35
|
+
const frameworkDir = new URL('src/vite/vue/', options.vitrifyDir)
|
|
36
|
+
options.baseUrl = options.baseUrl || '/'
|
|
37
|
+
options.mode = options.mode || process.env.MODE || import.meta.env.MODE
|
|
38
|
+
options.appDir = options.appDir || new URL('../../..', import.meta.url)
|
|
35
39
|
|
|
36
|
-
|
|
40
|
+
if (
|
|
41
|
+
options.baseUrl.charAt(options.baseUrl.length - 1) !== '/' ||
|
|
42
|
+
options.baseUrl.charAt(0) !== '/'
|
|
43
|
+
)
|
|
44
|
+
throw new Error('baseUrl should start and end with a /')
|
|
45
|
+
if (options.mode === 'development') {
|
|
46
|
+
// if (!options.vitrifyDir)
|
|
47
|
+
// throw new Error('Option vitrifyDir cannot be undefined')
|
|
48
|
+
// if (!options.vite) throw new Error('Option vite cannot be undefined')
|
|
49
|
+
// const { resolve } = await import('import-meta-resolve')
|
|
50
|
+
// const cliDir = new URL('../', await resolve('vitrify', import.meta.url))
|
|
51
|
+
options.appDir = options.appDir || new URL('../../..', import.meta.url)
|
|
52
|
+
|
|
53
|
+
const { createVitrifyDevServer } = await import('vitrify/dev')
|
|
54
|
+
const vite = await createVitrifyDevServer({
|
|
55
|
+
appDir: options.appDir,
|
|
56
|
+
ssr: 'ssr',
|
|
57
|
+
framework: 'vue',
|
|
58
|
+
base: options.baseUrl
|
|
59
|
+
})
|
|
60
|
+
// const { createServer, searchForWorkspaceRoot } = await import('vite')
|
|
61
|
+
// const { baseConfig } = await import('vitrify')
|
|
62
|
+
// const cliDir = options.vitrifyDir
|
|
63
|
+
// const config = await baseConfig({
|
|
64
|
+
// ssr: 'server',
|
|
65
|
+
// command: 'dev',
|
|
66
|
+
// mode: 'development',
|
|
67
|
+
// appDir: options.appDir,
|
|
68
|
+
// publicDir: options.publicDir || new URL('public', options.appDir)
|
|
69
|
+
// })
|
|
70
|
+
|
|
71
|
+
// config.server = {
|
|
72
|
+
// middlewareMode: true,
|
|
73
|
+
// fs: {
|
|
74
|
+
// allow: [
|
|
75
|
+
// searchForWorkspaceRoot(process.cwd()),
|
|
76
|
+
// searchForWorkspaceRoot(options.appDir.pathname),
|
|
77
|
+
// searchForWorkspaceRoot(cliDir.pathname)
|
|
78
|
+
// // appDir.pathname,
|
|
79
|
+
// ]
|
|
80
|
+
// },
|
|
81
|
+
// watch: {
|
|
82
|
+
// // During tests we edit the files too fast and sometimes chokidar
|
|
83
|
+
// // misses change events, so enforce polling for consistency
|
|
84
|
+
// usePolling: true,
|
|
85
|
+
// interval: 100
|
|
86
|
+
// }
|
|
87
|
+
// }
|
|
88
|
+
// const vite = await createServer({
|
|
89
|
+
// configFile: false,
|
|
90
|
+
// ...config
|
|
91
|
+
// })
|
|
92
|
+
|
|
93
|
+
console.log('Dev mode')
|
|
94
|
+
if (!('use' in fastify)) {
|
|
95
|
+
const middie = (await import('@fastify/middie')).default
|
|
96
|
+
await fastify.register(middie)
|
|
97
|
+
}
|
|
98
|
+
fastify.use(vite.middlewares)
|
|
99
|
+
|
|
100
|
+
fastify.get(`${options.baseUrl}*`, async (req, res) => {
|
|
37
101
|
try {
|
|
38
|
-
|
|
39
|
-
const url = req.raw.url
|
|
102
|
+
const url = req.raw.url?.replace(options.baseUrl!, '/')
|
|
40
103
|
const ssrContext = {
|
|
41
104
|
req,
|
|
42
105
|
res
|
|
43
106
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
new URL('index.html', options.cliDir)
|
|
107
|
+
|
|
108
|
+
let template = readFileSync(
|
|
109
|
+
new URL('index.html', frameworkDir)
|
|
48
110
|
).toString()
|
|
49
111
|
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
const
|
|
112
|
+
template = await vite.transformIndexHtml(url!, template)
|
|
113
|
+
|
|
114
|
+
const entryUrl = new URL('ssr/entry-server.ts', frameworkDir).pathname
|
|
115
|
+
const render = (await vite!.ssrLoadModule(entryUrl)).render
|
|
53
116
|
let manifest
|
|
54
117
|
// TODO: https://github.com/vitejs/vite/issues/2282
|
|
55
118
|
try {
|
|
@@ -58,11 +121,21 @@ const fastifySsrPlugin: FastifyPluginCallback<FastifySsrOptions> = async (
|
|
|
58
121
|
manifest = {}
|
|
59
122
|
}
|
|
60
123
|
|
|
124
|
+
const cssModules = [entryUrl]
|
|
125
|
+
// // @ts-ignore
|
|
126
|
+
// if (options.vite?.config.vitrify!.globalCss)
|
|
127
|
+
// cssModules.push(...options.vite?.config.vitrify.globalCss)
|
|
128
|
+
const matchedModules = componentsModules(cssModules, vite!)
|
|
129
|
+
const css = collectCss({
|
|
130
|
+
mods: matchedModules
|
|
131
|
+
})
|
|
132
|
+
|
|
61
133
|
const [appHtml, preloadLinks] = await render(url, manifest, ssrContext)
|
|
62
134
|
const html = template
|
|
63
135
|
.replace(`<!--preload-links-->`, preloadLinks)
|
|
64
136
|
.replace(`<!--app-html-->`, appHtml)
|
|
65
137
|
.replace('<!--product-name-->', options.productName || 'Product name')
|
|
138
|
+
.replace('<!--dev-ssr-css-->', css)
|
|
66
139
|
|
|
67
140
|
res.code(200)
|
|
68
141
|
res.type('text/html')
|
|
@@ -70,13 +143,13 @@ const fastifySsrPlugin: FastifyPluginCallback<FastifySsrOptions> = async (
|
|
|
70
143
|
// res.status(200).set({ 'Content-Type': 'text/html' }).end(html)
|
|
71
144
|
} catch (e: any) {
|
|
72
145
|
console.error(e.stack)
|
|
73
|
-
|
|
146
|
+
vite && vite.ssrFixStacktrace(e)
|
|
74
147
|
res.code(500)
|
|
75
148
|
res.send(e.stack)
|
|
76
149
|
}
|
|
77
150
|
})
|
|
78
151
|
} else {
|
|
79
|
-
options.
|
|
152
|
+
options.appDir = options.appDir || new URL('../../..', import.meta.url)
|
|
80
153
|
fastify.register(fastifyStatic, {
|
|
81
154
|
root: new URL('./dist/ssr/client', options.appDir).pathname,
|
|
82
155
|
wildcard: false,
|
|
@@ -85,7 +158,7 @@ const fastifySsrPlugin: FastifyPluginCallback<FastifySsrOptions> = async (
|
|
|
85
158
|
})
|
|
86
159
|
|
|
87
160
|
fastify.get(`${options.baseUrl}*`, async (req, res) => {
|
|
88
|
-
const url = req.raw.url
|
|
161
|
+
const url = req.raw.url?.replace(options.baseUrl!, '/')
|
|
89
162
|
const provide = options.provide ? await options.provide(req, res) : {}
|
|
90
163
|
const ssrContext: Record<string, any> = {
|
|
91
164
|
req,
|
|
@@ -93,9 +166,6 @@ const fastifySsrPlugin: FastifyPluginCallback<FastifySsrOptions> = async (
|
|
|
93
166
|
provide
|
|
94
167
|
}
|
|
95
168
|
|
|
96
|
-
// template = readFileSync(new URL('../client/index.html', import.meta.url).pathname).toString()
|
|
97
|
-
// manifest = JSON.parse(readFileSync(new URL('../client/ssr-manifest.json', import.meta.url)).toString())
|
|
98
|
-
// render = (await import(new URL('./entry-server.mjs', import.meta.url).pathname)).render
|
|
99
169
|
const template = readFileSync(
|
|
100
170
|
new URL('./dist/ssr/client/index.html', options.appDir).pathname
|
|
101
171
|
).toString()
|
|
@@ -119,8 +189,8 @@ const fastifySsrPlugin: FastifyPluginCallback<FastifySsrOptions> = async (
|
|
|
119
189
|
.replace(`<!--preload-links-->`, preloadLinks)
|
|
120
190
|
.replace(`<!--app-html-->`, appHtml)
|
|
121
191
|
|
|
122
|
-
if (options.
|
|
123
|
-
for (const ssrFunction of options.
|
|
192
|
+
if (options.onRendered?.length) {
|
|
193
|
+
for (const ssrFunction of options.onRendered) {
|
|
124
194
|
html = ssrFunction(html, ssrContext)
|
|
125
195
|
}
|
|
126
196
|
}
|
|
@@ -135,3 +205,4 @@ const fastifySsrPlugin: FastifyPluginCallback<FastifySsrOptions> = async (
|
|
|
135
205
|
}
|
|
136
206
|
|
|
137
207
|
export { fastifySsrPlugin }
|
|
208
|
+
export type FastifySsrPlugin = typeof fastifySsrPlugin
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
import { promises as fs } from 'fs'
|
|
2
2
|
import { routesToPaths } from '../../helpers/routes.js'
|
|
3
|
-
import type {
|
|
3
|
+
import type { OnRenderedHook } from '../../vitrify-config.js'
|
|
4
4
|
|
|
5
5
|
export const prerender = async ({
|
|
6
6
|
outDir,
|
|
7
7
|
templatePath,
|
|
8
8
|
manifestPath,
|
|
9
9
|
entryServerPath,
|
|
10
|
-
|
|
10
|
+
onRenderedHooks
|
|
11
11
|
}: {
|
|
12
12
|
outDir: string
|
|
13
13
|
templatePath: string
|
|
14
14
|
manifestPath: string
|
|
15
15
|
entryServerPath: string
|
|
16
|
-
|
|
16
|
+
onRenderedHooks: OnRenderedHook[]
|
|
17
17
|
}) => {
|
|
18
18
|
const promises = []
|
|
19
19
|
const template = (await fs.readFile(templatePath)).toString()
|
|
@@ -37,8 +37,8 @@ export const prerender = async ({
|
|
|
37
37
|
.replace(`<!--preload-links-->`, preloadLinks)
|
|
38
38
|
.replace(`<!--app-html-->`, appHtml)
|
|
39
39
|
|
|
40
|
-
if (
|
|
41
|
-
for (const ssrFunction of
|
|
40
|
+
if (onRenderedHooks?.length) {
|
|
41
|
+
for (const ssrFunction of onRenderedHooks) {
|
|
42
42
|
html = ssrFunction(html, ssrContext)
|
|
43
43
|
}
|
|
44
44
|
}
|
|
@@ -1,38 +1,45 @@
|
|
|
1
1
|
import type { FastifyInstance } from 'fastify'
|
|
2
2
|
import fastify from 'fastify'
|
|
3
|
-
import type {
|
|
4
|
-
|
|
5
|
-
import {
|
|
6
|
-
|
|
3
|
+
import type { ViteDevServer } from 'vite'
|
|
4
|
+
import { getCliDir, getCliViteDir } from '../../app-urls.js'
|
|
5
|
+
import type { OnRenderedHook, OnSetupFile } from '../../vitrify-config.js'
|
|
6
|
+
import type { FastifyCsrPlugin } from './fastify-csr-plugin.js'
|
|
7
|
+
import type { FastifySsrPlugin } from './fastify-ssr-plugin.js'
|
|
7
8
|
|
|
8
9
|
export const createApp = ({
|
|
9
|
-
|
|
10
|
+
onSetup,
|
|
10
11
|
appDir,
|
|
11
12
|
baseUrl,
|
|
12
|
-
|
|
13
|
+
onRendered,
|
|
14
|
+
fastifyPlugin,
|
|
15
|
+
vitrifyDir,
|
|
16
|
+
mode
|
|
13
17
|
}: {
|
|
14
|
-
|
|
18
|
+
onSetup: OnSetupFile[]
|
|
15
19
|
appDir: URL
|
|
16
20
|
baseUrl?: string
|
|
17
|
-
|
|
21
|
+
onRendered?: OnRenderedHook[]
|
|
22
|
+
fastifyPlugin: FastifySsrPlugin | FastifyCsrPlugin
|
|
23
|
+
vitrifyDir?: URL
|
|
24
|
+
mode: string
|
|
18
25
|
}) => {
|
|
19
26
|
const app = fastify({
|
|
20
27
|
logger: true
|
|
21
28
|
})
|
|
22
29
|
|
|
23
|
-
app.register(
|
|
30
|
+
app.register(fastifyPlugin, {
|
|
24
31
|
baseUrl,
|
|
25
32
|
appDir,
|
|
26
|
-
|
|
33
|
+
onRendered,
|
|
34
|
+
vitrifyDir,
|
|
35
|
+
mode
|
|
27
36
|
})
|
|
28
37
|
|
|
29
|
-
|
|
38
|
+
// if (onSetup?.length) {
|
|
39
|
+
// for (const setup of onSetup) {
|
|
40
|
+
// setup(app)
|
|
41
|
+
// }
|
|
42
|
+
// }
|
|
30
43
|
|
|
31
44
|
return app
|
|
32
45
|
}
|
|
33
|
-
|
|
34
|
-
// const app = createApp({
|
|
35
|
-
// setup
|
|
36
|
-
// })
|
|
37
|
-
|
|
38
|
-
// app.listen(process.env.PORT || 3000, process.env.HOST || '127.0.0.1')
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
// collect-css-ssr.ts
|
|
2
|
+
import type { ViteDevServer, ModuleNode, UpdatePayload } from 'vite'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Collect SSR CSS for Vite
|
|
6
|
+
*/
|
|
7
|
+
export const componentsModules = (
|
|
8
|
+
components: string[],
|
|
9
|
+
vite: ViteDevServer
|
|
10
|
+
) => {
|
|
11
|
+
const matchedModules = new Set<ModuleNode>()
|
|
12
|
+
components.forEach((component) => {
|
|
13
|
+
const modules = vite.moduleGraph.getModulesByFile(component)
|
|
14
|
+
modules?.forEach((mod) => matchedModules.add(mod))
|
|
15
|
+
})
|
|
16
|
+
return matchedModules
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export const collectCss = ({
|
|
20
|
+
mods,
|
|
21
|
+
styles = new Map<string, string>(),
|
|
22
|
+
checkedComponents = new Set()
|
|
23
|
+
}: {
|
|
24
|
+
mods: Set<ModuleNode>
|
|
25
|
+
styles?: Map<string, string>
|
|
26
|
+
checkedComponents?: Set<unknown>
|
|
27
|
+
}) => {
|
|
28
|
+
for (const mod of mods) {
|
|
29
|
+
if (
|
|
30
|
+
(mod.file?.endsWith('.scss') ||
|
|
31
|
+
mod.file?.endsWith('.css') ||
|
|
32
|
+
mod.id?.includes('vue&type=style')) &&
|
|
33
|
+
mod.ssrModule
|
|
34
|
+
) {
|
|
35
|
+
styles.set(mod.url, mod.ssrModule.default)
|
|
36
|
+
}
|
|
37
|
+
if (mod.importedModules.size > 0 && !checkedComponents.has(mod.id)) {
|
|
38
|
+
checkedComponents.add(mod.id)
|
|
39
|
+
collectCss({
|
|
40
|
+
mods: mod.importedModules,
|
|
41
|
+
styles,
|
|
42
|
+
checkedComponents
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
let result = ''
|
|
47
|
+
styles.forEach((content, id) => {
|
|
48
|
+
const styleTag = `<style type="text/css" vite-module-id="${hashCode(
|
|
49
|
+
id
|
|
50
|
+
)}">${content}</style>`
|
|
51
|
+
result = result.concat(styleTag)
|
|
52
|
+
})
|
|
53
|
+
return result
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Client listener to detect updated modules through HMR, and remove the initial styled attached to the head
|
|
58
|
+
*/
|
|
59
|
+
export const removeCssHotReloaded = () => {
|
|
60
|
+
if (import.meta.hot) {
|
|
61
|
+
import.meta.hot.on('vite:beforeUpdate', (module: UpdatePayload) => {
|
|
62
|
+
module.updates.forEach((update) => {
|
|
63
|
+
const moduleStyle = document.querySelector(
|
|
64
|
+
`[vite-module-id="${hashCode(update.acceptedPath)}"]`
|
|
65
|
+
)
|
|
66
|
+
if (moduleStyle) {
|
|
67
|
+
moduleStyle.remove()
|
|
68
|
+
}
|
|
69
|
+
})
|
|
70
|
+
})
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const hashCode = (moduleId: string) => {
|
|
75
|
+
let hash = 0,
|
|
76
|
+
i,
|
|
77
|
+
chr
|
|
78
|
+
if (moduleId.length === 0) return hash
|
|
79
|
+
for (i = 0; i < moduleId.length; i++) {
|
|
80
|
+
chr = moduleId.charCodeAt(i)
|
|
81
|
+
hash = (hash << 5) - hash + chr
|
|
82
|
+
hash |= 0 // Convert to 32bit integer
|
|
83
|
+
}
|
|
84
|
+
return hash
|
|
85
|
+
}
|
|
@@ -1,98 +1,11 @@
|
|
|
1
1
|
// https://github.com/quasarframework/quasar/blob/dev/app/lib/helpers/logger.js
|
|
2
2
|
import chalk from 'chalk'
|
|
3
|
-
const { bgGreen, green, inverse, bgRed, red, bgYellow, yellow } = chalk
|
|
4
|
-
import readline from 'readline'
|
|
5
3
|
import type { AddressInfo, Server } from 'net'
|
|
6
4
|
import type { ResolvedConfig, Logger } from 'vite'
|
|
7
5
|
import os from 'os'
|
|
8
6
|
import type { Hostname } from '../helpers/utils.js'
|
|
9
7
|
import { resolveHostname } from '../helpers/utils.js'
|
|
10
8
|
|
|
11
|
-
/**
|
|
12
|
-
* Main approach - App CLI related
|
|
13
|
-
*/
|
|
14
|
-
|
|
15
|
-
const dot = '•'
|
|
16
|
-
const banner = 'App ' + dot
|
|
17
|
-
const greenBanner = green(banner)
|
|
18
|
-
const redBanner = red(banner)
|
|
19
|
-
const yellowBanner = yellow(banner)
|
|
20
|
-
|
|
21
|
-
export const clearConsole = process.stdout.isTTY
|
|
22
|
-
? () => {
|
|
23
|
-
// Fill screen with blank lines. Then move to 0 (beginning of visible part) and clear it
|
|
24
|
-
const blank = '\n'.repeat(process.stdout.rows)
|
|
25
|
-
console.log(blank)
|
|
26
|
-
readline.cursorTo(process.stdout, 0, 0)
|
|
27
|
-
readline.clearScreenDown(process.stdout)
|
|
28
|
-
}
|
|
29
|
-
: () => {}
|
|
30
|
-
|
|
31
|
-
export const log = function (msg?: string) {
|
|
32
|
-
console.log(msg ? ` ${greenBanner} ${msg}` : '')
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const warn = function (msg?: string, pill?: string) {
|
|
36
|
-
if (msg !== void 0) {
|
|
37
|
-
const pillBanner = pill !== void 0 ? bgYellow.black('', pill, '') + ' ' : ''
|
|
38
|
-
|
|
39
|
-
console.warn(` ${yellowBanner} ⚠️ ${pillBanner}${msg}`)
|
|
40
|
-
} else {
|
|
41
|
-
console.warn()
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
export const fatal = function (msg?: string, pill?: string) {
|
|
46
|
-
if (msg !== void 0) {
|
|
47
|
-
const pillBanner = pill !== void 0 ? errorPill(pill) + ' ' : ''
|
|
48
|
-
|
|
49
|
-
console.error(`\n ${redBanner} ⚠️ ${pillBanner}${msg}\n`)
|
|
50
|
-
} else {
|
|
51
|
-
console.error()
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
process.exit(1)
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Extended approach - Compilation status & pills
|
|
59
|
-
*/
|
|
60
|
-
|
|
61
|
-
export const successPill = (msg?: string) => bgGreen.black('', msg, '')
|
|
62
|
-
export const infoPill = (msg?: string) => inverse('', msg, '')
|
|
63
|
-
export const errorPill = (msg?: string) => bgRed.white('', msg, '')
|
|
64
|
-
export const warningPill = (msg?: string) => bgYellow.black('', msg, '')
|
|
65
|
-
|
|
66
|
-
export const success = function (msg?: string, title = 'SUCCESS') {
|
|
67
|
-
console.log(` ${greenBanner} ${successPill(title)} ${green(dot + ' ' + msg)}`)
|
|
68
|
-
}
|
|
69
|
-
export const getSuccess = function (msg?: string, title?: string) {
|
|
70
|
-
return ` ${greenBanner} ${successPill(title)} ${green(dot + ' ' + msg)}`
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
export const info = function (msg?: string, title = 'INFO') {
|
|
74
|
-
console.log(` ${greenBanner} ${infoPill(title)} ${green(dot)} ${msg}`)
|
|
75
|
-
}
|
|
76
|
-
export const getInfo = function (msg?: string, title?: string) {
|
|
77
|
-
return ` ${greenBanner} ${infoPill(title)} ${green(dot)} ${msg}`
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
export const error = function (msg?: string, title = 'ERROR') {
|
|
81
|
-
console.log(` ${redBanner} ${errorPill(title)} ${red(dot + ' ' + msg)}`)
|
|
82
|
-
}
|
|
83
|
-
export const getError = function (msg?: string, title = 'ERROR') {
|
|
84
|
-
return ` ${redBanner} ${errorPill(title)} ${red(dot + ' ' + msg)}`
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
export const warning = function (msg?: string, title = 'WARNING') {
|
|
88
|
-
console.log(
|
|
89
|
-
` ${yellowBanner} ${warningPill(title)} ${yellow(dot + ' ' + msg)}`
|
|
90
|
-
)
|
|
91
|
-
}
|
|
92
|
-
export const getWarning = function (msg?: string, title = 'WARNING') {
|
|
93
|
-
return ` ${yellowBanner} ${warningPill(title)} ${yellow(dot + ' ' + msg)}`
|
|
94
|
-
}
|
|
95
|
-
|
|
96
9
|
export function printHttpServerUrls(
|
|
97
10
|
server: Server,
|
|
98
11
|
config: ResolvedConfig
|