forklaunch 1.15.0

Launch faster with forklaunch
# {{app_name}}

<div align="center">
    <img src="./assets/logo.svg" alt="ForkLaunch Logo" width="200">
</div>


{{description}}

## Overview

This project was generated by ForkLaunch. ForkLaunch streamlines the development process by automating boilerplate creation and managing dependencies across services, workers, and libraries. It handles manifest updates, Docker configuration, and ensures consistent development patterns.

## Getting Started

This creates a new project with the basic structure including:
- ForkLaunch manifest file
- Docker Compose configuration
- Basic project structure
- Development environment setup
- Pre-configured linter, formatter, and Husky

### Two directories, and they are not the same one

This file sits in the **workspace root** — the directory holding `package.json`,
where every `{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}}` command below runs.

The **application root** is above it: the directory holding
`.forklaunch/manifest.toml`, where every `forklaunch` command runs.

Running `{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} install` from the application root fails with a
"no package.json" error. That is the wrong directory, not a broken project.

On first run, from **this** directory:

```bash
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} install
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun run{{/is_bun}} build
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} database:setup
```

Now, you can run the project with:

```bash
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} dev
```

## Core Commands

### Adding Components

> Every `forklaunch` command in this section runs from the **application root**
> (the directory holding `.forklaunch/manifest.toml`), not from here.

#### Add a Service

```bash
forklaunch add service my-service
```

Creates a new microservice with:
- Service boilerplate code, including models, controllers, services, and routes
- Updated manifest
- Docker Compose configuration
- All necessary dependencies

#### Add a Worker

```bash
forklaunch add worker my-worker
```

Creates a background worker with:
- Worker boilerplate code, including models, controllers, services, and routes
- Job processing setup
- Updated manifest and Docker configuration

#### Add a Library

```bash
forklaunch add library my-library
```

Creates a shared library that can be used across services:
- Library structure
- Package configuration
- Automatic dependency linking

#### Add a Router (in workers and services)

```bash
forklaunch add router my-controller
```

The `add router` command is particularly powerful as it:
- Creates a new Controller following MVC patterns
- Automatically wires up routes, in code
- Integrates with existing service or worker
- Generates test files for the new controller

### Making changes

```
forklaunch change [application,service,worker,library,router]
```

Changes can be made at any time using the above command. This allows you to change configuration selected during creation. Note: it is highly recommended to revision your code before attempting to perform changes in case of failure.

### Deleting Services

To remove services, workers, libraries, or routers from your project, use the `forklaunch delete` command. This safely removes all associated files, updates the manifest configuration, cleans up Docker Compose definitions, and removes dependencies that are no longer needed. The delete process includes confirmation prompts and detailed logging to ensure you understand exactly what will be removed. Always commit your changes before deleting components, as this operation modifies multiple files across your project structure.

#### Check dependencies

```bash
forklaunch depcheck
```

Checks dependency versions across projects. To define groups of projects that need the same dependencies, look at `.forklaunch/manifest.toml` > `[project_peer_dependencies]`.

## Database Migrations

ForkLaunch uses `MikroORM` for database management with these commands:

```bash
# Initialize the database
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} migrate:init

# Create a new migration
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} migrate:create

# Apply pending migrations
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} migrate:up

# Revert the last migration
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} migrate:down
```

To access the full `MikroORM` CLI, run `{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} mikro-orm`. Note, you may have to supply necessary NODE_ENV arguments to interface correctly with the target database.

## Development Workflow

### Starting the Development Server

```bash
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} dev
```

This starts all services and workers defined in your manifest.

### Building the Project

```bash
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun run{{/is_bun}} build
```

Compiles all services, workers, and libraries.

## Development Tools

### Code Quality

ForkLaunch comes with pre-configured:
- ESLint for code linting
- Prettier for code formatting
- Husky for Git hooks

### Git Integration

To enable Husky Git hooks:

