alepha
Version:
Easy-to-use modern TypeScript framework for building many kind of applications.
127 lines (111 loc) • 3.46 kB
text/typescript
import { $inject, $state, AlephaError } from "alepha";
import { FileSystemProvider } from "alepha/system";
import { appEntryOptions } from "../atoms/appEntryOptions.ts";
/**
* Service for locating entry files in Alepha projects.
*
* Resolves application entry points for the CLI build pipeline.
*/
export class AppEntryProvider {
protected readonly fs = $inject(FileSystemProvider);
protected readonly options = $state(appEntryOptions);
protected readonly serverEntries = [
"main.server.ts",
"main.server.tsx",
"main.ts",
"main.tsx",
] as const;
protected readonly browserEntries = [
"main.browser.ts",
"main.browser.tsx",
"main.ts",
"main.tsx",
] as const;
protected readonly styleEntries = [
"main.css",
"styles.css",
"style.css",
] as const;
/**
* Get application entry points.
*
* Server entry is required, an error is thrown if not found.
* Browser entry is optional.
*
* It will first check for custom entries in options, see appEntryOptions.
*/
public async getAppEntry(root: string): Promise<AppEntry> {
const appEntry: AppEntry = {
root,
server: "",
};
if (this.options.server) {
const serverPath = this.fs.join(root, this.options.server);
const serverExists = await this.fs.exists(serverPath);
if (!serverExists) {
throw new AlephaError(`Custom server entry not found: ${serverPath}`);
}
appEntry.server = this.options.server;
}
if (this.options.browser) {
const browserPath = this.fs.join(root, this.options.browser);
const browserExists = await this.fs.exists(browserPath);
if (!browserExists) {
throw new AlephaError(`Custom browser entry not found: ${browserPath}`);
}
appEntry.browser = this.options.browser;
}
if (this.options.style) {
const stylePath = this.fs.join(root, this.options.style);
const styleExists = await this.fs.exists(stylePath);
if (!styleExists) {
throw new AlephaError(`Custom style entry not found: ${stylePath}`);
}
appEntry.style = this.options.style;
}
const srcFiles = await this.fs.ls(this.fs.join(root, "src"));
if (!appEntry.server) {
// find in conventional locations
for (const entry of this.serverEntries) {
if (srcFiles.includes(entry)) {
appEntry.server = this.fs.join("src", entry);
break;
}
}
}
if (!appEntry.server) {
const srcDir = this.fs.join(root, "src");
const tried = this.serverEntries
.map((e) => this.fs.join(srcDir, e))
.join(", ");
throw new AlephaError(
`No server entry found. Tried: ${tried}. Add a main.server.ts file or configure a custom entry in alepha.config.ts.`,
);
}
if (!appEntry.browser) {
// find in conventional locations
for (const entry of this.browserEntries) {
if (srcFiles.includes(entry)) {
appEntry.browser = this.fs.join("src", entry);
break;
}
}
}
if (!appEntry.style) {
// find in conventional locations
for (const entry of this.styleEntries) {
if (srcFiles.includes(entry)) {
appEntry.style = this.fs.join("src", entry);
break;
}
}
}
return appEntry;
}
}
export interface AppEntry {
root: string;
server: string;
browser?: string;
style?: string;
}