🚀 Socket Launch Week Day 5:Introducing Repository Access Permissions and Custom Roles.Learn more
Sign In

forji

Package Overview
Dependencies
Maintainers
1
Versions
6
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

forji

Library for building project structures with dynamic folder/file names

latest
npmnpm
Version
1.0.5
Version published
Weekly downloads
14
27.27%
Maintainers
1
Weekly downloads
 
Created
Source

🏗️ Project Builder

Version License: MIT TypeScript Node.js NPM

📁 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 extension
  • getFilesInFolder(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].

Built with ❤️ by developers for developers

FAQs

Package last updated on 02 Mar 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts