Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/customizer/Customizer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,14 @@ export class Customizer {
/** Custom instructions appended to transformPage's instruction block. */
protected customTransformInstructions: string[] = [];

// --- Local data folder ---
// Override in a derived class to change the local project folder name.

/** Name of the local data folder created in the user's project directory. */
get localFolder(): string {
return '.synthos';
}

// --- Content folder paths ---
// Override these in a derived class to point to your fork's folders.

Expand Down
26 changes: 14 additions & 12 deletions src/init.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { getOutdatedThemes, parseThemeFilename } from "./themes";
import { Customizer } from './customizer';

export interface SynthOSConfig {
localFolder: string;
pagesFolder: string;
requiredPagesFolder: string;
defaultPagesFolder: string;
Expand All @@ -24,6 +25,7 @@ export function createConfig(
customizer?: Customizer
): SynthOSConfig {
return {
localFolder: pagesFolder,
pagesFolder: path.join(process.cwd(), pagesFolder),
requiredPagesFolder: customizer?.requiredPagesFolder ?? path.join(__dirname, '../required-pages'),
defaultPagesFolder: customizer?.defaultPagesFolder ?? path.join(__dirname, '../default-pages'),
Expand All @@ -43,7 +45,7 @@ export async function init(config: SynthOSConfig, includeDefaultPages: boolean =
return false;
}

console.log(`Initializing .synthos folder...`);
console.log(`Initializing ${config.localFolder} folder...`);

// Create pages folder
await ensureFolderExists(config.pagesFolder);
Expand All @@ -54,7 +56,7 @@ export async function init(config: SynthOSConfig, includeDefaultPages: boolean =
await saveFile(path.join(config.pagesFolder, 'settings.json.example'), JSON.stringify(DefaultSettings, null, 4));

// Setup default scripts
console.log(`Copying default scripts to .synthos folder...`);
console.log(`Copying default scripts to ${config.localFolder} folder...`);
const scriptsFolder = path.join(config.pagesFolder, 'scripts');
await ensureFolderExists(scriptsFolder);
switch (process.platform) {
Expand All @@ -73,17 +75,17 @@ export async function init(config: SynthOSConfig, includeDefaultPages: boolean =
break;
}

await saveFile(path.join(scriptsFolder, 'example.sh'), '#!/bin/bash\n\n# This is an example script\n\n# You can run this script using the following command:\n# sh .synthos/scripts/example.sh\n\n# This script will print "Hello, World!" to the console\n\necho "Hello, World!"\n');
await saveFile(path.join(scriptsFolder, 'example.sh'), `#!/bin/bash\n\n# This is an example script\n\n# You can run this script using the following command:\n# sh ${config.localFolder}/scripts/example.sh\n\n# This script will print "Hello, World!" to the console\n\necho "Hello, World!"\n`);

// Setup default themes
console.log(`Copying default themes to .synthos folder...`);
console.log(`Copying default themes to ${config.localFolder} folder...`);
const themesFolder = path.join(config.pagesFolder, 'themes');
await ensureFolderExists(themesFolder);
await copyFiles(config.defaultThemesFolder, themesFolder);

// Copy pages
if (includeDefaultPages) {
console.log(`Copying default pages to .synthos folder...`);
console.log(`Copying default pages to ${config.localFolder} folder...`);
await copyDefaultPages(config.defaultPagesFolder, config.pagesFolder);
}

Expand All @@ -94,7 +96,7 @@ async function repairMissingFolders(config: SynthOSConfig): Promise<void> {
// Rebuild scripts folder from defaults if missing
const scriptsFolder = path.join(config.pagesFolder, 'scripts');
if (!await checkIfExists(scriptsFolder)) {
console.log(`Restoring default scripts to .synthos folder...`);
console.log(`Restoring default scripts to ${config.localFolder} folder...`);
await ensureFolderExists(scriptsFolder);
switch (process.platform) {
case 'win32':
Expand All @@ -111,13 +113,13 @@ async function repairMissingFolders(config: SynthOSConfig): Promise<void> {
await copyFile(path.join(config.defaultScriptsFolder, 'linux-terminal.json'), scriptsFolder);
break;
}
await saveFile(path.join(scriptsFolder, 'example.sh'), '#!/bin/bash\n\n# This is an example script\n\n# You can run this script using the following command:\n# sh .synthos/scripts/example.sh\n\n# This script will print "Hello, World!" to the console\n\necho "Hello, World!"\n');
await saveFile(path.join(scriptsFolder, 'example.sh'), `#!/bin/bash\n\n# This is an example script\n\n# You can run this script using the following command:\n# sh ${config.localFolder}/scripts/example.sh\n\n# This script will print "Hello, World!" to the console\n\necho "Hello, World!"\n`);
}

// Rebuild themes folder from defaults if missing
const themesFolder = path.join(config.pagesFolder, 'themes');
if (!await checkIfExists(themesFolder)) {
console.log(`Restoring default themes to .synthos folder...`);
console.log(`Restoring default themes to ${config.localFolder} folder...`);
await ensureFolderExists(themesFolder);
await copyFiles(config.defaultThemesFolder, themesFolder);
} else {
Expand Down Expand Up @@ -152,15 +154,15 @@ async function repairMissingFolders(config: SynthOSConfig): Promise<void> {
// No pages folder and no flat files — rebuild from defaults
const htmlFiles = (await listFiles(config.pagesFolder)).filter(f => f.endsWith('.html'));
if (htmlFiles.length === 0) {
console.log(`Restoring default pages to .synthos/pages/ folder...`);
console.log(`Restoring default pages to ${config.localFolder}/pages/ folder...`);
await copyDefaultPages(config.defaultPagesFolder, config.pagesFolder);
} else {
await ensureFolderExists(pagesSubdir);
}
}

// Migrate any stray flat .html files from root into pages/<name>/
await migrateFlatPages(config.pagesFolder);
await migrateFlatPages(config.pagesFolder, config.localFolder);
}

function toTitleCase(name: string): string {
Expand All @@ -171,12 +173,12 @@ function toTitleCase(name: string): string {
.replace(/\b\w/g, c => c.toUpperCase());
}

async function migrateFlatPages(pagesFolder: string): Promise<void> {
async function migrateFlatPages(pagesFolder: string, localFolder: string): Promise<void> {
const pagesSubdir = path.join(pagesFolder, 'pages');
const htmlFiles = (await listFiles(pagesFolder)).filter(f => f.endsWith('.html'));
if (htmlFiles.length === 0) return;

console.log(`Migrating ${htmlFiles.length} page(s) to .synthos/pages/ folder...`);
console.log(`Migrating ${htmlFiles.length} page(s) to ${localFolder}/pages/ folder...`);
await ensureFolderExists(pagesSubdir);
const now = new Date().toISOString();

Expand Down
2 changes: 1 addition & 1 deletion src/pages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ export interface PageInfo {
export type PageMetadata = Omit<PageInfo, 'name'>;

export async function loadPageMetadata(pagesFolder: string, name: string, fallbackFolder?: string): Promise<PageMetadata | undefined> {
// 1. Try user override: .synthos/pages/<name>/page.json
// 1. Try user override: <localFolder>/pages/<name>/page.json
const metadataPath = path.join(pagesFolder, 'pages', name, 'page.json');
if (await checkIfExists(metadataPath)) {
try {
Expand Down
4 changes: 2 additions & 2 deletions src/service/useApiRoutes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -794,14 +794,14 @@ Return ONLY the JSON object.`};
// Backup original page to .migrated/ before overwriting
const migratedFolder = path.join(config.pagesFolder, '.migrated');

// Handle legacy flat file (.synthos/pagename.html)
// Handle legacy flat file (<localFolder>/pagename.html)
const flatPath = path.join(config.pagesFolder, `${name}.html`);
if (await checkIfExists(flatPath)) {
await copyFile(flatPath, migratedFolder);
await deleteFile(flatPath);
}

// Handle folder-based page (.synthos/pages/name/)
// Handle folder-based page (<localFolder>/pages/name/)
const folderPath = path.join(config.pagesFolder, 'pages', name);
if (await checkIfExists(folderPath)) {
await copyFolderRecursive(folderPath, path.join(migratedFolder, name));
Expand Down
4 changes: 2 additions & 2 deletions src/synthos-cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export async function run() {
default: 4242
})
.option('pages', {
describe: `Include default pages when initializing a new .synthos folder.`,
describe: `Include default pages when initializing a new local folder.`,
type: 'boolean',
default: true
})
Expand All @@ -33,7 +33,7 @@ export async function run() {
})
.demandOption([]);
}, async (args) => {
const config = createConfig('.synthos', { debug: args.debug, debugPageUpdates: args.debugPageUpdates }, customizer);
const config = createConfig(customizer.localFolder, { debug: args.debug, debugPageUpdates: args.debugPageUpdates }, customizer);
await init(config, args.pages);
await server(config, customizer).listen(args.port, async () => {
console.log(`SynthOS server is running on http://localhost:${args.port}`);
Expand Down