phial 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +27 -0
  3. package/bin/phial.mjs +6 -0
  4. package/dist/cli.d.ts +2 -0
  5. package/dist/cli.js +2 -0
  6. package/dist/index.d.ts +1 -0
  7. package/dist/index.js +2 -0
  8. package/dist/lib/cli/index.d.ts +5 -0
  9. package/dist/lib/cli/index.d.ts.map +1 -0
  10. package/dist/lib/cli/index.js +101 -0
  11. package/dist/lib/cli/index.js.map +1 -0
  12. package/dist/lib/generated-routes.d.ts +176 -0
  13. package/dist/lib/server-routes/errors.js +16 -0
  14. package/dist/lib/server-routes/errors.js.map +1 -0
  15. package/dist/lib/vite-plugin/config.d.ts +54 -0
  16. package/dist/lib/vite-plugin/config.d.ts.map +1 -0
  17. package/dist/lib/vite-plugin/config.js +54 -0
  18. package/dist/lib/vite-plugin/config.js.map +1 -0
  19. package/dist/lib/vite-plugin/generated/client-entry.js +36 -0
  20. package/dist/lib/vite-plugin/generated/client-entry.js.map +1 -0
  21. package/dist/lib/vite-plugin/generated/virtual-modules.js +940 -0
  22. package/dist/lib/vite-plugin/generated/virtual-modules.js.map +1 -0
  23. package/dist/lib/vite-plugin/host/index.d.ts +4 -0
  24. package/dist/lib/vite-plugin/host/index.js +5 -0
  25. package/dist/lib/vite-plugin/host/plugin-build.d.ts +15 -0
  26. package/dist/lib/vite-plugin/host/plugin-build.d.ts.map +1 -0
  27. package/dist/lib/vite-plugin/host/plugin-build.js +242 -0
  28. package/dist/lib/vite-plugin/host/plugin-build.js.map +1 -0
  29. package/dist/lib/vite-plugin/host/plugin-dev-server.d.ts +19 -0
  30. package/dist/lib/vite-plugin/host/plugin-dev-server.d.ts.map +1 -0
  31. package/dist/lib/vite-plugin/host/plugin-dev-server.js +255 -0
  32. package/dist/lib/vite-plugin/host/plugin-dev-server.js.map +1 -0
  33. package/dist/lib/vite-plugin/host/plugin-prepare.d.ts +12 -0
  34. package/dist/lib/vite-plugin/host/plugin-prepare.d.ts.map +1 -0
  35. package/dist/lib/vite-plugin/host/plugin-prepare.js +29 -0
  36. package/dist/lib/vite-plugin/host/plugin-prepare.js.map +1 -0
  37. package/dist/lib/vite-plugin/host/plugin-server.d.ts +19 -0
  38. package/dist/lib/vite-plugin/host/plugin-server.d.ts.map +1 -0
  39. package/dist/lib/vite-plugin/host/plugin-server.js +60 -0
  40. package/dist/lib/vite-plugin/host/plugin-server.js.map +1 -0
  41. package/dist/lib/vite-plugin/index.d.ts +9 -0
  42. package/dist/lib/vite-plugin/index.d.ts.map +1 -0
  43. package/dist/lib/vite-plugin/index.js +261 -0
  44. package/dist/lib/vite-plugin/index.js.map +1 -0
  45. package/dist/lib/vite-plugin/scanners/app-pages-scanner.js +162 -0
  46. package/dist/lib/vite-plugin/scanners/app-pages-scanner.js.map +1 -0
  47. package/dist/lib/vite-plugin/scanners/app-runtime-scanner.js +39 -0
  48. package/dist/lib/vite-plugin/scanners/app-runtime-scanner.js.map +1 -0
  49. package/dist/lib/vite-plugin/scanners/route-manifest.js +60 -0
  50. package/dist/lib/vite-plugin/scanners/route-manifest.js.map +1 -0
  51. package/dist/lib/vite-plugin/scanners/routes-scanner.js +72 -0
  52. package/dist/lib/vite-plugin/scanners/routes-scanner.js.map +1 -0
  53. package/dist/lib/vite-plugin/scanners/scanner-utils.js +129 -0
  54. package/dist/lib/vite-plugin/scanners/scanner-utils.js.map +1 -0
  55. package/dist/lib/vite-plugin/scanners/server-routes-scanner.js +83 -0
  56. package/dist/lib/vite-plugin/scanners/server-routes-scanner.js.map +1 -0
  57. package/dist/lib/vite-plugin/scanners/types-generator.d.ts +9 -0
  58. package/dist/lib/vite-plugin/scanners/types-generator.d.ts.map +1 -0
  59. package/dist/lib/vite-plugin/scanners/types-generator.js +190 -0
  60. package/dist/lib/vite-plugin/scanners/types-generator.js.map +1 -0
  61. package/dist/vite-plugin.d.ts +7 -0
  62. package/dist/vite-plugin.js +8 -0
  63. package/package.json +89 -0
