-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathindex.ts
219 lines (188 loc) · 6.82 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
import * as fs from 'fs'
import * as url from 'url'
import * as path from 'path'
import pkg from 'fs-extra'
const { copyFileSync, unlinkSync, existsSync, mkdirSync, emptyDirSync } = pkg
import * as esbuild from 'esbuild'
const __dirname = url.fileURLToPath(new URL('.', import.meta.url))
let STUB = 1
/**
* @typedef {Object} SiteProps
* @property {string} server_directory location of files for the SSR server
* @property {string} static_directory location of static page files
* @property {string} prerendered_directory location of prerendered page files
*/
STUB = 1
type SiteProps = {
server_directory: string
static_directory: string
prerendered_directory: string
}
/**
* Prepare SvelteKit SSR server files for deployment to AWS services.
*
* To determine the URL request origin the server uses the following hierarchy:
* + The ORIGIN environment variable
* + The value of the 'X-Forwarded-Host' header
* + The domain name within the request event
*
* The origin value is important to prevent CORS errors.
*
* @param {any} builder The SvelteKit provided [Builder]{@link https://kit.svelte.dev/docs/types#public-types-builder} object
* @param {string} artifactPath The path where to place to SvelteKit files
* @param {any} esbuildOptions Options to pass to esbuild
* @param {boolean} streaming Use Lambda response streaming
* @returns {Promise<SiteProps>}
*/
export async function buildServer(
builder: any,
artifactPath: string = 'build',
esbuildOptions: any = {},
streaming: boolean = false
): Promise<SiteProps> {
emptyDirSync(artifactPath)
const static_directory = path.resolve(artifactPath, 'assets')
if (!existsSync(static_directory)) {
mkdirSync(static_directory, { recursive: true })
}
const prerendered_directory = path.resolve(artifactPath, 'prerendered')
if (!existsSync(prerendered_directory)) {
mkdirSync(prerendered_directory, { recursive: true })
}
const server_directory = path.resolve(artifactPath, 'server')
if (!existsSync(server_directory)) {
mkdirSync(server_directory, { recursive: true })
}
builder.log.minor('Copying asset files.')
const clientFiles = await builder.writeClient(static_directory)
builder.log.minor('Copying server files.')
await builder.writeServer(artifactPath)
let serverlessPath = `${__dirname}/lambda/serverless.js`
if (streaming) {
serverlessPath = `${__dirname}/lambda/serverless_streaming.js`
}
copyFileSync(serverlessPath, `${server_directory}/_index.js`)
copyFileSync(`${__dirname}/lambda/shims.js`, `${server_directory}/shims.js`)
builder.log.minor('Building AWS Lambda server function.')
esbuild.buildSync({
entryPoints: [`${server_directory}/_index.js`],
outfile: `${server_directory}/index.js`,
inject: [path.join(`${server_directory}/shims.js`)],
external: ['node:*', ...(esbuildOptions?.external ?? [])],
format: esbuildOptions?.format ?? 'cjs',
banner: esbuildOptions?.banner ?? {},
bundle: true,
platform: 'node',
target: esbuildOptions?.target ?? 'node18',
})
builder.log.minor('Prerendering static pages.')
const prerenderedFiles = await builder.writePrerendered(prerendered_directory)
builder.log.minor('Cleanup project.')
unlinkSync(`${server_directory}/_index.js`)
unlinkSync(`${artifactPath}/index.js`)
return {
server_directory,
static_directory,
prerendered_directory,
}
}
/**
* Prepare options handler for deployment to AWS services
* @param {any} builder The SvelteKit provided [Builder]{@link https://kit.svelte.dev/docs/types#public-types-builder} object
* @param {string} artifactPath The path where to place to SvelteKit files
* @returns {Promise<string>} Location of files for the options handler
*/
export async function buildOptions(
builder: any,
artifactPath: string = 'build'
): Promise<string> {
const options_directory = path.resolve(artifactPath, 'options')
if (!existsSync(options_directory)) {
mkdirSync(options_directory, { recursive: true })
}
builder.log.minor('Building router')
copyFileSync(
`${__dirname}/lambda/options.js`,
`${options_directory}/_options.js`
)
esbuild.buildSync({
entryPoints: [`${options_directory}/_options.js`],
outfile: `${options_directory}/index.js`,
external: ['node:*'],
format: 'cjs',
bundle: true,
platform: 'node',
})
builder.log.minor('Cleanup project.')
unlinkSync(`${options_directory}/_options.js`)
return options_directory
}
/**
* Prepare lambda@edge origin router for deployment to AWS services
*
* Note that this function will forward the original Host header as
* 'X-Forwarded-Host' to the lambda URLs.
*
* @param {any} builder The SvelteKit provided [Builder]{@link https://kit.svelte.dev/docs/types#public-types-builder} object
* @param {string} static_directory location of static page files
* @param {string} prerendered_directory location of prerendered page files
* @param {string} serverURL function URL for the server lambda
* @param {string} optionsURL function URL for the options handler lambda
* @param {string} artifactPath The path where to place to SvelteKit files
* @returns {Promise<string>} Location of files for the origin router
*/
export async function buildRouter(
builder: any,
static_directory: string,
prerendered_directory: string,
serverURL: string,
optionsURL: string,
artifactPath: string = 'build'
): Promise<string> {
const edge_directory = path.resolve(artifactPath, 'edge')
if (!existsSync(edge_directory)) {
mkdirSync(edge_directory, { recursive: true })
}
builder.log.minor('Building router')
copyFileSync(`${__dirname}/lambda/router.js`, `${edge_directory}/_router.js`)
let files = JSON.stringify([
...getAllFiles(static_directory),
...getAllFiles(prerendered_directory),
])
fs.writeFileSync(`${edge_directory}/static.js`, `export default ${files}`)
esbuild.buildSync({
entryPoints: [`${edge_directory}/_router.js`],
outfile: `${edge_directory}/router.js`,
define: {
SERVER_URL: `"${serverURL}"`,
OPTIONS_URL: `"${optionsURL}"`,
},
external: ['node:*', '@aws-sdk'],
format: 'cjs',
bundle: true,
platform: 'node',
})
builder.log.minor('Cleanup project.')
unlinkSync(`${edge_directory}/_router.js`)
return edge_directory
}
const getAllFiles = function (
dirPath: string,
basePath?: string,
arrayOfFiles?: string[]
) {
const files = fs.readdirSync(dirPath)
arrayOfFiles = arrayOfFiles || []
basePath = basePath || dirPath
files.forEach(function (file) {
const fileOrDir = path.join(dirPath, file)
if (fs.statSync(fileOrDir).isDirectory()) {
arrayOfFiles = getAllFiles(fileOrDir, basePath, arrayOfFiles)
} else {
const uriLocal = path.join(path.sep, dirPath.replace(basePath!, ''), file)
const uriPosix = uriLocal.split(path.sep).join(path.posix.sep)
arrayOfFiles!.push(uriPosix)
}
})
return arrayOfFiles
}