1 | import fs from 'fs-extra'
|
2 | import path from 'path'
|
3 | import mime from 'mime-types'
|
4 |
|
5 | import * as logger from './log'
|
6 | import { timer } from './timer'
|
7 | import { getRouteParams } from './getRouteParams'
|
8 | import { normalizeResponse } from './normalizeResponse'
|
9 | import { builtStaticFiles } from './builtStaticFiles'
|
10 | import { removeBuiltStaticFile } from './removeBuiltStaticFile'
|
11 | import { Presta } from './types'
|
12 |
|
13 | export function pathnameToFile(pathname: string, ext = 'html') {
|
14 | return !!path.extname(pathname)
|
15 | ? pathname
|
16 | : ext === 'html'
|
17 | ? `${pathname}/index.html`
|
18 | : `${pathname}.${ext}`
|
19 | }
|
20 |
|
21 | export function renderStaticEntries(entries: string[], config: Presta): Promise<{ allGeneratedFiles: string[] }> {
|
22 | return new Promise(async (y, n) => {
|
23 | logger.debug({
|
24 | label: 'debug',
|
25 | message: `rendering ${JSON.stringify(entries)}`,
|
26 | })
|
27 |
|
28 | const allGeneratedFiles: string[] = []
|
29 |
|
30 | for (const entry of entries) {
|
31 | const location = entry.replace(config.cwd, '')
|
32 |
|
33 | try {
|
34 | delete require.cache[entry]
|
35 |
|
36 | const file = require(entry)
|
37 | const paths = await file.getStaticPaths()
|
38 |
|
39 | const prevFiles = (builtStaticFiles[entry] = builtStaticFiles[entry] || [])
|
40 | const nextFiles: string[] = []
|
41 |
|
42 | if (!paths || !paths.length) {
|
43 | logger.warn({
|
44 | label: 'paths',
|
45 | message: `${location} - no paths to render`,
|
46 | })
|
47 |
|
48 | prevFiles.forEach((file) => removeBuiltStaticFile(file, config))
|
49 |
|
50 | continue
|
51 | }
|
52 |
|
53 | for (const url of paths) {
|
54 | const time = timer()
|
55 | const event = {
|
56 | path: url,
|
57 | routeParameters: file.route ? getRouteParams(url, file.route) : {},
|
58 | }
|
59 |
|
60 | const response = normalizeResponse(await file.handler(event, {}))
|
61 | const type = response.headers ? response.headers['Content-Type'] : ''
|
62 | const ext = type ? mime.extension(type as string) || 'html' : 'html'
|
63 | const filename = pathnameToFile(url, ext)
|
64 |
|
65 | allGeneratedFiles.push(filename)
|
66 | nextFiles.push(filename)
|
67 |
|
68 | fs.outputFileSync(path.join(config.staticOutputDir, filename), response.body, 'utf-8')
|
69 |
|
70 | logger.info({
|
71 | label: 'built',
|
72 | message: url,
|
73 | duration: time(),
|
74 | })
|
75 | }
|
76 |
|
77 |
|
78 | for (const file of prevFiles) {
|
79 | if (!nextFiles.includes(file)) {
|
80 | removeBuiltStaticFile(file, config)
|
81 | }
|
82 | }
|
83 |
|
84 | builtStaticFiles[entry] = nextFiles
|
85 | } catch (e) {
|
86 | if (config.env === 'development') {
|
87 | logger.error({
|
88 | label: 'error',
|
89 | message: 'errors detected, pausing...',
|
90 | error: e as Error,
|
91 | })
|
92 |
|
93 | y({ allGeneratedFiles })
|
94 | } else {
|
95 | logger.error({
|
96 | label: 'error',
|
97 | error: e as Error,
|
98 | })
|
99 |
|
100 | n(e)
|
101 | }
|
102 |
|
103 |
|
104 | break
|
105 | }
|
106 | }
|
107 |
|
108 |
|
109 |
|
110 |
|
111 | y({ allGeneratedFiles })
|
112 | })
|
113 | }
|