@@ -0,0 +1,72 @@
1
+ import { createRouteManifest } from "./route-manifest.js";
2
+ import { assertServerRouteConflicts, exists, normalizeExtensions, toPosixPath } from "./scanner-utils.js";
3
+ import { scanAppRuntime } from "./app-runtime-scanner.js";
4
+ import { scanAppPageRoutes } from "./app-pages-scanner.js";
5
+ import { scanServerMiddlewareFiles, scanServerRoutes } from "./server-routes-scanner.js";
6
+ import { relative, resolve } from "node:path";
7
+ //#region src/lib/vite-plugin/scanners/routes-scanner.ts
8
+ async function scanRoutes(options = {}) {
9
+ const root = resolve(options.root ?? process.cwd());
10
+ const appDir = resolve(root, options.appDir ?? "app");
11
+ const routesDir = resolve(root, options.routesDir ?? `${options.appDir ?? "app"}/pages`);
12
+ const serverRoutesDir = resolve(root, options.serverRoutesDir ?? "server/routes");
13
+ const serverMiddlewareDir = resolve(root, options.serverMiddlewareDir ?? "server/middleware");
14
+ const extensions = normalizeExtensions(options.extensions);
15
+ const serverExtensions = extensions.filter((extension) => extension !== ".vue");
16
+ const app = await scanAppRuntime({
17
+ root,
18
+ appDir,
19
+ extensions
20
+ });
21
+ const serverRoutes = await scanServerRoutes({
22
+ root,
23
+ routesDir: serverRoutesDir,
24
+ extensions: serverExtensions
25
+ });
26
+ const serverMiddleware = await scanServerMiddlewareFiles({
27
+ root,
28
+ middlewareDir: serverMiddlewareDir,
29
+ extensions: serverExtensions
30
+ });
31
+ const server = {
32
+ routesDir: toPosixPath(relative(root, serverRoutesDir)),
33
+ middlewareDir: toPosixPath(relative(root, serverMiddlewareDir)),
34
+ routes: serverRoutes,
35
+ middleware: serverMiddleware
36
+ };
37
+ if (!await exists(routesDir)) {
38
+ assertServerRouteConflicts([], server.routes);
39
+ return {
40
+ root,
41
+ appDir,
42
+ routesDir,
43
+ serverRoutesDir,
44
+ serverMiddlewareDir,
45
+ app,
46
+ server,
47
+ modules: [],
48
+ manifest: []
49
+ };
50
+ }
51
+ const modules = await scanAppPageRoutes({
52
+ root,
53
+ routesDir,
54
+ extensions
55
+ });
56
+ assertServerRouteConflicts(modules, server.routes);
57
+ return {
58
+ root,
59
+ appDir,
60
+ routesDir,
61
+ serverRoutesDir,
62
+ serverMiddlewareDir,
63
+ app,
64
+ server,
65
+ modules,
66
+ manifest: createRouteManifest(modules)
67
+ };
68
+ }
69
+ //#endregion
70
+ export { scanRoutes };
71
+
72
+ //# sourceMappingURL=routes-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"routes-scanner.js","names":[],"sources":["../../../../src/lib/vite-plugin/scanners/routes-scanner.ts"],"sourcesContent":["import { relative, resolve } from \"node:path\";\nimport { scanAppRuntime } from \"./app-runtime-scanner\";\nimport { scanAppPageRoutes } from \"./app-pages-scanner\";\nimport { createRouteManifest, type ScannedRoutesResult } from \"./route-manifest\";\nimport {\n assertServerRouteConflicts,\n DEFAULT_APP_DIR,\n DEFAULT_SERVER_MIDDLEWARE_DIR,\n DEFAULT_SERVER_ROUTES_DIR,\n exists,\n normalizeExtensions,\n toPosixPath,\n} from \"./scanner-utils\";\nimport { scanServerMiddlewareFiles, scanServerRoutes } from \"./server-routes-scanner\";\n\nexport interface RouteScannerOptions {\n root?: string;\n appDir?: string;\n routesDir?: string;\n serverRoutesDir?: string;\n serverMiddlewareDir?: string;\n extensions?: string[];\n}\n\nexport async function scanRoutes(options: RouteScannerOptions = {}): Promise<ScannedRoutesResult> {\n const root = resolve(options.root ?? process.cwd());\n const appDir = resolve(root, options.appDir ?? DEFAULT_APP_DIR);\n const routesDir = resolve(\n root,\n options.routesDir ?? `${options.appDir ?? DEFAULT_APP_DIR}/pages`,\n );\n const serverRoutesDir = resolve(root, options.serverRoutesDir ?? DEFAULT_SERVER_ROUTES_DIR);\n const serverMiddlewareDir = resolve(\n root,\n options.serverMiddlewareDir ?? DEFAULT_SERVER_MIDDLEWARE_DIR,\n );\n const extensions = normalizeExtensions(options.extensions);\n const serverExtensions = extensions.filter((extension) => extension !== \".vue\");\n const app = await scanAppRuntime({\n root,\n appDir,\n extensions,\n });\n const serverRoutes = await scanServerRoutes({\n root,\n routesDir: serverRoutesDir,\n extensions: serverExtensions,\n });\n const serverMiddleware = await scanServerMiddlewareFiles({\n root,\n middlewareDir: serverMiddlewareDir,\n extensions: serverExtensions,\n });\n const server = {\n routesDir: toPosixPath(relative(root, serverRoutesDir)),\n middlewareDir: toPosixPath(relative(root, serverMiddlewareDir)),\n routes: serverRoutes,\n middleware: serverMiddleware,\n };\n\n if (!(await exists(routesDir))) {\n assertServerRouteConflicts([], server.routes);\n return {\n root,\n appDir,\n routesDir,\n serverRoutesDir,\n serverMiddlewareDir,\n app,\n server,\n modules: [],\n manifest: [],\n };\n }\n\n const modules = await scanAppPageRoutes({\n root,\n routesDir,\n extensions,\n });\n assertServerRouteConflicts(modules, server.routes);\n\n return {\n root,\n appDir,\n routesDir,\n serverRoutesDir,\n serverMiddlewareDir,\n app,\n server,\n modules,\n manifest: createRouteManifest(modules),\n };\n}\n"],"mappings":";;;;;;;AAwBA,eAAsB,WAAW,UAA+B,EAAE,EAAgC;CAChG,MAAM,OAAO,QAAQ,QAAQ,QAAQ,QAAQ,KAAK,CAAC;CACnD,MAAM,SAAS,QAAQ,MAAM,QAAQ,UAAA,MAA0B;CAC/D,MAAM,YAAY,QAChB,MACA,QAAQ,aAAa,GAAG,QAAQ,UAAA,MAA0B,QAC3D;CACD,MAAM,kBAAkB,QAAQ,MAAM,QAAQ,mBAAA,gBAA6C;CAC3F,MAAM,sBAAsB,QAC1B,MACA,QAAQ,uBAAA,oBACT;CACD,MAAM,aAAa,oBAAoB,QAAQ,WAAW;CAC1D,MAAM,mBAAmB,WAAW,QAAQ,cAAc,cAAc,OAAO;CAC/E,MAAM,MAAM,MAAM,eAAe;EAC/B;EACA;EACA;EACD,CAAC;CACF,MAAM,eAAe,MAAM,iBAAiB;EAC1C;EACA,WAAW;EACX,YAAY;EACb,CAAC;CACF,MAAM,mBAAmB,MAAM,0BAA0B;EACvD;EACA,eAAe;EACf,YAAY;EACb,CAAC;CACF,MAAM,SAAS;EACb,WAAW,YAAY,SAAS,MAAM,gBAAgB,CAAC;EACvD,eAAe,YAAY,SAAS,MAAM,oBAAoB,CAAC;EAC/D,QAAQ;EACR,YAAY;EACb;AAED,KAAI,CAAE,MAAM,OAAO,UAAU,EAAG;AAC9B,6BAA2B,EAAE,EAAE,OAAO,OAAO;AAC7C,SAAO;GACL;GACA;GACA;GACA;GACA;GACA;GACA;GACA,SAAS,EAAE;GACX,UAAU,EAAE;GACb;;CAGH,MAAM,UAAU,MAAM,kBAAkB;EACtC;EACA;EACA;EACD,CAAC;AACF,4BAA2B,SAAS,OAAO,OAAO;AAElD,QAAO;EACL;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA,UAAU,oBAAoB,QAAQ;EACvC"}
@@ -0,0 +1,129 @@
1
+ import { collectAppPagePaths } from "./route-manifest.js";
2
+ import { basename, extname, relative, resolve } from "node:path";
3
+ import { readdir, stat } from "node:fs/promises";
4
+ //#region src/lib/vite-plugin/scanners/scanner-utils.ts
5
+ const DEFAULT_SERVER_ROUTES_DIR = "server/routes";
6
+ const DEFAULT_SERVER_MIDDLEWARE_DIR = "server/middleware";
7
+ const DEFAULT_EXTENSIONS = [
8
+ ".vue",
9
+ ".ts",
10
+ ".js",
11
+ ".tsx",
12
+ ".jsx"
13
+ ];
14
+ const ROUTE_FILE_BASENAMES = [
15
+ "layout",
16
+ "page",
17
+ "error",
18
+ "loading",
19
+ "action",
20
+ "loader",
21
+ "middleware"
22
+ ];
23
+ const DIRECTORY_MIDDLEWARE_BASENAME = "_middleware";
24
+ function normalizeExtensions(extensions) {
25
+ const resolved = extensions?.length ? extensions : DEFAULT_EXTENSIONS;
26
+ return Array.from(new Set(resolved.map((extension) => extension.startsWith(".") ? extension : `.${extension}`)));
27
+ }
28
+ function normalizeDirectoryMiddlewareExtensions(extensions) {
29
+ const filtered = extensions.filter((extension) => extension !== ".vue");
30
+ return filtered.length > 0 ? filtered : extensions;
31
+ }
32
+ async function exists(path) {
33
+ try {
34
+ await stat(path);
35
+ return true;
36
+ } catch {
37
+ return false;
38
+ }
39
+ }
40
+ async function resolveDirectoryFiles(directory) {
41
+ if (!await exists(directory)) return [];
42
+ return (await readdir(directory, { withFileTypes: true })).filter((entry) => entry.isFile()).map((entry) => entry.name).sort();
43
+ }
44
+ async function resolveNestedFiles(directory, relativeDir = "") {
45
+ if (!await exists(directory)) return [];
46
+ const entries = await readdir(resolve(directory, relativeDir), { withFileTypes: true });
47
+ const files = [];
48
+ for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
49
+ if (entry.name.startsWith(".")) continue;
50
+ const nextRelativePath = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;
51
+ if (entry.isDirectory()) {
52
+ files.push(...await resolveNestedFiles(directory, nextRelativePath));
53
+ continue;
54
+ }
55
+ if (entry.isFile()) files.push(toPosixPath(nextRelativePath));
56
+ }
57
+ return files;
58
+ }
59
+ function resolveNamedFile(directory, files, baseName, extensions) {
60
+ const matches = files.filter((file) => {
61
+ const extension = extname(file);
62
+ return extensions.includes(extension) && file.slice(0, -extension.length) === baseName;
63
+ });
64
+ if (matches.length <= 1) return matches[0];
65
+ throw new Error(`Duplicate ${baseName} files found in ${directory || "."}: ${matches.join(", ")}`);
66
+ }
67
+ function resolveSingleEntryFile(files, directory, label) {
68
+ if (files.length <= 1) return files[0];
69
+ throw new Error(`Duplicate ${label} files found in ${directory || "."}: ${files.map((file) => basename(file)).join(", ")}`);
70
+ }
71
+ function collectEntryFiles(entries, kind) {
72
+ return entries.filter((entry) => entry.kind === kind).map((entry) => entry.file);
73
+ }
74
+ function toRootRelativeRouteFile(root, routesDir, file) {
75
+ return toPosixPath(relative(root, resolve(routesDir, file)));
76
+ }
77
+ function getEntryBaseName(entry) {
78
+ const extension = extname(entry);
79
+ const fileName = entry.slice(entry.lastIndexOf("/") + 1);
80
+ return fileName.slice(0, fileName.length - extension.length);
81
+ }
82
+ function getLastPathSegment(path) {
83
+ const separatorIndex = path.lastIndexOf("/");
84
+ return separatorIndex >= 0 ? path.slice(separatorIndex + 1) : path;
85
+ }
86
+ function isRouteDirectory(name) {
87
+ return !name.startsWith(".") && !name.startsWith("_");
88
+ }
89
+ function assertServerRouteConflicts(appModules, serverRoutes) {
90
+ if (serverRoutes.length === 0) return;
91
+ const appPaths = new Set(collectAppPagePaths(appModules));
92
+ for (const serverRoute of serverRoutes) for (const appPath of appPaths) {
93
+ if (!routePatternsOverlap(appPath, serverRoute.path)) continue;
94
+ throw new Error(`Server route "${serverRoute.path}" from ${serverRoute.file} conflicts with app page path "${appPath}". Phial does not split path ownership between app/pages and server/routes, even across different HTTP methods.`);
95
+ }
96
+ }
97
+ function routePatternsOverlap(leftPath, rightPath) {
98
+ const leftSegments = routePatternSegments(leftPath);
99
+ const rightSegments = routePatternSegments(rightPath);
100
+ const memo = /* @__PURE__ */ new Map();
101
+ return visit(0, 0);
102
+ function visit(leftIndex, rightIndex) {
103
+ const key = `${leftIndex}:${rightIndex}`;
104
+ const cached = memo.get(key);
105
+ if (cached !== void 0) return cached;
106
+ let result = false;
107
+ if (leftIndex === leftSegments.length && rightIndex === rightSegments.length) result = true;
108
+ else if (leftIndex < leftSegments.length && leftSegments[leftIndex] === "*") result = leftIndex === leftSegments.length - 1 || visit(leftIndex + 1, rightIndex) || rightIndex < rightSegments.length && visit(leftIndex, rightIndex + 1);
109
+ else if (rightIndex < rightSegments.length && rightSegments[rightIndex] === "*") result = rightIndex === rightSegments.length - 1 || visit(leftIndex, rightIndex + 1) || leftIndex < leftSegments.length && visit(leftIndex + 1, rightIndex);
110
+ else if (leftIndex < leftSegments.length && rightIndex < rightSegments.length) result = routeSegmentsCompatible(leftSegments[leftIndex], rightSegments[rightIndex]) && visit(leftIndex + 1, rightIndex + 1);
111
+ memo.set(key, result);
112
+ return result;
113
+ }
114
+ }
115
+ function routeSegmentsCompatible(left, right) {
116
+ if (left === right) return true;
117
+ return left.startsWith(":") || right.startsWith(":");
118
+ }
119
+ function routePatternSegments(path) {
120
+ if (path === "/" || !path) return [];
121
+ return path.split("/").filter(Boolean);
122
+ }
123
+ function toPosixPath(path) {
124
+ return path.replace(/\\/g, "/");
125
+ }
126
+ //#endregion
127
+ export { DEFAULT_SERVER_MIDDLEWARE_DIR, DEFAULT_SERVER_ROUTES_DIR, DIRECTORY_MIDDLEWARE_BASENAME, ROUTE_FILE_BASENAMES, assertServerRouteConflicts, collectEntryFiles, exists, getEntryBaseName, getLastPathSegment, isRouteDirectory, normalizeDirectoryMiddlewareExtensions, normalizeExtensions, resolveDirectoryFiles, resolveNamedFile, resolveNestedFiles, resolveSingleEntryFile, toPosixPath, toRootRelativeRouteFile };
128
+
129
+ //# sourceMappingURL=scanner-utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner-utils.js","names":[],"sources":["../../../../src/lib/vite-plugin/scanners/scanner-utils.ts"],"sourcesContent":["import { readdir, stat } from \"node:fs/promises\";\nimport { basename, extname, relative, resolve } from \"node:path\";\nimport type { ScannedRouteModule, ScannedServerRoute } from \"./route-manifest\";\nimport { collectAppPagePaths } from \"./route-manifest\";\n\nexport const DEFAULT_APP_DIR = \"app\";\nexport const DEFAULT_SERVER_ROUTES_DIR = \"server/routes\";\nexport const DEFAULT_SERVER_MIDDLEWARE_DIR = \"server/middleware\";\nexport const DEFAULT_EXTENSIONS = [\".vue\", \".ts\", \".js\", \".tsx\", \".jsx\"];\nexport const ROUTE_FILE_BASENAMES = [\n \"layout\",\n \"page\",\n \"error\",\n \"loading\",\n \"action\",\n \"loader\",\n \"middleware\",\n] as const;\nexport const DIRECTORY_MIDDLEWARE_BASENAME = \"_middleware\";\n\nexport type RouteFileBaseName = (typeof ROUTE_FILE_BASENAMES)[number];\nexport type AppEntryKind = RouteFileBaseName | \"directory-middleware\";\nexport type ServerEntryKind = \"route\" | \"directory-middleware\";\n\nexport function normalizeExtensions(extensions?: string[]): string[] {\n const resolved = extensions?.length ? extensions : DEFAULT_EXTENSIONS;\n return Array.from(\n new Set(resolved.map((extension) => (extension.startsWith(\".\") ? extension : `.${extension}`))),\n );\n}\n\nexport function normalizeDirectoryMiddlewareExtensions(extensions: string[]): string[] {\n const filtered = extensions.filter((extension) => extension !== \".vue\");\n return filtered.length > 0 ? filtered : extensions;\n}\n\nexport async function exists(path: string): Promise<boolean> {\n try {\n await stat(path);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function resolveDirectoryFiles(directory: string): Promise<string[]> {\n if (!(await exists(directory))) {\n return [];\n }\n\n const entries = await readdir(directory, {\n withFileTypes: true,\n });\n\n return entries\n .filter((entry) => entry.isFile())\n .map((entry) => entry.name)\n .sort();\n}\n\nexport async function resolveNestedFiles(directory: string, relativeDir = \"\"): Promise<string[]> {\n if (!(await exists(directory))) {\n return [];\n }\n\n const entries = await readdir(resolve(directory, relativeDir), {\n withFileTypes: true,\n });\n const files: string[] = [];\n\n for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {\n if (entry.name.startsWith(\".\")) {\n continue;\n }\n\n const nextRelativePath = relativeDir ? `${relativeDir}/${entry.name}` : entry.name;\n if (entry.isDirectory()) {\n files.push(...(await resolveNestedFiles(directory, nextRelativePath)));\n continue;\n }\n\n if (entry.isFile()) {\n files.push(toPosixPath(nextRelativePath));\n }\n }\n\n return files;\n}\n\nexport function resolveNamedFile(\n directory: string,\n files: string[],\n baseName: string,\n extensions: string[],\n): string | undefined {\n const matches = files.filter((file) => {\n const extension = extname(file);\n return extensions.includes(extension) && file.slice(0, -extension.length) === baseName;\n });\n\n if (matches.length <= 1) {\n return matches[0];\n }\n\n throw new Error(\n `Duplicate ${baseName} files found in ${directory || \".\"}: ${matches.join(\", \")}`,\n );\n}\n\nexport function resolveSingleEntryFile(\n files: string[],\n directory: string,\n label: string,\n): string | undefined {\n if (files.length <= 1) {\n return files[0];\n }\n\n throw new Error(\n `Duplicate ${label} files found in ${directory || \".\"}: ${files.map((file) => basename(file)).join(\", \")}`,\n );\n}\n\nexport function collectEntryFiles<TEntryKind extends string>(\n entries: Array<{\n kind: TEntryKind;\n file: string;\n }>,\n kind: TEntryKind,\n): string[] {\n return entries.filter((entry) => entry.kind === kind).map((entry) => entry.file);\n}\n\nexport function toRootRelativeRouteFile(root: string, routesDir: string, file: string): string {\n return toPosixPath(relative(root, resolve(routesDir, file)));\n}\n\nexport function getEntryBaseName(entry: string): string {\n const extension = extname(entry);\n const fileName = entry.slice(entry.lastIndexOf(\"/\") + 1);\n return fileName.slice(0, fileName.length - extension.length);\n}\n\nexport function getLastPathSegment(path: string): string {\n const separatorIndex = path.lastIndexOf(\"/\");\n return separatorIndex >= 0 ? path.slice(separatorIndex + 1) : path;\n}\n\nexport function isRouteDirectory(name: string): boolean {\n return !name.startsWith(\".\") && !name.startsWith(\"_\");\n}\n\nexport function assertServerRouteConflicts(\n appModules: ScannedRouteModule[],\n serverRoutes: ScannedServerRoute[],\n): void {\n if (serverRoutes.length === 0) {\n return;\n }\n\n const appPaths = new Set(collectAppPagePaths(appModules));\n\n for (const serverRoute of serverRoutes) {\n for (const appPath of appPaths) {\n if (!routePatternsOverlap(appPath, serverRoute.path)) {\n continue;\n }\n\n throw new Error(\n `Server route \"${serverRoute.path}\" from ${serverRoute.file} conflicts with app page path \"${appPath}\". Phial does not split path ownership between app/pages and server/routes, even across different HTTP methods.`,\n );\n }\n }\n}\n\nfunction routePatternsOverlap(leftPath: string, rightPath: string): boolean {\n const leftSegments = routePatternSegments(leftPath);\n const rightSegments = routePatternSegments(rightPath);\n const memo = new Map<string, boolean>();\n\n return visit(0, 0);\n\n function visit(leftIndex: number, rightIndex: number): boolean {\n const key = `${leftIndex}:${rightIndex}`;\n const cached = memo.get(key);\n if (cached !== undefined) {\n return cached;\n }\n\n let result = false;\n\n if (leftIndex === leftSegments.length && rightIndex === rightSegments.length) {\n result = true;\n } else if (leftIndex < leftSegments.length && leftSegments[leftIndex] === \"*\") {\n result =\n leftIndex === leftSegments.length - 1 ||\n visit(leftIndex + 1, rightIndex) ||\n (rightIndex < rightSegments.length && visit(leftIndex, rightIndex + 1));\n } else if (rightIndex < rightSegments.length && rightSegments[rightIndex] === \"*\") {\n result =\n rightIndex === rightSegments.length - 1 ||\n visit(leftIndex, rightIndex + 1) ||\n (leftIndex < leftSegments.length && visit(leftIndex + 1, rightIndex));\n } else if (leftIndex < leftSegments.length && rightIndex < rightSegments.length) {\n result =\n routeSegmentsCompatible(leftSegments[leftIndex], rightSegments[rightIndex]) &&\n visit(leftIndex + 1, rightIndex + 1);\n }\n\n memo.set(key, result);\n return result;\n }\n}\n\nfunction routeSegmentsCompatible(left: string, right: string): boolean {\n if (left === right) {\n return true;\n }\n\n return left.startsWith(\":\") || right.startsWith(\":\");\n}\n\nfunction routePatternSegments(path: string): string[] {\n if (path === \"/\" || !path) {\n return [];\n }\n\n return path.split(\"/\").filter(Boolean);\n}\n\nexport function toPosixPath(path: string): string {\n return path.replace(/\\\\/g, \"/\");\n}\n"],"mappings":"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"}
@@ -0,0 +1,83 @@
1
+ import { DIRECTORY_MIDDLEWARE_BASENAME, collectEntryFiles, getEntryBaseName, normalizeDirectoryMiddlewareExtensions, resolveNestedFiles, resolveSingleEntryFile, toPosixPath, toRootRelativeRouteFile } from "./scanner-utils.js";
2
+ import { rethrowServerRouteBuildError } from "../../server-routes/errors.js";
3
+ import { extname, relative, resolve } from "node:path";
4
+ import { build } from "fs-route-ir";
5
+ //#region src/lib/vite-plugin/scanners/server-routes-scanner.ts
6
+ async function scanServerRoutes(options) {
7
+ const files = await resolveNestedFiles(options.routesDir);
8
+ if (files.length === 0) return [];
9
+ const directoryMiddlewareExtensions = normalizeDirectoryMiddlewareExtensions(options.extensions);
10
+ let result;
11
+ try {
12
+ result = build(files, {
13
+ profile: "file-based",
14
+ root: "",
15
+ ignore(entry, kind) {
16
+ if (kind === "dir") return false;
17
+ return !options.extensions.includes(extname(entry));
18
+ },
19
+ defineEntry({ file, baseName }) {
20
+ if (baseName === "_middleware") {
21
+ if (!directoryMiddlewareExtensions.includes(extname(file))) return null;
22
+ return {
23
+ kind: "directory-middleware",
24
+ scope: "directory"
25
+ };
26
+ }
27
+ return { kind: "route" };
28
+ },
29
+ isRouteFile(file) {
30
+ return getEntryBaseName(file) !== DIRECTORY_MIDDLEWARE_BASENAME;
31
+ }
32
+ });
33
+ } catch (error) {
34
+ rethrowServerRouteBuildError(error);
35
+ }
36
+ return collectServerRoutes(result.tree.nodes, options);
37
+ }
38
+ async function scanServerMiddlewareFiles(options) {
39
+ const entries = await resolveNestedFiles(options.middlewareDir);
40
+ const registry = /* @__PURE__ */ new Map();
41
+ for (const entry of entries) {
42
+ const extension = extname(entry);
43
+ if (!options.extensions.includes(extension)) continue;
44
+ const middlewareName = toPosixPath(entry.slice(0, -extension.length));
45
+ if (registry.has(middlewareName)) throw new Error(`Duplicate server middleware definitions found for "${middlewareName}" in server/middleware.`);
46
+ registry.set(middlewareName, toPosixPath(relative(options.root, resolve(options.middlewareDir, entry))));
47
+ }
48
+ return Object.fromEntries([...registry.entries()].sort(([left], [right]) => left.localeCompare(right)));
49
+ }
50
+ function collectServerRoutes(nodes, options) {
51
+ const routes = [];
52
+ for (const node of nodes) visit(node, []);
53
+ return routes.sort((left, right) => left.path.localeCompare(right.path) || left.id.localeCompare(right.id));
54
+ function visit(node, inheritedDirectoryMiddleware) {
55
+ if (isDirectoryContainerNode(node)) {
56
+ const localDirectoryMiddleware = collectDirectoryMiddlewareEntries(node, options);
57
+ const nextDirectoryMiddleware = localDirectoryMiddleware.length > 0 ? [...inheritedDirectoryMiddleware, ...localDirectoryMiddleware] : inheritedDirectoryMiddleware;
58
+ for (const child of node.children) visit(child, nextDirectoryMiddleware);
59
+ return;
60
+ }
61
+ const routeFile = resolveSingleEntryFile(collectEntryFiles(node.entries, "route"), node.dir, "route");
62
+ if (!routeFile) throw new Error(`Route leaf "${node.id}" is missing a route file entry.`);
63
+ routes.push({
64
+ id: node.id,
65
+ file: toRootRelativeRouteFile(options.root, options.routesDir, routeFile),
66
+ absoluteFile: toPosixPath(resolve(options.routesDir, routeFile)),
67
+ directoryMiddleware: inheritedDirectoryMiddleware,
68
+ path: node.pattern
69
+ });
70
+ }
71
+ }
72
+ function collectDirectoryMiddlewareEntries(node, options) {
73
+ const file = resolveSingleEntryFile(collectEntryFiles(node.entries, "directory-middleware"), node.dir, DIRECTORY_MIDDLEWARE_BASENAME);
74
+ if (!file) return [];
75
+ return [toRootRelativeRouteFile(options.root, options.routesDir, file)];
76
+ }
77
+ function isDirectoryContainerNode(node) {
78
+ return node.id.startsWith("dir:");
79
+ }
80
+ //#endregion
81
+ export { scanServerMiddlewareFiles, scanServerRoutes };
82
+
83
+ //# sourceMappingURL=server-routes-scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-routes-scanner.js","names":[],"sources":["../../../../src/lib/vite-plugin/scanners/server-routes-scanner.ts"],"sourcesContent":["import { extname, relative, resolve } from \"node:path\";\nimport { build, type RouteNode } from \"fs-route-ir\";\nimport type { ScannedServerRoute } from \"./route-manifest\";\nimport { rethrowServerRouteBuildError } from \"../../server-routes/errors\";\nimport {\n collectEntryFiles,\n DIRECTORY_MIDDLEWARE_BASENAME,\n getEntryBaseName,\n normalizeDirectoryMiddlewareExtensions,\n resolveNestedFiles,\n resolveSingleEntryFile,\n toPosixPath,\n toRootRelativeRouteFile,\n type ServerEntryKind,\n} from \"./scanner-utils\";\n\nexport async function scanServerRoutes(options: {\n root: string;\n routesDir: string;\n extensions: string[];\n}): Promise<ScannedServerRoute[]> {\n const files = await resolveNestedFiles(options.routesDir);\n if (files.length === 0) {\n return [];\n }\n\n const directoryMiddlewareExtensions = normalizeDirectoryMiddlewareExtensions(options.extensions);\n let result;\n try {\n result = build(files, {\n profile: \"file-based\",\n root: \"\",\n ignore(entry, kind) {\n if (kind === \"dir\") {\n return false;\n }\n\n return !options.extensions.includes(extname(entry));\n },\n defineEntry({ file, baseName }) {\n if (baseName === DIRECTORY_MIDDLEWARE_BASENAME) {\n if (!directoryMiddlewareExtensions.includes(extname(file))) {\n return null;\n }\n\n return {\n kind: \"directory-middleware\" as const,\n scope: \"directory\" as const,\n };\n }\n\n return {\n kind: \"route\" as const,\n };\n },\n isRouteFile(file) {\n return getEntryBaseName(file) !== DIRECTORY_MIDDLEWARE_BASENAME;\n },\n });\n } catch (error) {\n rethrowServerRouteBuildError(error);\n }\n\n return collectServerRoutes(result.tree.nodes, options);\n}\n\nexport async function scanServerMiddlewareFiles(options: {\n root: string;\n middlewareDir: string;\n extensions: string[];\n}): Promise<Record<string, string>> {\n const entries = await resolveNestedFiles(options.middlewareDir);\n const registry = new Map<string, string>();\n\n for (const entry of entries) {\n const extension = extname(entry);\n if (!options.extensions.includes(extension)) {\n continue;\n }\n\n const middlewareName = toPosixPath(entry.slice(0, -extension.length));\n if (registry.has(middlewareName)) {\n throw new Error(\n `Duplicate server middleware definitions found for \"${middlewareName}\" in server/middleware.`,\n );\n }\n\n registry.set(\n middlewareName,\n toPosixPath(relative(options.root, resolve(options.middlewareDir, entry))),\n );\n }\n\n return Object.fromEntries(\n [...registry.entries()].sort(([left], [right]) => left.localeCompare(right)),\n );\n}\n\nfunction collectServerRoutes(\n nodes: RouteNode<unknown, ServerEntryKind>[],\n options: {\n root: string;\n routesDir: string;\n },\n): ScannedServerRoute[] {\n const routes: ScannedServerRoute[] = [];\n\n for (const node of nodes) {\n visit(node, []);\n }\n\n return routes.sort(\n (left, right) => left.path.localeCompare(right.path) || left.id.localeCompare(right.id),\n );\n\n function visit(\n node: RouteNode<unknown, ServerEntryKind>,\n inheritedDirectoryMiddleware: string[],\n ): void {\n if (isDirectoryContainerNode(node)) {\n const localDirectoryMiddleware = collectDirectoryMiddlewareEntries(node, options);\n const nextDirectoryMiddleware =\n localDirectoryMiddleware.length > 0\n ? [...inheritedDirectoryMiddleware, ...localDirectoryMiddleware]\n : inheritedDirectoryMiddleware;\n\n for (const child of node.children) {\n visit(child, nextDirectoryMiddleware);\n }\n\n return;\n }\n\n const routeFile = resolveSingleEntryFile(\n collectEntryFiles(node.entries, \"route\"),\n node.dir,\n \"route\",\n );\n if (!routeFile) {\n throw new Error(`Route leaf \"${node.id}\" is missing a route file entry.`);\n }\n\n routes.push({\n id: node.id,\n file: toRootRelativeRouteFile(options.root, options.routesDir, routeFile),\n absoluteFile: toPosixPath(resolve(options.routesDir, routeFile)),\n directoryMiddleware: inheritedDirectoryMiddleware,\n path: node.pattern,\n });\n }\n}\n\nfunction collectDirectoryMiddlewareEntries(\n node: RouteNode<unknown, ServerEntryKind>,\n options: {\n root: string;\n routesDir: string;\n },\n): string[] {\n const file = resolveSingleEntryFile(\n collectEntryFiles(node.entries, \"directory-middleware\"),\n node.dir,\n DIRECTORY_MIDDLEWARE_BASENAME,\n );\n if (!file) {\n return [];\n }\n\n return [toRootRelativeRouteFile(options.root, options.routesDir, file)];\n}\n\nfunction isDirectoryContainerNode<TMeta, TEntryKind extends string>(\n node: RouteNode<TMeta, TEntryKind>,\n): boolean {\n return node.id.startsWith(\"dir:\");\n}\n"],"mappings":";;;;;AAgBA,eAAsB,iBAAiB,SAIL;CAChC,MAAM,QAAQ,MAAM,mBAAmB,QAAQ,UAAU;AACzD,KAAI,MAAM,WAAW,EACnB,QAAO,EAAE;CAGX,MAAM,gCAAgC,uCAAuC,QAAQ,WAAW;CAChG,IAAI;AACJ,KAAI;AACF,WAAS,MAAM,OAAO;GACpB,SAAS;GACT,MAAM;GACN,OAAO,OAAO,MAAM;AAClB,QAAI,SAAS,MACX,QAAO;AAGT,WAAO,CAAC,QAAQ,WAAW,SAAS,QAAQ,MAAM,CAAC;;GAErD,YAAY,EAAE,MAAM,YAAY;AAC9B,QAAI,aAAA,eAA4C;AAC9C,SAAI,CAAC,8BAA8B,SAAS,QAAQ,KAAK,CAAC,CACxD,QAAO;AAGT,YAAO;MACL,MAAM;MACN,OAAO;MACR;;AAGH,WAAO,EACL,MAAM,SACP;;GAEH,YAAY,MAAM;AAChB,WAAO,iBAAiB,KAAK,KAAK;;GAErC,CAAC;UACK,OAAO;AACd,+BAA6B,MAAM;;AAGrC,QAAO,oBAAoB,OAAO,KAAK,OAAO,QAAQ;;AAGxD,eAAsB,0BAA0B,SAIZ;CAClC,MAAM,UAAU,MAAM,mBAAmB,QAAQ,cAAc;CAC/D,MAAM,2BAAW,IAAI,KAAqB;AAE1C,MAAK,MAAM,SAAS,SAAS;EAC3B,MAAM,YAAY,QAAQ,MAAM;AAChC,MAAI,CAAC,QAAQ,WAAW,SAAS,UAAU,CACzC;EAGF,MAAM,iBAAiB,YAAY,MAAM,MAAM,GAAG,CAAC,UAAU,OAAO,CAAC;AACrE,MAAI,SAAS,IAAI,eAAe,CAC9B,OAAM,IAAI,MACR,sDAAsD,eAAe,yBACtE;AAGH,WAAS,IACP,gBACA,YAAY,SAAS,QAAQ,MAAM,QAAQ,QAAQ,eAAe,MAAM,CAAC,CAAC,CAC3E;;AAGH,QAAO,OAAO,YACZ,CAAC,GAAG,SAAS,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,KAAK,cAAc,MAAM,CAAC,CAC7E;;AAGH,SAAS,oBACP,OACA,SAIsB;CACtB,MAAM,SAA+B,EAAE;AAEvC,MAAK,MAAM,QAAQ,MACjB,OAAM,MAAM,EAAE,CAAC;AAGjB,QAAO,OAAO,MACX,MAAM,UAAU,KAAK,KAAK,cAAc,MAAM,KAAK,IAAI,KAAK,GAAG,cAAc,MAAM,GAAG,CACxF;CAED,SAAS,MACP,MACA,8BACM;AACN,MAAI,yBAAyB,KAAK,EAAE;GAClC,MAAM,2BAA2B,kCAAkC,MAAM,QAAQ;GACjF,MAAM,0BACJ,yBAAyB,SAAS,IAC9B,CAAC,GAAG,8BAA8B,GAAG,yBAAyB,GAC9D;AAEN,QAAK,MAAM,SAAS,KAAK,SACvB,OAAM,OAAO,wBAAwB;AAGvC;;EAGF,MAAM,YAAY,uBAChB,kBAAkB,KAAK,SAAS,QAAQ,EACxC,KAAK,KACL,QACD;AACD,MAAI,CAAC,UACH,OAAM,IAAI,MAAM,eAAe,KAAK,GAAG,kCAAkC;AAG3E,SAAO,KAAK;GACV,IAAI,KAAK;GACT,MAAM,wBAAwB,QAAQ,MAAM,QAAQ,WAAW,UAAU;GACzE,cAAc,YAAY,QAAQ,QAAQ,WAAW,UAAU,CAAC;GAChE,qBAAqB;GACrB,MAAM,KAAK;GACZ,CAAC;;;AAIN,SAAS,kCACP,MACA,SAIU;CACV,MAAM,OAAO,uBACX,kBAAkB,KAAK,SAAS,uBAAuB,EACvD,KAAK,KACL,8BACD;AACD,KAAI,CAAC,KACH,QAAO,EAAE;AAGX,QAAO,CAAC,wBAAwB,QAAQ,MAAM,QAAQ,WAAW,KAAK,CAAC;;AAGzE,SAAS,yBACP,MACS;AACT,QAAO,KAAK,GAAG,WAAW,OAAO"}
@@ -0,0 +1,9 @@
1
+ //#region src/lib/vite-plugin/scanners/types-generator.d.ts
2
+ interface GeneratedPhialTypesResult {
3
+ directory: string;
4
+ middlewareFile: string;
5
+ routesFile: string;
6
+ }
7
+ //#endregion
8
+ export { GeneratedPhialTypesResult };
9
+ //# sourceMappingURL=types-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-generator.d.ts","names":[],"sources":["../../../../src/lib/vite-plugin/scanners/types-generator.ts"],"mappings":";UAQiB,yBAAA;EACf,SAAA;EACA,cAAA;EACA,UAAA;AAAA"}
@@ -0,0 +1,190 @@
1
+ import { extname, relative, resolve } from "node:path";
2
+ import { mkdir, writeFile } from "node:fs/promises";
3
+ //#region src/lib/vite-plugin/scanners/types-generator.ts
4
+ const PHIAL_TYPES_DIR = ".phial/types";
5
+ const MIDDLEWARE_TYPES_FILE = "middleware.d.ts";
6
+ const ROUTES_TYPES_FILE = "routes.d.ts";
7
+ async function writePhialProjectTypes(result) {
8
+ const typesDirectory = resolve(result.root, PHIAL_TYPES_DIR);
9
+ const middlewareFile = resolve(typesDirectory, MIDDLEWARE_TYPES_FILE);
10
+ const routesFile = resolve(typesDirectory, ROUTES_TYPES_FILE);
11
+ await mkdir(typesDirectory, { recursive: true });
12
+ await writeFile(middlewareFile, createMiddlewareTypesDeclaration(result), "utf8");
13
+ await writeFile(routesFile, createRouteTypesDeclaration(result), "utf8");
14
+ return {
15
+ directory: typesDirectory,
16
+ middlewareFile,
17
+ routesFile
18
+ };
19
+ }
20
+ function createMiddlewareTypesDeclaration(result) {
21
+ const appMiddlewareNames = Object.keys(result.app.middleware).sort();
22
+ const appEntries = appMiddlewareNames.length > 0 ? appMiddlewareNames.map((name) => ` ${JSON.stringify(name)}: true`).join("\n") : "";
23
+ return [
24
+ "// Generated by Phial. Do not edit manually.",
25
+ "declare module 'phial' {",
26
+ " interface MiddlewareRegistry {",
27
+ ...appEntries ? [appEntries] : [],
28
+ " }",
29
+ "}",
30
+ "",
31
+ "export {}",
32
+ ""
33
+ ].join("\n");
34
+ }
35
+ function createRouteTypesDeclaration(result) {
36
+ const routes = collectTypedRoutes(result);
37
+ const pathEntries = routes.length > 0 ? collectPathRegistryEntries(routes).map((route) => ` ${JSON.stringify(route.pathPattern)}: ${route.paramsType}`).join("\n") : "";
38
+ const targetPathUnion = routes.length > 0 ? Array.from(new Set(routes.map((route) => route.targetPathType))).join(" | ") : "string";
39
+ const idEntries = routes.length > 0 ? routes.map((route) => ` ${JSON.stringify(route.id)}: { path: ${JSON.stringify(route.pathPattern)}; targetPath: ${route.targetPathType}; params: ${route.paramsType} }`).join("\n") : "";
40
+ const appTypeImportLine = createAppDataTypeImportLine(result);
41
+ const importTypeLines = createRouteTypeImportLines(routes);
42
+ const loaderEntries = routes.length > 0 ? routes.map((route, index) => ` ${JSON.stringify(route.id)}: ${createRouteDataTypeExpression(route, index, "loader")}`).join("\n") : "";
43
+ const actionEntries = routes.length > 0 ? routes.map((route, index) => ` ${JSON.stringify(route.id)}: ${createRouteDataTypeExpression(route, index, "action")}`).join("\n") : "";
44
+ const appDataEntries = result.app.loader ? [" data: ResolveRouteDataValue<ResolveRouteHandler<never, PhialAppLoaderModule, \"loader\">>"] : [];
45
+ return [
46
+ "// Generated by Phial. Do not edit manually.",
47
+ appTypeImportLine,
48
+ appTypeImportLine ? "" : "",
49
+ ...importTypeLines,
50
+ importTypeLines.length > 0 ? "" : "",
51
+ "declare module 'phial' {",
52
+ " interface AppDataRegistry {",
53
+ ...appDataEntries,
54
+ " }",
55
+ "",
56
+ " interface RoutePathRegistry {",
57
+ ...pathEntries ? [pathEntries] : [],
58
+ " }",
59
+ "",
60
+ " interface RouteTypeRegistry {",
61
+ ` targetPath: ${targetPathUnion}`,
62
+ " }",
63
+ "",
64
+ " interface RouteIdRegistry {",
65
+ ...idEntries ? [idEntries] : [],
66
+ " }",
67
+ "",
68
+ " interface RouteLoaderDataRegistry {",
69
+ ...loaderEntries ? [loaderEntries] : [],
70
+ " }",
71
+ "",
72
+ " interface RouteActionDataRegistry {",
73
+ ...actionEntries ? [actionEntries] : [],
74
+ " }",
75
+ "}",
76
+ "",
77
+ "export {}",
78
+ ""
79
+ ].join("\n");
80
+ }
81
+ function collectTypedRoutes(result) {
82
+ return result.modules.map((module) => {
83
+ const route = createTypedRoute(result, module);
84
+ return {
85
+ id: module.id,
86
+ module,
87
+ pathPattern: route.pathPattern,
88
+ targetPathType: route.targetPathType,
89
+ paramsType: serializeParamsType(route.params)
90
+ };
91
+ }).sort((left, right) => left.id.localeCompare(right.id));
92
+ }
93
+ function collectPathRegistryEntries(routes) {
94
+ const registry = /* @__PURE__ */ new Map();
95
+ for (const route of routes) if (!registry.has(route.pathPattern)) registry.set(route.pathPattern, route);
96
+ return [...registry.values()].sort((left, right) => left.pathPattern.localeCompare(right.pathPattern));
97
+ }
98
+ function createTypedRoute(result, module) {
99
+ const relativeFile = toPosixPath(relative(result.routesDir, module.absoluteFile));
100
+ const extension = extname(relativeFile);
101
+ const relativeDir = getEntryDirectory(relativeFile.slice(0, -extension.length));
102
+ const segments = relativeDir ? relativeDir.split("/").filter(Boolean) : [];
103
+ let variants = [{
104
+ segments: [],
105
+ template: false
106
+ }];
107
+ const params = [];
108
+ const patternSegments = [];
109
+ for (const segment of segments) {
110
+ if (isRouteGroup(segment)) continue;
111
+ if (/^\[\[\.\.\.[^/]+\]\]$/.test(segment)) {
112
+ const paramName = extractRouteParamName(segment);
113
+ params.push({
114
+ name: paramName,
115
+ optional: true
116
+ });
117
+ patternSegments.push(`:${paramName}`);
118
+ variants = [...variants, ...variants.map((variant) => ({
119
+ segments: [...variant.segments, "${string}"],
120
+ template: true
121
+ }))];
122
+ continue;
123
+ }
124
+ if (/^\[\.\.\.[^/]+\]$/.test(segment) || /^\[[^/]+\]$/.test(segment)) {
125
+ const paramName = extractRouteParamName(segment);
126
+ params.push({
127
+ name: paramName,
128
+ optional: false
129
+ });
130
+ patternSegments.push(`:${paramName}`);
131
+ variants = variants.map((variant) => ({
132
+ segments: [...variant.segments, "${string}"],
133
+ template: true
134
+ }));
135
+ continue;
136
+ }
137
+ patternSegments.push(segment);
138
+ variants = variants.map((variant) => ({
139
+ segments: [...variant.segments, segment],
140
+ template: variant.template
141
+ }));
142
+ }
143
+ return {
144
+ pathPattern: patternSegments.length > 0 ? `/${patternSegments.join("/")}` : "/",
145
+ targetPathType: variants.length > 0 ? Array.from(new Set(variants.map((variant) => {
146
+ if (variant.segments.length === 0) return "\"/\"";
147
+ return variant.template ? `\`/${variant.segments.join("/")}\`` : JSON.stringify(`/${variant.segments.join("/")}`);
148
+ }))).join(" | ") : "string",
149
+ params
150
+ };
151
+ }
152
+ function createAppDataTypeImportLine(result) {
153
+ if (!result.app.loader) return "";
154
+ return `import type * as PhialAppLoaderModule from ${JSON.stringify(createTypeImportSpecifier(result.app.loader))}`;
155
+ }
156
+ function createRouteTypeImportLines(routes) {
157
+ return routes.flatMap((route, index) => {
158
+ const lines = [`import type * as PhialRoutePrimaryModule${index} from ${JSON.stringify(createTypeImportSpecifier(route.module.file))}`];
159
+ if (route.module.files.loader) lines.push(`import type * as PhialRouteLoaderModule${index} from ${JSON.stringify(createTypeImportSpecifier(route.module.files.loader))}`);
160
+ if (route.module.files.action) lines.push(`import type * as PhialRouteActionModule${index} from ${JSON.stringify(createTypeImportSpecifier(route.module.files.action))}`);
161
+ return lines;
162
+ });
163
+ }
164
+ function createRouteDataTypeExpression(route, index, kind) {
165
+ return `ResolveRouteDataValue<ResolveRouteHandler<${`PhialRoutePrimaryModule${index}`}, ${kind === "loader" ? route.module.files.loader ? `PhialRouteLoaderModule${index}` : "never" : route.module.files.action ? `PhialRouteActionModule${index}` : "never"}, ${JSON.stringify(kind)}>>`;
166
+ }
167
+ function serializeParamsType(params) {
168
+ if (params.length === 0) return "{}";
169
+ return `{\n${params.map(({ name, optional }) => ` ${JSON.stringify(name)}${optional ? "?" : ""}: string`).join(";\n")}\n}`;
170
+ }
171
+ function getEntryDirectory(path) {
172
+ const separatorIndex = path.lastIndexOf("/");
173
+ return separatorIndex >= 0 ? path.slice(0, separatorIndex) : "";
174
+ }
175
+ function isRouteGroup(segment) {
176
+ return segment.startsWith("(") && segment.endsWith(")");
177
+ }
178
+ function extractRouteParamName(segment) {
179
+ return segment.replace(/^\[\[\.\.\.[^/]+/, "").replace(/^\[\.\.\./, "").replace(/^\[/, "").replace(/\]\]?$/, "");
180
+ }
181
+ function createTypeImportSpecifier(file) {
182
+ return file.startsWith("/") ? file : `/${file}`;
183
+ }
184
+ function toPosixPath(path) {
185
+ return path.replace(/\\/g, "/");
186
+ }
187
+ //#endregion
188
+ export { writePhialProjectTypes };
189
+
190
+ //# sourceMappingURL=types-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types-generator.js","names":[],"sources":["../../../../src/lib/vite-plugin/scanners/types-generator.ts"],"sourcesContent":["import { mkdir, writeFile } from \"node:fs/promises\";\nimport { extname, relative, resolve } from \"node:path\";\nimport type { ScannedRouteModule, ScannedRoutesResult } from \"./route-manifest\";\n\nconst PHIAL_TYPES_DIR = \".phial/types\";\nconst MIDDLEWARE_TYPES_FILE = \"middleware.d.ts\";\nconst ROUTES_TYPES_FILE = \"routes.d.ts\";\n\nexport interface GeneratedPhialTypesResult {\n directory: string;\n middlewareFile: string;\n routesFile: string;\n}\n\nexport async function writePhialProjectTypes(\n result: ScannedRoutesResult,\n): Promise<GeneratedPhialTypesResult> {\n const typesDirectory = resolve(result.root, PHIAL_TYPES_DIR);\n const middlewareFile = resolve(typesDirectory, MIDDLEWARE_TYPES_FILE);\n const routesFile = resolve(typesDirectory, ROUTES_TYPES_FILE);\n\n await mkdir(typesDirectory, { recursive: true });\n await writeFile(middlewareFile, createMiddlewareTypesDeclaration(result), \"utf8\");\n await writeFile(routesFile, createRouteTypesDeclaration(result), \"utf8\");\n\n return {\n directory: typesDirectory,\n middlewareFile,\n routesFile,\n };\n}\n\nexport function createMiddlewareTypesDeclaration(result: ScannedRoutesResult): string {\n const appMiddlewareNames = Object.keys(result.app.middleware).sort();\n const appEntries =\n appMiddlewareNames.length > 0\n ? appMiddlewareNames.map((name) => ` ${JSON.stringify(name)}: true`).join(\"\\n\")\n : \"\";\n\n return [\n \"// Generated by Phial. Do not edit manually.\",\n \"declare module 'phial' {\",\n \" interface MiddlewareRegistry {\",\n ...(appEntries ? [appEntries] : []),\n \" }\",\n \"}\",\n \"\",\n \"export {}\",\n \"\",\n ].join(\"\\n\");\n}\n\nexport function createRouteTypesDeclaration(result: ScannedRoutesResult): string {\n const routes = collectTypedRoutes(result);\n const pathEntries =\n routes.length > 0\n ? collectPathRegistryEntries(routes)\n .map((route) => ` ${JSON.stringify(route.pathPattern)}: ${route.paramsType}`)\n .join(\"\\n\")\n : \"\";\n const targetPathUnion =\n routes.length > 0\n ? Array.from(new Set(routes.map((route) => route.targetPathType))).join(\" | \")\n : \"string\";\n const idEntries =\n routes.length > 0\n ? routes\n .map(\n (route) =>\n ` ${JSON.stringify(route.id)}: { path: ${JSON.stringify(route.pathPattern)}; targetPath: ${route.targetPathType}; params: ${route.paramsType} }`,\n )\n .join(\"\\n\")\n : \"\";\n const appTypeImportLine = createAppDataTypeImportLine(result);\n const importTypeLines = createRouteTypeImportLines(routes);\n const loaderEntries =\n routes.length > 0\n ? routes\n .map(\n (route, index) =>\n ` ${JSON.stringify(route.id)}: ${createRouteDataTypeExpression(route, index, \"loader\")}`,\n )\n .join(\"\\n\")\n : \"\";\n const actionEntries =\n routes.length > 0\n ? routes\n .map(\n (route, index) =>\n ` ${JSON.stringify(route.id)}: ${createRouteDataTypeExpression(route, index, \"action\")}`,\n )\n .join(\"\\n\")\n : \"\";\n const appDataEntries = result.app.loader\n ? [' data: ResolveRouteDataValue<ResolveRouteHandler<never, PhialAppLoaderModule, \"loader\">>']\n : [];\n\n return [\n \"// Generated by Phial. Do not edit manually.\",\n appTypeImportLine,\n appTypeImportLine ? \"\" : \"\",\n ...importTypeLines,\n importTypeLines.length > 0 ? \"\" : \"\",\n \"declare module 'phial' {\",\n \" interface AppDataRegistry {\",\n ...appDataEntries,\n \" }\",\n \"\",\n \" interface RoutePathRegistry {\",\n ...(pathEntries ? [pathEntries] : []),\n \" }\",\n \"\",\n \" interface RouteTypeRegistry {\",\n ` targetPath: ${targetPathUnion}`,\n \" }\",\n \"\",\n \" interface RouteIdRegistry {\",\n ...(idEntries ? [idEntries] : []),\n \" }\",\n \"\",\n \" interface RouteLoaderDataRegistry {\",\n ...(loaderEntries ? [loaderEntries] : []),\n \" }\",\n \"\",\n \" interface RouteActionDataRegistry {\",\n ...(actionEntries ? [actionEntries] : []),\n \" }\",\n \"}\",\n \"\",\n \"export {}\",\n \"\",\n ].join(\"\\n\");\n}\n\nfunction collectTypedRoutes(result: ScannedRoutesResult): Array<{\n id: string;\n module: ScannedRouteModule;\n pathPattern: string;\n targetPathType: string;\n paramsType: string;\n}> {\n return result.modules\n .map((module) => {\n const route = createTypedRoute(result, module);\n return {\n id: module.id,\n module,\n pathPattern: route.pathPattern,\n targetPathType: route.targetPathType,\n paramsType: serializeParamsType(route.params),\n };\n })\n .sort((left, right) => left.id.localeCompare(right.id));\n}\n\nfunction collectPathRegistryEntries(\n routes: Array<{\n id: string;\n module: ScannedRouteModule;\n pathPattern: string;\n targetPathType: string;\n paramsType: string;\n }>,\n): Array<{\n id: string;\n module: ScannedRouteModule;\n pathPattern: string;\n targetPathType: string;\n paramsType: string;\n}> {\n const registry = new Map<\n string,\n {\n id: string;\n module: ScannedRouteModule;\n pathPattern: string;\n targetPathType: string;\n paramsType: string;\n }\n >();\n\n for (const route of routes) {\n if (!registry.has(route.pathPattern)) {\n registry.set(route.pathPattern, route);\n }\n }\n\n return [...registry.values()].sort((left, right) =>\n left.pathPattern.localeCompare(right.pathPattern),\n );\n}\n\nfunction createTypedRoute(\n result: ScannedRoutesResult,\n module: ScannedRouteModule,\n): {\n pathPattern: string;\n targetPathType: string;\n params: Array<{ name: string; optional: boolean }>;\n} {\n const relativeFile = toPosixPath(relative(result.routesDir, module.absoluteFile));\n const extension = extname(relativeFile);\n const withoutExtension = relativeFile.slice(0, -extension.length);\n const relativeDir = getEntryDirectory(withoutExtension);\n const segments = relativeDir ? relativeDir.split(\"/\").filter(Boolean) : [];\n\n let variants: Array<{ segments: string[]; template: boolean }> = [\n { segments: [], template: false },\n ];\n const params: Array<{ name: string; optional: boolean }> = [];\n const patternSegments: string[] = [];\n\n for (const segment of segments) {\n if (isRouteGroup(segment)) {\n continue;\n }\n\n if (/^\\[\\[\\.\\.\\.[^/]+\\]\\]$/.test(segment)) {\n const paramName = extractRouteParamName(segment);\n params.push({ name: paramName, optional: true });\n patternSegments.push(`:${paramName}`);\n variants = [\n ...variants,\n ...variants.map((variant) => ({\n segments: [...variant.segments, \"${string}\"],\n template: true,\n })),\n ];\n continue;\n }\n\n if (/^\\[\\.\\.\\.[^/]+\\]$/.test(segment) || /^\\[[^/]+\\]$/.test(segment)) {\n const paramName = extractRouteParamName(segment);\n params.push({ name: paramName, optional: false });\n patternSegments.push(`:${paramName}`);\n variants = variants.map((variant) => ({\n segments: [...variant.segments, \"${string}\"],\n template: true,\n }));\n continue;\n }\n\n patternSegments.push(segment);\n variants = variants.map((variant) => ({\n segments: [...variant.segments, segment],\n template: variant.template,\n }));\n }\n\n const pathPattern = patternSegments.length > 0 ? `/${patternSegments.join(\"/\")}` : \"/\";\n const targetPathType =\n variants.length > 0\n ? Array.from(\n new Set(\n variants.map((variant) => {\n if (variant.segments.length === 0) {\n return '\"/\"';\n }\n\n return variant.template\n ? `\\`/${variant.segments.join(\"/\")}\\``\n : JSON.stringify(`/${variant.segments.join(\"/\")}`);\n }),\n ),\n ).join(\" | \")\n : \"string\";\n\n return {\n pathPattern,\n targetPathType,\n params,\n };\n}\n\nfunction createAppDataTypeImportLine(result: ScannedRoutesResult): string {\n if (!result.app.loader) {\n return \"\";\n }\n\n return `import type * as PhialAppLoaderModule from ${JSON.stringify(createTypeImportSpecifier(result.app.loader))}`;\n}\n\nfunction createRouteTypeImportLines(\n routes: Array<{\n id: string;\n module: ScannedRouteModule;\n pathPattern: string;\n targetPathType: string;\n paramsType: string;\n }>,\n): string[] {\n return routes.flatMap((route, index) => {\n const lines: string[] = [\n `import type * as PhialRoutePrimaryModule${index} from ${JSON.stringify(createTypeImportSpecifier(route.module.file))}`,\n ];\n\n if (route.module.files.loader) {\n lines.push(\n `import type * as PhialRouteLoaderModule${index} from ${JSON.stringify(createTypeImportSpecifier(route.module.files.loader))}`,\n );\n }\n\n if (route.module.files.action) {\n lines.push(\n `import type * as PhialRouteActionModule${index} from ${JSON.stringify(createTypeImportSpecifier(route.module.files.action))}`,\n );\n }\n\n return lines;\n });\n}\n\nfunction createRouteDataTypeExpression(\n route: {\n module: ScannedRouteModule;\n },\n index: number,\n kind: \"loader\" | \"action\",\n): string {\n const primaryModule = `PhialRoutePrimaryModule${index}`;\n const entryModule =\n kind === \"loader\"\n ? route.module.files.loader\n ? `PhialRouteLoaderModule${index}`\n : \"never\"\n : route.module.files.action\n ? `PhialRouteActionModule${index}`\n : \"never\";\n\n return `ResolveRouteDataValue<ResolveRouteHandler<${primaryModule}, ${entryModule}, ${JSON.stringify(kind)}>>`;\n}\n\nfunction serializeParamsType(params: Array<{ name: string; optional: boolean }>): string {\n if (params.length === 0) {\n return \"{}\";\n }\n\n return `{\\n${params\n .map(({ name, optional }) => ` ${JSON.stringify(name)}${optional ? \"?\" : \"\"}: string`)\n .join(\";\\n\")}\\n}`;\n}\n\nfunction getEntryDirectory(path: string): string {\n const separatorIndex = path.lastIndexOf(\"/\");\n return separatorIndex >= 0 ? path.slice(0, separatorIndex) : \"\";\n}\n\nfunction isRouteGroup(segment: string): boolean {\n return segment.startsWith(\"(\") && segment.endsWith(\")\");\n}\n\nfunction extractRouteParamName(segment: string): string {\n return segment\n .replace(/^\\[\\[\\.\\.\\.[^/]+/, \"\")\n .replace(/^\\[\\.\\.\\./, \"\")\n .replace(/^\\[/, \"\")\n .replace(/\\]\\]?$/, \"\");\n}\n\nfunction createTypeImportSpecifier(file: string): string {\n return file.startsWith(\"/\") ? file : `/${file}`;\n}\n\nfunction toPosixPath(path: string): string {\n return path.replace(/\\\\/g, \"/\");\n}\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { LoadPhialConfigOptions, LoadedPhialConfig, PhialConfig, PhialDevConfig, PhialPluginOptions, PhialServerConfig, defineConfig, loadPhialConfig } from "./lib/vite-plugin/config.js";
2
+ import { PhialBuildOptions, PhialBuildResult, buildPhialApp } from "./lib/vite-plugin/host/plugin-build.js";
3
+ import { PhialDevServerHandle, PhialDevServerOptions, startPhialDevServer } from "./lib/vite-plugin/host/plugin-dev-server.js";
4
+ import { PhialPrepareOptions, preparePhialApp } from "./lib/vite-plugin/host/plugin-prepare.js";
5
+ import { PhialStartServerHandle, PhialStartServerOptions, startPhialServer } from "./lib/vite-plugin/host/plugin-server.js";
6
+ import { PhialVitePluginOptions, phialVitePlugin } from "./lib/vite-plugin/index.js";
7
+ export { type LoadPhialConfigOptions, type LoadedPhialConfig, type PhialBuildOptions, type PhialBuildResult, type PhialConfig, type PhialDevConfig, type PhialDevServerHandle, type PhialDevServerOptions, type PhialPluginOptions, type PhialPrepareOptions, type PhialServerConfig, type PhialStartServerHandle, type PhialStartServerOptions, type PhialVitePluginOptions, buildPhialApp, defineConfig, loadPhialConfig, phialVitePlugin, preparePhialApp, startPhialDevServer, startPhialServer };
@@ -0,0 +1,8 @@
1
+ import { defineConfig, loadPhialConfig } from "./lib/vite-plugin/config.js";
2
+ import { phialVitePlugin } from "./lib/vite-plugin/index.js";
3
+ import { buildPhialApp } from "./lib/vite-plugin/host/plugin-build.js";
4
+ import { startPhialDevServer } from "./lib/vite-plugin/host/plugin-dev-server.js";
5
+ import { preparePhialApp } from "./lib/vite-plugin/host/plugin-prepare.js";
6
+ import { startPhialServer } from "./lib/vite-plugin/host/plugin-server.js";
7
+ import "./lib/vite-plugin/host/index.js";
8
+ export { buildPhialApp, defineConfig, loadPhialConfig, phialVitePlugin, preparePhialApp, startPhialDevServer, startPhialServer };