|
1 | 1 | import {writeFileSync} from 'node:fs';
|
2 |
| -import {join} from 'node:path'; |
| 2 | +import {join, posix} from 'node:path'; |
3 | 3 | import {fileURLToPath} from 'node:url';
|
4 |
| -import esbuild from 'esbuild'; |
5 | 4 | import YAML from 'yaml';
|
6 |
| -import glob from 'glob-promise'; |
| 5 | +import esbuild from 'esbuild'; |
7 | 6 |
|
8 |
| -/** |
9 |
| - * @typedef {import('esbuild').BuildOptions} BuildOptions |
10 |
| - */ |
| 7 | +const files = fileURLToPath(new URL('./files', import.meta.url)); |
11 | 8 |
|
12 | 9 | /** @type {import('.')} **/
|
13 |
| -export default function entrypoint(options) { |
| 10 | +export default function entrypoint() { |
14 | 11 | return {
|
15 | 12 | name: 'appengine',
|
16 | 13 |
|
17 |
| - async adapt({utils}) { |
| 14 | + async adapt(builder) { |
18 | 15 | const dir = '.appengine_build_output';
|
19 |
| - utils.rimraf(dir); |
| 16 | + const temporary = builder.getBuildDirectory('appengine-tmp'); |
20 | 17 |
|
21 |
| - const files = fileURLToPath(new URL('./files', import.meta.url)); |
| 18 | + builder.rimraf(dir); |
| 19 | + builder.rimraf(temporary); |
22 | 20 |
|
23 |
| - const dirs = { |
24 |
| - static: join(dir, 'static'), |
25 |
| - client: join(dir, 'client'), |
26 |
| - tmp: '.svelte-kit/appengine/', |
27 |
| - }; |
| 21 | + builder.log.minor('Copying assets'); |
| 22 | + builder.writeClient(`${dir}/storage`); |
| 23 | + // Builder.writeServer(`${dir}/server`); |
| 24 | + builder.writeStatic(`${dir}/storage`); |
28 | 25 |
|
29 |
| - utils.log.minor('Generating nodejs entrypoint...'); |
30 |
| - utils.rimraf(dirs.tmp); |
31 |
| - utils.copy(join(files, 'entry.js'), '.svelte-kit/appengine/entry.js'); |
32 |
| - |
33 |
| - /** @type {BuildOptions} */ |
34 |
| - const defaultOptions = { |
35 |
| - entryPoints: [join(dirs.tmp, 'entry.js')], |
36 |
| - outfile: join(dir, 'index.js'), |
37 |
| - bundle: true, |
38 |
| - inject: [join(files, 'shims.js')], |
39 |
| - platform: 'node', |
40 |
| - target: 'node16', |
41 |
| - }; |
| 26 | + const relativePath = posix.relative(temporary, builder.getServerDirectory()); |
42 | 27 |
|
43 |
| - const buildOptions = options && options.esbuild |
44 |
| - ? await options.esbuild(defaultOptions) : defaultOptions; |
| 28 | + builder.log.minor('Prerendering static pages'); |
| 29 | + const prerenderedPaths = await builder.prerender({ |
| 30 | + dest: `${dir}/storage`, |
| 31 | + }); |
45 | 32 |
|
46 |
| - await esbuild.build(buildOptions); |
| 33 | + // Copy server handler |
| 34 | + builder.copy(files, temporary, {replace: { |
| 35 | + APP: `${relativePath}/app.js`, |
| 36 | + }}); |
47 | 37 |
|
48 |
| - utils.log.minor('Writing package.json...'); |
49 | 38 | writeFileSync(
|
50 |
| - join(dir, 'package.json'), |
51 |
| - JSON.stringify({ |
52 |
| - type: 'commonjs', |
53 |
| - }), |
| 39 | + `${temporary}/manifest.js`, |
| 40 | + `export const manifest = ${builder.generateManifest({ |
| 41 | + relativePath, |
| 42 | + })};\n`, |
54 | 43 | );
|
55 | 44 |
|
56 |
| - utils.log.minor('Prerendering static pages...'); |
57 |
| - await utils.prerender({ |
58 |
| - dest: dirs.static, |
| 45 | + await esbuild.build({ |
| 46 | + entryPoints: [`${temporary}/entry.js`], |
| 47 | + outfile: `${dir}/index.js`, |
| 48 | + target: 'node16', |
| 49 | + bundle: true, |
| 50 | + platform: 'node', |
59 | 51 | });
|
60 | 52 |
|
61 |
| - utils.log.minor('Copying assets...'); |
62 |
| - utils.copy_static_files(dirs.static); |
63 |
| - utils.copy_client_files(dirs.client); |
64 |
| - |
65 |
| - utils.log.minor('Writing app.yaml...'); |
66 |
| - |
67 |
| - const staticFiles = await glob('**/*.*', {cwd: dirs.static}); |
68 |
| - utils.log.minor('Creating routes for static files' + staticFiles.join(', ')); |
| 53 | + writeFileSync(`${dir}/package.json`, JSON.stringify({type: 'commonjs'})); |
| 54 | + |
| 55 | + const serverRoutes = []; |
| 56 | + |
| 57 | + builder.createEntries(route => { |
| 58 | + const parts = []; |
| 59 | + |
| 60 | + for (const segment of route.segments) { |
| 61 | + if (segment.rest || segment.dynamic) { |
| 62 | + parts.push('.*'); |
| 63 | + } else { |
| 64 | + parts.push(segment.content); |
| 65 | + } |
| 66 | + } |
| 67 | + |
| 68 | + const id = '/' + parts.join('/'); |
| 69 | + return { |
| 70 | + id, |
| 71 | + filter: _ => true, |
| 72 | + complete: _ => { |
| 73 | + if (prerenderedPaths.paths.includes(id)) { |
| 74 | + const staticPath = join('storage', id, 'index.html'); |
| 75 | + serverRoutes.push( |
| 76 | + { |
| 77 | + url: id, |
| 78 | + // eslint-disable-next-line camelcase |
| 79 | + static_files: staticPath, |
| 80 | + upload: staticPath, |
| 81 | + }, |
| 82 | + ); |
| 83 | + } else { |
| 84 | + serverRoutes.push( |
| 85 | + { |
| 86 | + url: id, |
| 87 | + secure: 'always', |
| 88 | + script: 'auto', |
| 89 | + }, |
| 90 | + ); |
| 91 | + } |
| 92 | + }, |
| 93 | + }; |
| 94 | + }); |
69 | 95 |
|
70 |
| - const staticFilesRoutes = staticFiles.map(f => ({ |
71 |
| - // Remove index.html from url |
72 |
| - url: '/' + f.replace(/index\.html$/gi, ''), |
73 |
| - // eslint-disable-next-line camelcase |
74 |
| - static_files: join('static', f).replace(/\\/g, '/'), |
75 |
| - upload: join('static', f).replace(/\\/g, '/'), |
76 |
| - })); |
| 96 | + if (serverRoutes.length > 99) { |
| 97 | + throw new Error('Too many url routes: ' + serverRoutes.length); |
| 98 | + } |
77 | 99 |
|
78 | 100 | writeFileSync(
|
79 | 101 | join(dir, 'app.yaml'),
|
80 | 102 | YAML.stringify({
|
81 | 103 | runtime: 'nodejs16',
|
82 | 104 | entrypoint: 'node index.js',
|
83 | 105 | handlers: [
|
| 106 | + ...serverRoutes, |
84 | 107 | {
|
85 |
| - url: '/_app', |
| 108 | + url: '/', |
86 | 109 | // eslint-disable-next-line camelcase
|
87 |
| - static_dir: 'client/_app', |
88 |
| - }, |
89 |
| - ...staticFilesRoutes, |
90 |
| - { |
91 |
| - url: '/.*', |
92 |
| - secure: 'always', |
93 |
| - script: 'auto', |
| 110 | + static_dir: 'storage', |
94 | 111 | },
|
95 | 112 | ],
|
96 | 113 | }),
|
97 | 114 | );
|
98 | 115 |
|
99 |
| - utils.log.success('To deploy, run "gcloud app deploy --project <CLOUD_PROJECT_ID> .appengine_build_output/app.yaml"'); |
| 116 | + builder.log.success('To deploy, run "gcloud app deploy --project <CLOUD_PROJECT_ID> .appengine_build_output/app.yaml"'); |
100 | 117 | },
|
101 | 118 | };
|
102 | 119 | }
|
0 commit comments