mirror of
https://github.com/Sevichecc/Urara-Blog.git
synced 2025-05-06 00:19:30 +08:00
260 lines
6.5 KiB
Text
260 lines
6.5 KiB
Text
import { $ } from './index.js';
|
|
import glob from 'tiny-glob';
|
|
import zlib from 'zlib';
|
|
import { existsSync, statSync, createReadStream, createWriteStream } from 'fs';
|
|
import { pipeline } from 'stream';
|
|
import { promisify } from 'util';
|
|
import { r as rimraf, m as mkdirp, c as copy } from './filesystem.js';
|
|
import { g as generate_manifest } from '../vite.js';
|
|
import 'path';
|
|
import 'url';
|
|
import 'node:child_process';
|
|
import 'node:fs';
|
|
import 'node:path';
|
|
import '@sveltejs/vite-plugin-svelte';
|
|
import 'vite';
|
|
import './sync.js';
|
|
import './utils.js';
|
|
import './write_tsconfig.js';
|
|
import 'querystring';
|
|
import '../node.js';
|
|
import '../node/polyfills.js';
|
|
import 'assert';
|
|
import 'net';
|
|
import 'http';
|
|
import 'buffer';
|
|
import 'stream/web';
|
|
import 'perf_hooks';
|
|
import 'util/types';
|
|
import 'events';
|
|
import 'tls';
|
|
import 'async_hooks';
|
|
import 'console';
|
|
import 'node:http';
|
|
import 'node:https';
|
|
import 'node:zlib';
|
|
import 'node:stream';
|
|
import 'node:buffer';
|
|
import 'node:util';
|
|
import 'node:url';
|
|
import 'node:net';
|
|
import 'crypto';
|
|
import './error.js';
|
|
|
|
/**
|
|
* Creates the Builder which is passed to adapters for building the application.
|
|
* @param {{
|
|
* config: import('types').ValidatedConfig;
|
|
* build_data: import('types').BuildData;
|
|
* prerendered: import('types').Prerendered;
|
|
* log: import('types').Logger;
|
|
* }} opts
|
|
* @returns {import('types').Builder}
|
|
*/
|
|
function create_builder({ config, build_data, prerendered, log }) {
|
|
/** @type {Set<string>} */
|
|
const prerendered_paths = new Set(prerendered.paths);
|
|
|
|
/** @param {import('types').RouteData} route */
|
|
// TODO routes should come pre-filtered
|
|
function not_prerendered(route) {
|
|
if (route.type === 'page' && route.path) {
|
|
return !prerendered_paths.has(route.path) && !prerendered_paths.has(route.path + '/');
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
const pipe = promisify(pipeline);
|
|
|
|
/**
|
|
* @param {string} file
|
|
* @param {'gz' | 'br'} format
|
|
*/
|
|
async function compress_file(file, format = 'gz') {
|
|
const compress =
|
|
format == 'br'
|
|
? zlib.createBrotliCompress({
|
|
params: {
|
|
[zlib.constants.BROTLI_PARAM_MODE]: zlib.constants.BROTLI_MODE_TEXT,
|
|
[zlib.constants.BROTLI_PARAM_QUALITY]: zlib.constants.BROTLI_MAX_QUALITY,
|
|
[zlib.constants.BROTLI_PARAM_SIZE_HINT]: statSync(file).size
|
|
}
|
|
})
|
|
: zlib.createGzip({ level: zlib.constants.Z_BEST_COMPRESSION });
|
|
|
|
const source = createReadStream(file);
|
|
const destination = createWriteStream(`${file}.${format}`);
|
|
|
|
await pipe(source, compress, destination);
|
|
}
|
|
|
|
return {
|
|
log,
|
|
rimraf,
|
|
mkdirp,
|
|
copy,
|
|
|
|
config,
|
|
prerendered,
|
|
|
|
async createEntries(fn) {
|
|
const { routes } = build_data.manifest_data;
|
|
|
|
/** @type {import('types').RouteDefinition[]} */
|
|
const facades = routes.map((route) => ({
|
|
id: route.id,
|
|
type: route.type,
|
|
segments: route.id.split('/').map((segment) => ({
|
|
dynamic: segment.includes('['),
|
|
rest: segment.includes('[...'),
|
|
content: segment
|
|
})),
|
|
pattern: route.pattern,
|
|
methods: route.type === 'page' ? ['GET'] : build_data.server.methods[route.file]
|
|
}));
|
|
|
|
const seen = new Set();
|
|
|
|
for (let i = 0; i < routes.length; i += 1) {
|
|
const route = routes[i];
|
|
const { id, filter, complete } = fn(facades[i]);
|
|
|
|
if (seen.has(id)) continue;
|
|
seen.add(id);
|
|
|
|
const group = [route];
|
|
|
|
// figure out which lower priority routes should be considered fallbacks
|
|
for (let j = i + 1; j < routes.length; j += 1) {
|
|
if (filter(facades[j])) {
|
|
group.push(routes[j]);
|
|
}
|
|
}
|
|
|
|
const filtered = new Set(group.filter(not_prerendered));
|
|
|
|
// heuristic: if /foo/[bar] is included, /foo/[bar].json should
|
|
// also be included, since the page likely needs the endpoint
|
|
filtered.forEach((route) => {
|
|
if (route.type === 'page') {
|
|
const endpoint = routes.find((candidate) => candidate.id === route.id + '.json');
|
|
|
|
if (endpoint) {
|
|
filtered.add(endpoint);
|
|
}
|
|
}
|
|
});
|
|
|
|
if (filtered.size > 0) {
|
|
await complete({
|
|
generateManifest: ({ relativePath, format }) =>
|
|
generate_manifest({
|
|
build_data,
|
|
relative_path: relativePath,
|
|
routes: Array.from(filtered),
|
|
format
|
|
})
|
|
});
|
|
}
|
|
}
|
|
},
|
|
|
|
generateManifest: ({ relativePath, format }) => {
|
|
return generate_manifest({
|
|
build_data,
|
|
relative_path: relativePath,
|
|
routes: build_data.manifest_data.routes.filter(not_prerendered),
|
|
format
|
|
});
|
|
},
|
|
|
|
getBuildDirectory(name) {
|
|
return `${config.kit.outDir}/${name}`;
|
|
},
|
|
|
|
getClientDirectory() {
|
|
return `${config.kit.outDir}/output/client`;
|
|
},
|
|
|
|
getServerDirectory() {
|
|
return `${config.kit.outDir}/output/server`;
|
|
},
|
|
|
|
getStaticDirectory() {
|
|
return config.kit.files.assets;
|
|
},
|
|
|
|
writeClient(dest) {
|
|
return [...copy(`${config.kit.outDir}/output/client`, dest)];
|
|
},
|
|
|
|
writePrerendered(dest, { fallback } = {}) {
|
|
const source = `${config.kit.outDir}/output/prerendered`;
|
|
const files = [...copy(`${source}/pages`, dest), ...copy(`${source}/dependencies`, dest)];
|
|
|
|
if (fallback) {
|
|
files.push(fallback);
|
|
copy(`${source}/fallback.html`, `${dest}/${fallback}`);
|
|
}
|
|
|
|
return files;
|
|
},
|
|
|
|
writeServer(dest) {
|
|
return copy(`${config.kit.outDir}/output/server`, dest);
|
|
},
|
|
|
|
// TODO remove these methods for 1.0
|
|
// @ts-expect-error
|
|
writeStatic() {
|
|
throw new Error(
|
|
`writeStatic has been removed. Please ensure you are using the latest version of ${
|
|
config.kit.adapter.name || 'your adapter'
|
|
}`
|
|
);
|
|
},
|
|
|
|
async compress(directory) {
|
|
if (!existsSync(directory)) {
|
|
return;
|
|
}
|
|
|
|
const files = await glob('**/*.{html,js,json,css,svg,xml,wasm}', {
|
|
cwd: directory,
|
|
dot: true,
|
|
absolute: true,
|
|
filesOnly: true
|
|
});
|
|
|
|
await Promise.all(
|
|
files.map((file) => Promise.all([compress_file(file, 'gz'), compress_file(file, 'br')]))
|
|
);
|
|
},
|
|
|
|
async prerender() {
|
|
throw new Error(
|
|
'builder.prerender() has been removed. Prerendering now takes place in the build phase — see builder.prerender and builder.writePrerendered'
|
|
);
|
|
}
|
|
};
|
|
}
|
|
|
|
/**
|
|
* @param {import('types').ValidatedConfig} config
|
|
* @param {import('types').BuildData} build_data
|
|
* @param {import('types').Prerendered} prerendered
|
|
* @param {{ log: import('types').Logger }} opts
|
|
*/
|
|
async function adapt(config, build_data, prerendered, { log }) {
|
|
const { name, adapt } = config.kit.adapter;
|
|
|
|
console.log($.bold().cyan(`\n> Using ${name}`));
|
|
|
|
const builder = create_builder({ config, build_data, prerendered, log });
|
|
await adapt(builder);
|
|
|
|
log.success('done');
|
|
}
|
|
|
|
export { adapt };
|