forji v1.0.5
๐๏ธ Project Builder
๐ A powerful, type-safe library for programmatically generating project structures with templates
โจ Features
- ๐ฏ Type-Safe - Written in TypeScript with complete type definitions
- ๐งฉ Flexible - Create any folder/file structure with a simple object definition
- ๐ Template Variables - Use variables in file names and content
- ๐ File Discovery - Helpers to find files and folders in your generated structure
- ๐ฎ Singleton Pattern - Easy to use across your application without managing state
- ๐ Path Management - Access paths to your created files and folders
- โก Asynchronous - Built with promises for non-blocking performance
๐ฆ Installation
npm install forji
# or
yarn add forji
# or
pnpm add forji
# or
bun add forji
๐ Quick Start
import { Build } from 'forji';
async function main() {
// Define your project structure
const structure = {
src: {
components: {
Button$tsx: 'export const Button = () => <button>Click me</button>;',
index$ts: 'export * from "./Button";'
},
utils: {
helpers$ts: 'export const sum = (a: number, b: number) => a + b;'
},
index$ts: 'export * from "./components";'
},
package$json: JSON.stringify({
name: "{{projectName}}",
version: "1.0.0"
}, null, 2)
};
// Build the project with template variables
await Build(structure, './my-project', {
projectName: 'awesome-app'
});
console.log('๐ Project successfully generated!');
}
main().catch(console.error);
๐ API Reference
Core Functions
Build(structure, rootPath, variables)
๐ ๏ธ Creates a project structure based on a configuration object.
import { Build } from 'forji';
const result = await Build(
{
'src': { /* folders and files */ },
'README.md': '# My Project'
},
'./output',
{ version: '1.0.0' }
);
getFolder(folderName)
๐ Retrieves the path of a folder by name.
import { getFolder } from 'forji';
const componentsPath = getFolder('components');
// -> '/path/to/project/src/components'
getFile(fileName)
๐ Retrieves the path of a file by name.
import { getFile } from 'forji';
const readmePath = getFile('README.md');
// -> '/path/to/project/README.md'
getPath(name)
๐ Retrieves the path of a file or folder by name.
import { getPath } from 'forji';
const path = getPath('Button.tsx');
// -> '/path/to/project/src/components/Button.tsx'
findFile(fileName, directory?)
๐ Recursively searches for a file starting from a directory.
import { findFile } from 'forji';
const configPath = await findFile('config.json');
// -> '/path/to/project/config.json' (if found)
ProjectBuilder Class
The ProjectBuilder
class uses the singleton pattern and manages the internal state of your project.
import { ProjectBuilder } from 'forji';
const builder = ProjectBuilder.getInstance();
const tsFiles = builder.getFilesByExtension('ts');
Methods
getFilesByExtension(extension)
- ๐ท๏ธ Returns all files with the specified extensiongetFilesInFolder(folderName)
- ๐ Returns all files in a specific folder
๐ Template Variables
Project Builder supports powerful templating with variables that can be used in both file/folder names and content using the {{variableName}}
syntax.
Basic Usage
Variables are defined in the third parameter of Build()
and then referenced in your structure definition:
const structure = {
'src': {
'{{componentName}}$tsx': 'export const {{componentName}} = () => <div>Hello</div>;'
}
};
await Build(structure, './output', {
componentName: 'Header'
});
// Creates: ./output/src/Header.tsx with content: export const Header = () => <div>Hello</div>;
Supported Variable Types
The TemplateVariables
type supports various primitive values:
type TemplateVariables = Record<string, string | number | boolean>;
// Example
await Build(structure, './output', {
appName: 'MyAwesomeApp', // string
version: 1.0, // number
isProduction: true, // boolean
port: 3000 // number
});
Variables in File/Folder Names
Variables can be used in any part of a path:
const structure = {
'{{srcFolder}}': {
'{{componentFolder}}': {
'{{prefix}}Button$tsx': '// {{copyright}}'
}
}
};
await Build(structure, './output', {
srcFolder: 'src',
componentFolder: 'components',
prefix: 'UI',
copyright: 'ยฉ 2025 Example Corp'
});
// Creates: ./output/src/components/UIButton.tsx
Variables in File Content
Variables shine when generating dynamic file content:
const structure = {
'package$json': JSON.stringify({
name: "{{projectName}}",
version: "{{version}}",
description: "{{description}}",
scripts: {
"start": "node dist/index.js",
"dev": "nodemon --exec ts-node src/index.ts",
"build": "tsc",
"test": "{{testCommand}}"
},
dependencies: {{dependencies}}
}, null, 2)
};
await Build(structure, './output', {
projectName: 'api-service',
version: '0.1.0',
description: 'Backend API service',
testCommand: 'jest --coverage',
dependencies: JSON.stringify({
"express": "^4.18.2",
"dotenv": "^16.0.3"
})
});
Dynamic Configuration Files
Generate configuration files with environment-specific settings:
function generateConfig(variables) {
const env = variables.environment;
let dbConfig = {};
if (env === 'development') {
dbConfig = {
host: 'localhost',
port: 5432
};
} else if (env === 'production') {
dbConfig = {
host: 'db.example.com',
port: 5432,
ssl: true
};
}
return JSON.stringify({
appName: variables.appName,
port: variables.port,
database: dbConfig,
logLevel: env === 'development' ? 'debug' : 'info'
}, null, 2);
}
const structure = {
'config$json': generateConfig
};
await Build(structure, './my-app', {
appName: 'MyService',
environment: 'development',
port: 3000
});
Combining with Content Generators
Variables can be mixed with dynamic content generation:
const structure = {
src: {
models: {
'{{entityName}}$ts': () => {
// This function has access to the variables via closure
return `export interface {{entityName}} {
id: string;
name: string;
createdAt: Date;
{{customFields}}
}`;
}
}
}
};
await Build(structure, './api', {
entityName: 'User',
customFields: `
email: string;
password: string;
role: 'admin' | 'user';`
});
Variable Interpolation in Arrays or Objects
For complex structures, consider pre-processing with variables:
function generateRouteFiles(routes) {
const files = {};
routes.forEach(route => {
const fileName = `${route.name}Route$ts`;
files[fileName] = `import { Router } from 'express';
const router = Router();
router.get('/${route.path}', (req, res) => {
res.json({ message: '${route.description}' });
});
export default router;`;
});
return files;
}
const routes = [
{ name: 'user', path: 'users', description: 'Get all users' },
{ name: 'product', path: 'products', description: 'Get all products' }
];
const structure = {
'src': {
'routes': generateRouteFiles(routes)
}
};
await Build(structure, './api');
๐งช Advanced Usage
File Name Formatting
The library supports special formatting for file names:
const structure = {
// Using $ for extensions
'tsconfig$json': '{ "compilerOptions": {} }',
// Using quotes for names with special characters
'"README.md"': '# Project Documentation'
};
Accessing Build Results
import { Build, getFilesByExtension } from 'forji';
// Build project
const builder = await Build(structure, './output');
// Get all TypeScript files
const tsFiles = builder.getFilesByExtension('ts');
// Get all files in the components folder
const componentFiles = builder.getFilesInFolder('components');
๐ง Configuration Examples
React Project
const reactProject = {
src: {
components: {
App$tsx: `import React from 'react';
export const App = () => <div>Hello World</div>;`,
index$ts: 'export * from "./App";'
},
index$tsx: `import React from 'react';
import ReactDOM from 'react-dom';
import { App } from './components';
ReactDOM.render(<App />, document.getElementById('root'));`
},
public: {
'index.html': `<!DOCTYPE html>
<html>
<head>
<title>{{projectName}}</title>
</head>
<body>
<div id="root"></div>
</body>
</html>`
},
package$json: JSON.stringify({
name: "{{projectName}}",
version: "{{version}}",
dependencies: {
"react": "^18.2.0",
"react-dom": "^18.2.0"
}
}, null, 2)
};
๐ Project Structure
forji/
โโโ src/
โ โโโ index.ts # Main entry point
โ โโโ ProjectBuilder.ts # Core builder class
โ โโโ types.ts # Type definitions
โ โโโ utils.ts # Utility functions
โโโ package.json
โโโ README.md
๐ค Contributing
Contributions, issues and feature requests are welcome!
- ๐ด Fork the project
- ๐จ Make your changes
- ๐ Create a pull request
๐ License
MIT ยฉ ๐๏ธ Hicham Jebara.