The pathResolver utility provides consistent path construction across KosmoJS's directory structure.
It handles the complexity of different directory types - some relative to the project root, some to the source folder, and some nested within the lib directory.
Basic Usage โ
import { pathResolver } from "@kosmojs/devlib";
export const factory: GeneratorFactory = async ({
appRoot,
sourceFolder,
formatters,
}) => {
const { resolve } = pathResolver({ appRoot, sourceFolder });
// Resolve paths to various locations
const apiPath = resolve("apiDir", "users/[id]/index.ts");
const libPath = resolve("apiLibDir", "users/[id]/types.ts");
const corePath = resolve("coreDir", "middleware.ts");
return { watchHandler };
};Directory Types โ
The resolver understands different directory categories and constructs paths accordingly:
Source Folder Shortcut โ
@ - Resolves directly to the source folder root
resolve("@", "config/index.ts")
// โ @front/config/index.tsRoot-Level Directories โ
coreDir and libDir - Resolve to project root locations
resolve("coreDir", "api/middleware.ts")
// โ core/api/middleware.ts
resolve("libDir", "types.ts")
// โ lib/types.tsThese directories exist at the project root, not within source folders.
Source-Relative Directories โ
Directories like apiDir, pagesDir, configDir resolve relative to the current source folder:
resolve("apiDir", "users/index.ts")
// โ @front/api/users/index.ts
resolve("pagesDir", "dashboard/index.tsx")
// โ @front/pages/dashboard/index.tsx
resolve("configDir", "index.ts")
// โ @front/config/index.tsLib Directories โ
Directories ending in LibDir (like apiLibDir, pagesLibDir, fetchLibDir) combine the global lib directory with the source folder and the specific lib subdirectory:
resolve("apiLibDir", "users/[id]/types.ts")
// โ lib/@front/{api}/users/[id]/types.ts
resolve("fetchLibDir", "index.ts")
// โ lib/@front/{fetch}/index.ts
resolve("pagesLibDir", "dashboard/route.ts")
// โ lib/@front/{pages}/dashboard/route.tsThis structure keeps generated files organized by source folder while maintaining a global lib directory for all generated code.
Implementation Details โ
The resolver applies these rules:
@shortcut โ Source folder directlycoreDirorlibDirโ Project root location- Directories ending in
LibDirโlib/{sourceFolder}/{specificLibDir} - All other directories โ
{sourceFolder}/{specificDir}
The appRoot parameter, when provided, prefixes all resolved paths to create absolute file paths suitable for file system operations.
Available Directories โ
The resolver works with all directory constants from KosmoJS's defaults. Common directories include:
Source directories:
apiDir- API routes directorypagesDir- Page components directoryconfigDir- Configuration directory
Lib directories:
apiLibDir- Generated API helperspagesLibDir- Generated page helpersfetchLibDir- Generated fetch clients
Root directories:
coreDir- Core application codelibDir- Generated code root
Type Safety โ
The Dir type ensures you only reference valid directory names:
type Dir =
| keyof {
[K in keyof typeof defaults as K extends `${string}Dir`
? K
: never]: unknown;
}
| "@";This extracts all keys from defaults that end with "Dir", plus the "@" shortcut, providing autocomplete and compile-time validation.
If you attempt to use an invalid directory name, TypeScript will catch it during development.
Practical Examples โ
Generating API Files โ
const { resolve } = pathResolver({ appRoot, sourceFolder });
// Generate route helper
await renderToFile(
resolve("apiLibDir", route.importPath, "helpers.ts"),
helperTemplate,
{ route },
{ formatters }
);
// Generate route types
await renderToFile(
resolve("apiLibDir", route.importPath, "types.ts"),
typesTemplate,
{ route },
{ formatters }
);Generating Framework Files โ
const { resolve } = pathResolver({ appRoot, sourceFolder });
// Generate router configuration
await renderToFile(
resolve("pagesLibDir", "router.ts"),
routerTemplate,
{ routes },
{ formatters }
);
// Write to source folder directly
await renderToFile(
resolve("@", "App.tsx"),
appTemplate,
{},
{ formatters }
);Reading Core Files โ
const { resolve } = pathResolver({ appRoot, sourceFolder });
// Read core middleware
const middlewarePath = resolve("coreDir", "api/middleware.ts");
const middlewareContent = await fs.readFile(middlewarePath, "utf8");Best Practices โ
Always use the resolver rather than manually constructing paths. The resolver ensures consistency and handles the complexity of different directory nesting patterns.
Import from @kosmojs/devlib to access the resolver and other utilities rather than implementing your own path logic.
Leverage type safety by letting TypeScript guide you to valid directory names through autocomplete.
Use the @ shortcut when you need to write directly to the source folder, such as for framework setup files that users might customize.
Prefer lib directories for generated code that users shouldn't edit manually. This keeps the source folder clean and makes it clear what's user code versus generated artifacts.