```bash
{{#is_node}}npx{{/is_node}}{{#is_bun}}bun{{/is_bun}} husky install
```

This sets up pre-commit hooks for linting and formatting.

### Testing

Run tests with:

```bash
{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} test
```

### Definining Configuration

Configuration can be defined via a ConfigInjector class. The behavior can be observed in `mikro-orm.config.ts` and `registrations.ts` files.

Dependencies can have one of three lifetimes:

- `singleton` - A singleton dependency is created once and shared across the application.
- `scoped` - A scoped dependency is created once per scoped session.
- `transient` - A transient dependency is created each time it is requested.

This abstraction is also powerful to validate that environment and expected constant variables are present at runtime.

### Adding API Metadata

When defining APIs, you can add metadata to the API definition in an idiomatic manner. This achieves the following:

- Serves as a typing specification when writing API handlers
- Validates and coerces data to specified types when processed in handlers 
- Used to generate OpenAPI specification
- Used to generate API reference documentation

The general format is defined by the REST method, but generally follows the following format:

```typescript
{
  name: "A Random POST API",
  summary: "My API that works! Probably a nice POST request",
  headers: {
    "x-header-name": string
  },
  params: {
    id: number
  },
  body: {
    message: string,
    nestedObject: {
        anotherNestedObject: {
            sweet: boolean
        },
        justAString: string,
        justANumber: number,
    }
  },
  responses: {
    200: {
        returnMessage: string,
        metadata: {
            items: array(union(string, number, boolean)),
            timestamp: date
        }
    },
    301: union(string, number)
  },
};
```

Auth can also be added to the API definition, but is not required. Supported auth types are:

- `bearer` - Bearer token authentication
- `jwt` - JWT authentication
- `other` - Another auth method. You will need to supply a `decodeToken` callback

When defining this, the smart typing will ask you to provide `permissions` and/or `roles` for the API. You can also supply optional callbacks that hook into the token based auth flow.

## Advanced Configuration

### OpenTelemetry Configuration

By default, ForkLaunch will configure OpenTelemetry to send traces to an OpenTelemetry collector service running in docker. The LGTM stack is pre-configured to receive metrics, logs, and traces, and a pre-configured `grafana` dashboard is available at `http://localhost:3000`.

In order to make adjustments, config and code is located in the `monitoring` directory. Custom metrics can be added to `monitoring/metrics.ts`, and used virtually anywhere in code. Context aware instrumentation will deliver logs, metrics and traces. Supported override NODE_ENV variables are:

- `OTEL_EXPORTER_OTLP_ENDPOINT` - The endpoint to send traces to.
- `OTEL_SERVICE_NAME` - The name of the service.

### OpenAPI Configuration and API Reference documentation

Contract aware OpenAPI is generated live when running `pnpm dev`. API references are available at `http://localhost:3000/api/v1/docs`. You have the option of using swagger or scalar. If using scalar (by default), customization options can be passed through additional configuration. Note, the path can be overridden by supplying values for the following NODE_ENV variables:

- `VERSION` - The title of the OpenAPI documentation.
- `DOCS_PATH` - The path to the OpenAPI documentation.

Enrichment of the OpenAPI spec can be done inline where contract details are defined.

### Custom License

When initializing a project, the license was specified. The generated license will appear in the root of your project.

## Troubleshooting

If you encounter service specific issues, you can run `dev:local` within any service or worker to start a local development server. Please note, you will need docker resources to be run in order to interact with specified resources.

If you encounter issues:

1. Ensure all dependencies are installed: `{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun{{/is_bun}} install`
2. Rebuild the project: `{{#is_node}}pnpm{{/is_node}}{{#is_bun}}bun run{{/is_bun}} build`
3. Check Docker services: `docker-compose ps`
4. Review logs: `docker-compose logs -f`


More information can be found in [ForkLaunch documentation](https://forklaunch.com/docs).

Happy hacking!