2025-04-15 16:39:47 +02:00

974 lines
33 KiB
JavaScript

"use strict";
var __create = Object.create;
var __defProp = Object.defineProperty;
var __defProps = Object.defineProperties;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __propIsEnum = Object.prototype.propertyIsEnumerable;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __spreadValues = (a, b) => {
for (var prop in b || (b = {}))
if (__hasOwnProp.call(b, prop))
__defNormalProp(a, prop, b[prop]);
if (__getOwnPropSymbols)
for (var prop of __getOwnPropSymbols(b)) {
if (__propIsEnum.call(b, prop))
__defNormalProp(a, prop, b[prop]);
}
return a;
};
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
var __export = (target, all) => {
for (var name in all)
__defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
if (from && typeof from === "object" || typeof from === "function") {
for (let key of __getOwnPropNames(from))
if (!__hasOwnProp.call(to, key) && key !== except)
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
}
return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
// If the importer is in node compatibility mode or this is not an ESM
// file that has been converted to a CommonJS file using a Babel-
// compatible transform (i.e. "__esModule" has not been set), then set
// "default" to the CommonJS "module.exports" for node compatibility.
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
// src/index.ts
var index_exports = {};
__export(index_exports, {
PageContext: () => PageContext,
default: () => index_default,
reactResolver: () => reactResolver,
solidResolver: () => solidResolver,
syncIndexResolver: () => syncIndexResolver,
vueResolver: () => vueResolver
});
module.exports = __toCommonJS(index_exports);
// src/constants.ts
var MODULE_IDS = [
"~pages",
"~react-pages",
"~solid-pages",
"pages-generated",
"virtual:generated-pages",
"virtual:generated-pages-react"
];
var MODULE_ID_VIRTUAL = "virtual:vite-plugin-pages/generated-pages";
var ROUTE_BLOCK_ID_VIRTUAL = "virtual:vite-plugin-pages/route-block";
var ROUTE_IMPORT_NAME = "__pages_import_$1__";
var routeBlockQueryRE = /\?vue&type=route/;
var dynamicRouteRE = /^\[(.+)\]$/;
var cacheAllRouteRE = /^\[\.{3}(.*)\]$/;
var replaceDynamicRouteRE = /^\[(?:\.{3})?(.*)\]$/;
var nuxtDynamicRouteRE = /^_(.*)$/;
var nuxtCacheAllRouteRE = /^_$/;
var countSlashRE = /\//g;
var replaceIndexRE = /\/?index$/;
// src/context.ts
var import_node_path4 = require("path");
var import_node_process2 = __toESM(require("process"), 1);
// node_modules/.pnpm/@antfu+utils@9.1.0/node_modules/@antfu/utils/dist/index.mjs
function toArray(array) {
array = array != null ? array : [];
return Array.isArray(array) ? array : [array];
}
function slash(str) {
return str.replace(/\\/g, "/");
}
var VOID = Symbol("p-void");
// src/files.ts
var import_node_path2 = require("path");
var import_tinyglobby = require("tinyglobby");
// src/utils.ts
var import_node_path = require("path");
var import_node_url = require("url");
var import_debug = __toESM(require("debug"), 1);
var import_micromatch = __toESM(require("micromatch"), 1);
var debug = {
hmr: (0, import_debug.default)("vite-plugin-pages:hmr"),
routeBlock: (0, import_debug.default)("vite-plugin-pages:routeBlock"),
options: (0, import_debug.default)("vite-plugin-pages:options"),
pages: (0, import_debug.default)("vite-plugin-pages:pages"),
search: (0, import_debug.default)("vite-plugin-pages:search"),
env: (0, import_debug.default)("vite-plugin-pages:env"),
cache: (0, import_debug.default)("vite-plugin-pages:cache"),
resolver: (0, import_debug.default)("vite-plugin-pages:resolver")
};
function extsToGlob(extensions) {
return extensions.length > 1 ? `{${extensions.join(",")}}` : extensions[0] || "";
}
function countSlash(value) {
return (value.match(countSlashRE) || []).length;
}
function isPagesDir(path, options) {
for (const page of options.dirs) {
const dirPath = slash((0, import_node_path.resolve)(options.root, page.dir));
if (path.startsWith(dirPath))
return true;
}
return false;
}
function isTarget(path, options) {
return isPagesDir(path, options) && !import_micromatch.default.isMatch(path, options.exclude) && options.extensionsRE.test(path);
}
function isDynamicRoute(routePath, nuxtStyle = false) {
return nuxtStyle ? nuxtDynamicRouteRE.test(routePath) : dynamicRouteRE.test(routePath);
}
function isCatchAllRoute(routePath, nuxtStyle = false) {
return nuxtStyle ? nuxtCacheAllRouteRE.test(routePath) : cacheAllRouteRE.test(routePath);
}
function resolveImportMode(filepath, options) {
const mode = options.importMode;
if (typeof mode === "function")
return mode(filepath, options);
return mode;
}
function invalidatePagesModule(server) {
const { moduleGraph } = server;
const mods = moduleGraph.getModulesByFile(MODULE_ID_VIRTUAL);
if (mods) {
const seen = /* @__PURE__ */ new Set();
mods.forEach((mod) => {
moduleGraph.invalidateModule(mod, seen);
});
}
}
function normalizeCase(str, caseSensitive) {
if (!caseSensitive)
return str.toLocaleLowerCase();
return str;
}
function normalizeName(name, isDynamic, nuxtStyle = false) {
if (!isDynamic)
return name;
return nuxtStyle ? name.replace(nuxtDynamicRouteRE, "$1") || "all" : name.replace(replaceDynamicRouteRE, "$1");
}
function buildReactRoutePath(node, nuxtStyle = false) {
const isDynamic = isDynamicRoute(node, nuxtStyle);
const isCatchAll = isCatchAllRoute(node, nuxtStyle);
const normalizedName = normalizeName(node, isDynamic, nuxtStyle);
if (isDynamic) {
if (isCatchAll)
return "*";
return `:${normalizedName}`;
}
return `${normalizedName}`;
}
function buildReactRemixRoutePath(node) {
const escapeStart = "[";
const escapeEnd = "]";
let result = "";
let rawSegmentBuffer = "";
let inEscapeSequence = 0;
let skipSegment = false;
for (let i = 0; i < node.length; i++) {
let isNewEscapeSequence2 = function() {
return !inEscapeSequence && char === escapeStart && lastChar !== escapeStart;
}, isCloseEscapeSequence2 = function() {
return inEscapeSequence && char === escapeEnd && nextChar !== escapeEnd;
}, isStartOfLayoutSegment2 = function() {
return char === "_" && nextChar === "_" && !rawSegmentBuffer;
};
var isNewEscapeSequence = isNewEscapeSequence2, isCloseEscapeSequence = isCloseEscapeSequence2, isStartOfLayoutSegment = isStartOfLayoutSegment2;
const char = node.charAt(i);
const lastChar = i > 0 ? node.charAt(i - 1) : void 0;
const nextChar = i < node.length - 1 ? node.charAt(i + 1) : void 0;
if (skipSegment) {
if (char === "/" || char === "." || char === import_node_path.win32.sep)
skipSegment = false;
continue;
}
if (isNewEscapeSequence2()) {
inEscapeSequence++;
continue;
}
if (isCloseEscapeSequence2()) {
inEscapeSequence--;
continue;
}
if (inEscapeSequence) {
result += char;
continue;
}
if (char === "/" || char === import_node_path.win32.sep || char === ".") {
if (rawSegmentBuffer === "index" && result.endsWith("index"))
result = result.replace(replaceIndexRE, "");
else result += "/";
rawSegmentBuffer = "";
continue;
}
if (isStartOfLayoutSegment2()) {
skipSegment = true;
continue;
}
rawSegmentBuffer += char;
if (char === "$") {
result += typeof nextChar === "undefined" ? "*" : ":";
continue;
}
result += char;
}
if (rawSegmentBuffer === "index" && result.endsWith("index"))
result = result.replace(replaceIndexRE, "");
return result || void 0;
}
function parsePageRequest(id) {
const [moduleId, rawQuery] = id.split("?", 2);
const query = new import_node_url.URLSearchParams(rawQuery);
const pageId = query.get("id");
return {
moduleId,
query,
pageId
};
}
// src/files.ts
function getPageDirs(PageOptions, root, exclude) {
const dirs = (0, import_tinyglobby.globSync)(slash(PageOptions.dir), {
ignore: exclude,
onlyDirectories: true,
dot: true,
expandDirectories: false,
cwd: root
});
const pageDirs = dirs.map((dir) => __spreadProps(__spreadValues({}, PageOptions), {
dir: dir.replace(/\/$/, "")
}));
return pageDirs;
}
function getPageFiles(path, options, pageOptions) {
var _a;
const {
exclude,
extensions
} = options;
const ext = extsToGlob(extensions);
const pattern = (_a = pageOptions == null ? void 0 : pageOptions.filePattern) != null ? _a : `**/*.${ext}`;
const files = (0, import_tinyglobby.globSync)(pattern, {
ignore: exclude,
onlyFiles: true,
cwd: path
}).map((p) => slash((0, import_node_path2.join)(path, p)));
return files;
}
// src/options.ts
var import_node_path3 = require("path");
var import_node_process = __toESM(require("process"), 1);
// src/stringify.ts
var componentRE = /"(?:component|element)":("(.*?)")/g;
var hasFunctionRE = /"(?:props|beforeEnter)":("(.*?)")/g;
var multilineCommentsRE = /\/\*(.|[\r\n])*?\*\//g;
var singlelineCommentsRE = /\/\/.*/g;
function replaceFunction(_, value) {
if (typeof value === "function" || typeof value === "function") {
const fnBody = value.toString().replace(multilineCommentsRE, "").replace(singlelineCommentsRE, "").replace(/(\s)/g, "");
if (fnBody.length < 8 || fnBody.substring(0, 8) !== "function")
return `_NuFrRa_${fnBody}`;
return fnBody;
}
return value;
}
function stringifyRoutes(preparedRoutes, options) {
const importsMap = /* @__PURE__ */ new Map();
function getImportString(path, importName) {
var _a, _b;
const mode = resolveImportMode(path, options);
return mode === "sync" ? `import ${importName} from "${path}"` : `const ${importName} = ${((_b = (_a = options.resolver.stringify) == null ? void 0 : _a.dynamicImport) == null ? void 0 : _b.call(_a, path)) || `() => import("${path}")`}`;
}
function componentReplacer(str, replaceStr, path) {
var _a, _b;
let importName = importsMap.get(path);
if (!importName)
importName = ROUTE_IMPORT_NAME.replace("$1", `${importsMap.size}`);
importsMap.set(path, importName);
importName = ((_b = (_a = options.resolver.stringify) == null ? void 0 : _a.component) == null ? void 0 : _b.call(_a, importName)) || importName;
return str.replace(replaceStr, importName);
}
function functionReplacer(str, replaceStr, content) {
if (content.startsWith("function"))
return str.replace(replaceStr, content);
if (content.startsWith("_NuFrRa_"))
return str.replace(replaceStr, content.slice(8));
return str;
}
const stringRoutes = JSON.stringify(preparedRoutes, replaceFunction).replace(componentRE, componentReplacer).replace(hasFunctionRE, functionReplacer);
const imports = Array.from(importsMap).map((args) => getImportString(...args));
return {
imports,
stringRoutes
};
}
function generateClientCode(routes, options) {
var _a, _b;
const { imports, stringRoutes } = stringifyRoutes(routes, options);
const code = `${imports.join(";\n")};
const routes = ${stringRoutes};
export default routes;`;
return ((_b = (_a = options.resolver.stringify) == null ? void 0 : _a.final) == null ? void 0 : _b.call(_a, code)) || code;
}
// src/resolvers/react.ts
function prepareRoutes(routes, options, parent) {
var _a, _b;
for (const route of routes) {
if (parent)
route.path = (_a = route.path) == null ? void 0 : _a.replace(/^\//, "");
if (route.children)
route.children = prepareRoutes(route.children, options, route);
delete route.rawRoute;
Object.assign(route, ((_b = options.extendRoute) == null ? void 0 : _b.call(options, route, parent)) || {});
}
return routes;
}
async function computeReactRoutes(ctx) {
var _a, _b;
const { routeStyle, caseSensitive, importPath } = ctx.options;
const nuxtStyle = routeStyle === "nuxt";
const pageRoutes = [...ctx.pageRouteMap.values()].sort((a, b) => countSlash(a.route) - countSlash(b.route));
const routes = [];
pageRoutes.forEach((page) => {
const pathNodes = page.route.split("/");
const element = importPath === "relative" ? page.path.replace(ctx.root, "") : page.path;
let parentRoutes = routes;
for (let i = 0; i < pathNodes.length; i++) {
const node = pathNodes[i];
const route = {
caseSensitive,
path: "",
rawRoute: pathNodes.slice(0, i + 1).join("/")
};
if (i === pathNodes.length - 1)
route.element = element;
const isIndexRoute = normalizeCase(node, caseSensitive).endsWith("index");
if (!route.path && isIndexRoute) {
route.path = "/";
} else if (!isIndexRoute) {
if (routeStyle === "remix")
route.path = buildReactRemixRoutePath(node);
else
route.path = buildReactRoutePath(node, nuxtStyle);
}
const parent = parentRoutes.find((parent2) => {
return pathNodes.slice(0, i).join("/") === parent2.rawRoute;
});
if (parent) {
parent.children = parent.children || [];
parentRoutes = parent.children;
}
const exits = parentRoutes.some((parent2) => {
return pathNodes.slice(0, i + 1).join("/") === parent2.rawRoute;
});
if (!exits)
parentRoutes.push(route);
}
});
let finalRoutes = prepareRoutes(routes, ctx.options);
finalRoutes = await ((_b = (_a = ctx.options).onRoutesGenerated) == null ? void 0 : _b.call(_a, finalRoutes)) || finalRoutes;
return finalRoutes;
}
async function resolveReactRoutes(ctx) {
var _a, _b;
const finalRoutes = await computeReactRoutes(ctx);
let client = generateClientCode(finalRoutes, ctx.options);
client = await ((_b = (_a = ctx.options).onClientGenerated) == null ? void 0 : _b.call(_a, client)) || client;
return client;
}
function reactResolver() {
return {
resolveModuleIds() {
return ["~react-pages", "virtual:generated-pages-react"];
},
resolveExtensions() {
return ["tsx", "jsx", "ts", "js"];
},
async resolveRoutes(ctx) {
return resolveReactRoutes(ctx);
},
async getComputedRoutes(ctx) {
return computeReactRoutes(ctx);
},
stringify: {
component: (path) => `React.createElement(${path})`,
dynamicImport: (path) => `React.lazy(() => import("${path}"))`,
final: (code) => `import React from "react";
${code}`
}
};
}
// src/resolvers/solid.ts
function prepareRoutes2(options, routes, parent) {
var _a, _b;
for (const route of routes) {
if (parent)
route.path = (_a = route.path) == null ? void 0 : _a.replace(/^\//, "");
if (route.children)
route.children = prepareRoutes2(options, route.children, route);
delete route.rawRoute;
Object.assign(route, ((_b = options.extendRoute) == null ? void 0 : _b.call(options, route, parent)) || {});
}
return routes;
}
async function computeSolidRoutes(ctx) {
var _a, _b;
const { routeStyle, caseSensitive, importPath } = ctx.options;
const nuxtStyle = routeStyle === "nuxt";
const pageRoutes = [...ctx.pageRouteMap.values()].sort((a, b) => countSlash(a.route) - countSlash(b.route));
const routes = [];
pageRoutes.forEach((page) => {
const pathNodes = page.route.split("/");
const component = importPath === "relative" ? page.path.replace(ctx.root, "") : page.path;
const element = importPath === "relative" ? page.path.replace(ctx.root, "") : page.path;
let parentRoutes = routes;
for (let i = 0; i < pathNodes.length; i++) {
const node = pathNodes[i];
const normalizedPath = normalizeCase(node, caseSensitive);
const route = {
path: "",
rawRoute: pathNodes.slice(0, i + 1).join("/")
};
const parent = parentRoutes.find(
(parent2) => pathNodes.slice(0, i).join("/") === parent2.rawRoute
);
if (parent) {
parent.children = parent.children || [];
parentRoutes = parent.children;
}
if (i === pathNodes.length - 1) {
route.element = element;
route.component = component;
}
if (normalizedPath === "index") {
if (!route.path)
route.path = "/";
} else if (normalizedPath !== "index") {
if (routeStyle === "remix")
route.path = buildReactRemixRoutePath(node) || "";
else
route.path = buildReactRoutePath(node, nuxtStyle) || "";
}
const exist = parentRoutes.some((parent2) => {
return pathNodes.slice(0, i + 1).join("/") === parent2.rawRoute;
});
if (!exist)
parentRoutes.push(route);
}
});
let finalRoutes = prepareRoutes2(ctx.options, routes);
finalRoutes = await ((_b = (_a = ctx.options).onRoutesGenerated) == null ? void 0 : _b.call(_a, finalRoutes)) || finalRoutes;
return finalRoutes;
}
async function resolveSolidRoutes(ctx) {
var _a, _b;
const finalRoutes = await computeSolidRoutes(ctx);
let client = generateClientCode(finalRoutes, ctx.options);
client = await ((_b = (_a = ctx.options).onClientGenerated) == null ? void 0 : _b.call(_a, client)) || client;
return client;
}
function solidResolver() {
return {
resolveModuleIds() {
return ["~solid-pages"];
},
resolveExtensions() {
return ["tsx", "jsx", "ts", "js"];
},
async resolveRoutes(ctx) {
return resolveSolidRoutes(ctx);
},
async getComputedRoutes(ctx) {
return computeSolidRoutes(ctx);
},
stringify: {
dynamicImport: (path) => `Solid.lazy(() => import("${path}"))`,
final: (code) => `import * as Solid from "solid-js";
${code}`
}
};
}
// src/resolvers/vue.ts
var import_dequal = require("dequal");
var import_picocolors = __toESM(require("picocolors"), 1);
// src/customBlock.ts
var import_node_fs = __toESM(require("fs"), 1);
var import_extract_comments = __toESM(require("extract-comments"), 1);
var import_json5 = __toESM(require("json5"), 1);
var import_local_pkg = require("local-pkg");
var import_yaml = require("yaml");
var routeJSXReg = /^\s+(route)\s+/gm;
function parseJSX(code) {
return (0, import_extract_comments.default)(code).slice(0, 1).filter((comment) => routeJSXReg.test(comment.value) && comment.value.includes(":") && comment.loc.start.line === 1);
}
function parseYamlComment(code, path) {
return code.reduce((memo, item) => {
const { value } = item;
const v = value.replace(routeJSXReg, "");
debug.routeBlock(`use ${v} parser`);
try {
const yamlResult = (0, import_yaml.parse)(v);
return __spreadValues(__spreadValues({}, memo), yamlResult);
} catch (err) {
throw new Error(`Invalid YAML format of comment in ${path}
${err.message}`);
}
}, {});
}
async function parseSFC(code) {
try {
const { parse } = await (0, import_local_pkg.importModule)("@vue/compiler-sfc");
return parse(code, {
pad: "space"
}).descriptor || parse({
source: code
});
} catch (e) {
throw new Error(`[vite-plugin-pages] Vue3's "@vue/compiler-sfc" is required.`);
}
}
function parseCustomBlock(block, filePath, options) {
var _a;
const lang = (_a = block.lang) != null ? _a : options.routeBlockLang;
debug.routeBlock(`use ${lang} parser`);
if (lang === "json5") {
try {
return import_json5.default.parse(block.content);
} catch (err) {
throw new Error(`Invalid JSON5 format of <${block.type}> content in ${filePath}
${err.message}`);
}
} else if (lang === "json") {
try {
return JSON.parse(block.content);
} catch (err) {
throw new Error(`Invalid JSON format of <${block.type}> content in ${filePath}
${err.message}`);
}
} else if (lang === "yaml" || lang === "yml") {
try {
return (0, import_yaml.parse)(block.content);
} catch (err) {
throw new Error(`Invalid YAML format of <${block.type}> content in ${filePath}
${err.message}`);
}
}
}
async function getRouteBlock(path, options) {
const content = import_node_fs.default.readFileSync(path, "utf8");
const parsedSFC = await parseSFC(content);
const blockStr = parsedSFC == null ? void 0 : parsedSFC.customBlocks.find((b) => b.type === "route");
const parsedJSX = parseJSX(content);
if (!blockStr && parsedJSX.length === 0)
return;
let result;
if (blockStr)
result = parseCustomBlock(blockStr, path, options);
if (parsedJSX.length > 0)
result = parseYamlComment(parsedJSX, path);
return result;
}
// src/resolvers/vue.ts
function prepareRoutes3(ctx, routes, parent) {
var _a, _b, _c, _d;
for (const route of routes) {
if (route.name)
route.name = route.name.replace(new RegExp(`${ctx.options.routeNameSeparator}index$`), "");
if (parent)
route.path = (_a = route.path) == null ? void 0 : _a.replace(/^\//, "");
if (route.children)
route.children = prepareRoutes3(ctx, route.children, route);
if ((_b = route.children) == null ? void 0 : _b.find((c) => c.name === route.name))
delete route.name;
route.props = true;
delete route.rawRoute;
if (route.customBlock) {
Object.assign(route, route.customBlock || {});
delete route.customBlock;
}
Object.assign(route, ((_d = (_c = ctx.options).extendRoute) == null ? void 0 : _d.call(_c, route, parent)) || {});
}
return routes;
}
async function computeVueRoutes(ctx, customBlockMap) {
var _a, _b;
const { routeStyle, caseSensitive, importPath, routeNameSeparator } = ctx.options;
const pageRoutes = [...ctx.pageRouteMap.values()].sort((a, b) => countSlash(a.route) - countSlash(b.route));
const routes = [];
pageRoutes.forEach((page) => {
const pathNodes = page.route.split("/");
const component = importPath === "relative" ? page.path.replace(ctx.root, "") : page.path;
const customBlock = customBlockMap.get(page.path);
const route = {
name: "",
path: "",
component,
customBlock,
rawRoute: page.route
};
let parentRoutes = routes;
let dynamicRoute = false;
for (let i = 0; i < pathNodes.length; i++) {
const node = pathNodes[i];
const nuxtStyle = routeStyle === "nuxt";
const isDynamic = isDynamicRoute(node, nuxtStyle);
const isCatchAll = isCatchAllRoute(node, nuxtStyle);
const normalizedName = normalizeName(node, isDynamic, nuxtStyle);
const normalizedPath = normalizeCase(normalizedName, caseSensitive);
if (isDynamic)
dynamicRoute = true;
route.name += route.name ? `${routeNameSeparator}${normalizedName}` : normalizedName;
const parent = parentRoutes.find((parent2) => {
return pathNodes.slice(0, i + 1).join("/") === parent2.rawRoute;
});
if (parent) {
parent.children = parent.children || [];
parentRoutes = parent.children;
route.path = "";
} else if (normalizedPath === "index") {
if (!route.path)
route.path = "/";
} else if (normalizedPath !== "index") {
if (isDynamic) {
route.path += `/:${normalizedName}`;
if (isCatchAll) {
if (i === 0)
route.path += "(.*)*";
else
route.path += "(.*)";
} else if (nuxtStyle && i === pathNodes.length - 1) {
const isIndexFound = pageRoutes.find(({ route: route2 }) => {
return route2 === page.route.replace(pathNodes[i], "index");
});
if (!isIndexFound)
route.path += "?";
}
} else {
route.path += `/${normalizedPath}`;
}
}
}
if (dynamicRoute)
parentRoutes.push(route);
else
parentRoutes.unshift(route);
});
let finalRoutes = prepareRoutes3(ctx, routes);
finalRoutes = await ((_b = (_a = ctx.options).onRoutesGenerated) == null ? void 0 : _b.call(_a, finalRoutes)) || finalRoutes;
return finalRoutes;
}
async function resolveVueRoutes(ctx, customBlockMap) {
var _a, _b;
const finalRoutes = await computeVueRoutes(ctx, customBlockMap);
let client = generateClientCode(finalRoutes, ctx.options);
client = await ((_b = (_a = ctx.options).onClientGenerated) == null ? void 0 : _b.call(_a, client)) || client;
return client;
}
function vueResolver() {
const customBlockMap = /* @__PURE__ */ new Map();
async function checkCustomBlockChange(ctx, path) {
var _a;
const exitsCustomBlock = customBlockMap.get(path);
let customBlock;
try {
customBlock = await getRouteBlock(path, ctx.options);
} catch (error) {
(_a = ctx.logger) == null ? void 0 : _a.error(import_picocolors.default.red(`[vite-plugin-pages] ${error.message}`));
return;
}
if (!exitsCustomBlock && !customBlock)
return;
if (!customBlock) {
customBlockMap.delete(path);
ctx.debug.routeBlock("%s deleted", path);
return;
}
if (!exitsCustomBlock || !(0, import_dequal.dequal)(exitsCustomBlock, customBlock)) {
ctx.debug.routeBlock("%s old: %O", path, exitsCustomBlock);
ctx.debug.routeBlock("%s new: %O", path, customBlock);
customBlockMap.set(path, customBlock);
ctx.onUpdate();
}
}
return {
resolveExtensions() {
return ["vue", "ts", "js"];
},
resolveModuleIds() {
return ["~pages", "pages-generated", "virtual:generated-pages"];
},
async resolveRoutes(ctx) {
return resolveVueRoutes(ctx, customBlockMap);
},
async getComputedRoutes(ctx) {
return computeVueRoutes(ctx, customBlockMap);
},
hmr: {
added: async (ctx, path) => checkCustomBlockChange(ctx, path),
changed: async (ctx, path) => checkCustomBlockChange(ctx, path),
removed: async (_ctx, path) => {
customBlockMap.delete(path);
}
}
};
}
// src/options.ts
function resolvePageDirs(dirs, root, exclude) {
dirs = toArray(dirs);
return dirs.flatMap((dir) => {
const option = typeof dir === "string" ? { dir, baseRoute: "" } : dir;
option.dir = slash((0, import_node_path3.resolve)(root, option.dir)).replace(`${root}/`, "");
option.baseRoute = option.baseRoute.replace(/^\//, "").replace(/\/$/, "");
return getPageDirs(option, root, exclude);
});
}
var syncIndexResolver = (filepath, options) => {
for (const page of options.dirs) {
if (page.baseRoute === "" && filepath.startsWith(`/${page.dir}/index`))
return "sync";
}
return "async";
};
function getResolver(originalResolver) {
let resolver = originalResolver || "vue";
if (typeof resolver !== "string")
return resolver;
switch (resolver) {
case "vue":
resolver = vueResolver();
break;
case "react":
resolver = reactResolver();
break;
case "solid":
resolver = solidResolver();
break;
default:
throw new Error(`Unsupported resolver: ${resolver}`);
}
return resolver;
}
function resolveOptions(userOptions, viteRoot) {
var _a;
const {
dirs = ["src/pages"],
routeBlockLang = "json5",
exclude = ["node_modules", ".git", "**/__*__/**"],
caseSensitive = false,
routeNameSeparator = "-",
extendRoute,
onRoutesGenerated,
onClientGenerated
} = userOptions;
const root = viteRoot || slash(import_node_process.default.cwd());
const importMode = userOptions.importMode || syncIndexResolver;
const importPath = userOptions.importPath || "relative";
const resolver = getResolver(userOptions.resolver);
const extensions = userOptions.extensions || resolver.resolveExtensions();
const extensionsRE = new RegExp(`\\.(${extensions.join("|")})$`);
const resolvedDirs = resolvePageDirs(dirs, root, exclude);
const routeStyle = userOptions.routeStyle || "next";
const moduleIds = userOptions.moduleId ? [userOptions.moduleId] : ((_a = resolver.resolveModuleIds) == null ? void 0 : _a.call(resolver)) || MODULE_IDS;
const resolvedOptions = {
dirs: resolvedDirs,
routeStyle,
routeBlockLang,
moduleIds,
root,
extensions,
importMode,
importPath,
exclude,
caseSensitive,
resolver,
extensionsRE,
extendRoute,
onRoutesGenerated,
onClientGenerated,
routeNameSeparator
};
return resolvedOptions;
}
// src/context.ts
var PageContext = class {
constructor(userOptions, viteRoot = import_node_process2.default.cwd()) {
this._pageRouteMap = /* @__PURE__ */ new Map();
this.rawOptions = userOptions;
this.root = slash(viteRoot);
debug.env("root", this.root);
this.options = resolveOptions(userOptions, this.root);
debug.options(this.options);
}
setLogger(logger) {
this.logger = logger;
}
setupViteServer(server) {
if (this._server === server)
return;
this._server = server;
this.setupWatcher(server.watcher);
}
setupWatcher(watcher) {
watcher.on("unlink", async (path) => {
path = slash(path);
if (!isTarget(path, this.options))
return;
await this.removePage(path);
this.onUpdate();
});
watcher.on("add", async (path) => {
path = slash(path);
if (!isTarget(path, this.options))
return;
const page = this.options.dirs.find((i) => path.startsWith(slash((0, import_node_path4.resolve)(this.root, i.dir))));
await this.addPage(path, page);
this.onUpdate();
});
watcher.on("change", async (path) => {
var _a, _b;
path = slash(path);
if (!isTarget(path, this.options))
return;
const page = this._pageRouteMap.get(path);
if (page)
await ((_b = (_a = this.options.resolver.hmr) == null ? void 0 : _a.changed) == null ? void 0 : _b.call(_a, this, path));
});
}
async addPage(path, pageDir) {
var _a, _b;
debug.pages("add", path);
for (const p of toArray(path)) {
const pageDirPath = slash((0, import_node_path4.resolve)(this.root, pageDir.dir));
const extension = this.options.extensions.find((ext) => p.endsWith(`.${ext}`));
if (!extension)
continue;
const route = slash((0, import_node_path4.join)(pageDir.baseRoute, p.replace(`${pageDirPath}/`, "").replace(`.${extension}`, "")));
this._pageRouteMap.set(p, {
path: p,
route
});
await ((_b = (_a = this.options.resolver.hmr) == null ? void 0 : _a.added) == null ? void 0 : _b.call(_a, this, p));
}
}
async removePage(path) {
var _a, _b;
debug.pages("remove", path);
this._pageRouteMap.delete(path);
await ((_b = (_a = this.options.resolver.hmr) == null ? void 0 : _a.removed) == null ? void 0 : _b.call(_a, this, path));
}
onUpdate() {
if (!this._server)
return;
invalidatePagesModule(this._server);
debug.hmr("Reload generated pages.");
this._server.ws.send({
type: "full-reload"
});
}
async resolveRoutes() {
return this.options.resolver.resolveRoutes(this);
}
async searchGlob() {
const pageDirFiles = this.options.dirs.map((page) => {
const pagesDirPath = slash((0, import_node_path4.resolve)(this.options.root, page.dir));
const files = getPageFiles(pagesDirPath, this.options, page);
debug.search(page.dir, files);
return __spreadProps(__spreadValues({}, page), {
files: files.map((file) => slash(file))
});
});
for (const page of pageDirFiles)
await this.addPage(page.files, page);
debug.cache(this.pageRouteMap);
}
get debug() {
return debug;
}
get pageRouteMap() {
return this._pageRouteMap;
}
};
// src/index.ts
function pagesPlugin(userOptions = {}) {
let ctx;
return {
name: "vite-plugin-pages",
enforce: "pre",
async configResolved(config) {
if (!userOptions.resolver && config.plugins.find((i) => i.name.includes("vite:react"))) {
userOptions.resolver = "react";
}
if (!userOptions.resolver && config.plugins.find((i) => i.name.includes("solid"))) {
userOptions.resolver = "solid";
}
ctx = new PageContext(userOptions, config.root);
ctx.setLogger(config.logger);
await ctx.searchGlob();
},
api: {
getResolvedRoutes() {
return ctx.options.resolver.getComputedRoutes(ctx);
}
},
configureServer(server) {
ctx.setupViteServer(server);
},
resolveId(id) {
if (ctx.options.moduleIds.includes(id))
return `${MODULE_ID_VIRTUAL}?id=${id}`;
if (routeBlockQueryRE.test(id))
return ROUTE_BLOCK_ID_VIRTUAL;
return null;
},
async load(id) {
const {
moduleId,
pageId
} = parsePageRequest(id);
if (moduleId === MODULE_ID_VIRTUAL && pageId && ctx.options.moduleIds.includes(pageId))
return ctx.resolveRoutes();
if (id === ROUTE_BLOCK_ID_VIRTUAL) {
return {
code: "export default {};",
map: null
};
}
return null;
}
};
}
var index_default = pagesPlugin;
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
PageContext,
reactResolver,
solidResolver,
syncIndexResolver,
vueResolver
});
//# sourceMappingURL=index.cjs.map