File: /var/www/quadcode.com/node_modules/@sveltejs/kit/src/core/postbuild/analyse.js
import { join } from 'node:path';
import { pathToFileURL } from 'node:url';
import { get_option } from '../../utils/options.js';
import {
validate_layout_exports,
validate_layout_server_exports,
validate_page_exports,
validate_page_server_exports,
validate_server_exports
} from '../../utils/exports.js';
import { load_config } from '../config/index.js';
import { forked } from '../../utils/fork.js';
import { should_polyfill } from '../../utils/platform.js';
import { installPolyfills } from '../../exports/node/polyfills.js';
import { resolvePath } from '../../exports/index.js';
import { ENDPOINT_METHODS } from '../../constants.js';
import { filter_private_env, filter_public_env } from '../../utils/env.js';
export default forked(import.meta.url, analyse);
/**
* @param {{
* manifest_path: string;
* env: Record<string, string>
* }} opts
*/
async function analyse({ manifest_path, env }) {
/** @type {import('@sveltejs/kit').SSRManifest} */
const manifest = (await import(pathToFileURL(manifest_path).href)).manifest;
/** @type {import('types').ValidatedKitConfig} */
const config = (await load_config()).kit;
const server_root = join(config.outDir, 'output');
/** @type {import('types').ServerInternalModule} */
const internal = await import(pathToFileURL(`${server_root}/server/internal.js`).href);
if (should_polyfill) {
installPolyfills();
}
// configure `import { building } from '$app/environment'` —
// essential we do this before analysing the code
internal.set_building(true);
// set env, in case it's used in initialisation
const { publicPrefix: public_prefix, privatePrefix: private_prefix } = config.env;
internal.set_private_env(filter_private_env(env, { public_prefix, private_prefix }));
internal.set_public_env(filter_public_env(env, { public_prefix, private_prefix }));
/** @type {import('types').ServerMetadata} */
const metadata = {
nodes: [],
routes: new Map()
};
// analyse nodes
for (const loader of manifest._.nodes) {
const node = await loader();
metadata.nodes[node.index] = {
has_server_load: node.server?.load !== undefined || node.server?.trailingSlash !== undefined
};
}
// analyse routes
for (const route of manifest._.routes) {
/** @type {Array<'GET' | 'POST'>} */
const page_methods = [];
/** @type {import('types').HttpMethod[]} */
const api_methods = [];
/** @type {import('types').PrerenderOption | undefined} */
let prerender = undefined;
/** @type {any} */
let config = undefined;
/** @type {import('types').PrerenderEntryGenerator | undefined} */
let entries = undefined;
if (route.endpoint) {
const mod = await route.endpoint();
if (mod.prerender !== undefined) {
validate_server_exports(mod, route.id);
if (mod.prerender && (mod.POST || mod.PATCH || mod.PUT || mod.DELETE)) {
throw new Error(
`Cannot prerender a +server file with POST, PATCH, PUT, or DELETE (${route.id})`
);
}
prerender = mod.prerender;
}
Object.values(mod).forEach((/** @type {import('types').HttpMethod} */ method) => {
if (mod[method] && ENDPOINT_METHODS.has(method)) {
api_methods.push(method);
}
});
config = mod.config;
entries = mod.entries;
}
if (route.page) {
const nodes = await Promise.all(
[...route.page.layouts, route.page.leaf].map((n) => {
if (n !== undefined) return manifest._.nodes[n]();
})
);
const layouts = nodes.slice(0, -1);
const page = nodes.at(-1);
for (const layout of layouts) {
if (layout) {
validate_layout_server_exports(layout.server, layout.server_id);
validate_layout_exports(layout.universal, layout.universal_id);
}
}
if (page) {
page_methods.push('GET');
if (page.server?.actions) page_methods.push('POST');
validate_page_server_exports(page.server, page.server_id);
validate_page_exports(page.universal, page.universal_id);
}
prerender = get_option(nodes, 'prerender') ?? false;
config = get_config(nodes);
entries ??= get_option(nodes, 'entries');
}
metadata.routes.set(route.id, {
config,
methods: Array.from(new Set([...page_methods, ...api_methods])),
page: {
methods: page_methods
},
api: {
methods: api_methods
},
prerender,
entries:
entries && (await entries()).map((entry_object) => resolvePath(route.id, entry_object))
});
}
return metadata;
}
/**
* Do a shallow merge (first level) of the config object
* @param {Array<import('types').SSRNode | undefined>} nodes
*/
function get_config(nodes) {
let current = {};
for (const node of nodes) {
const config = node?.universal?.config ?? node?.server?.config;
if (config) {
current = {
...current,
...config
};
}
}
return Object.keys(current).length ? current : undefined;
}