# SAIF DotNet CLI Project Templates

> 👷 **For Platform Contributors:** This guide is for developers working on the Forge template system. For using templates to create applications, see [Creating and Using Templates](#creating-and-using-templates).

SAIF provides a collection of `dotnet new` templates for creating standardized projects. These templates are packaged and distributed via NuGet, making it easy to bootstrap new applications with consistent structure and configuration.

## 📋 Overview

| Aspect              | Details                                       |
| ------------------- | --------------------------------------------- |
| **Location**        | `src/templates/`                              |
| **Configuration**   | JSON files in `.template.config/` directories |
| **Distribution**    | NuGet package (`SAIF.Platform.Templates`)     |
| **Interfaces**      | `dotnet new` CLI or SAIF CLI                  |
| **Target Audience** | Platform contributors and app developers      |

## 📚 Reference

📖 See [Microsoft Documentation](https://learn.microsoft.com/en-us/dotnet/core/tools/custom-templates) for template authoring details.

## Template Structure Overview

Templates in `src/templates/` use JSON configuration files following the [Microsoft dotnet new template schema](https://learn.microsoft.com/en-us/dotnet/core/tools/custom-templates). Each template is self-contained with its own configuration and can inherit shared symbol definitions from the `shared/` subdirectory.

## Working with Template Files

All templates are located in `src/templates/`. Each template is a self-contained directory that follows the dotnet new template convention. Templates are organized into three categories:

### Template Categories

#### 1. Main API Templates

These generate complete application solutions with .NET projects, infrastructure, and CI/CD:

- `saif-api-sys` - System API (integrates with backend systems or data sources)
- `saif-api-exp` - Experience API (user-facing, aggregates multiple APIs)
- `saif-api-proc` - Process API (business process orchestration)

Each inherits shared configuration and automatically generates feature templates via post-actions.

#### 2. Feature Templates

These add functionality to existing applications without duplicating core structure:

- `saif-feature-base` - Core application structure
- `saif-feature-api` - API layer
- `saif-feature-database-cosmosdb` - Azure Cosmos DB integration
- `saif-feature-database-oracle` - Oracle Database integration
- `saif-feature-front-end-react` - React UI framework
- `saif-feature-event-subscription` - Event-driven capabilities

Feature templates are called by main API template setup scripts with symbol values automatically substituted.

#### 3. Package Templates

Specialized templates for reusable libraries and infrastructure:

- `saif-nuget-package` - .NET NuGet packages
- `saif-terraform-module` - Infrastructure as Code modules
- `saif-typespec-package` - OpenAPI specifications
- `saif-test-tools` - Testing utilities
- `saif-dynatrace-config` - Monitoring configuration
- `saif-azure-terraform-team` - Team infrastructure
- And others...

### Template File Structure

Each template contains a `.template.config/` directory with JSON configuration files:

**`template.json`** (required)

- Main template metadata and configuration
- Defines template identity, name, and short name (the name used with `dotnet new`)
- Lists shared configuration files to include via `additionalConfigFiles`
- Defines symbol parameters and their properties
- Configures post-actions (scripts to run after generation)
- Maps source names for file/folder renaming (e.g., `SAIF.App1` → your project name)

Example structure:

```json
{
  "$schema": "http://json.schemastore.org/template",
  "identity": "SAIF.Service.Api.System",
  "name": "SAIF Service - System Api",
  "shortName": "saif-api-sys",
  "sourceName": "SAIF.App1",
  "additionalConfigFiles": [
    "shared.api_type.g.template.json",
    "shared.database_type.template.json",
    "shared.custom_operations.template.json"
  ],
  "symbols": {
    "skip_setup": {
      "type": "parameter",
      "datatype": "bool",
      "defaultValue": "false"
    }
  },
  "postActions": []
}
```

**Shared Symbol Files** (`shared.*.template.json`)
Reusable symbol definitions shared across multiple templates. Located in the `shared/` subdirectory:

- `shared.business_domain.template.json` - Business domain selection
- `shared.database_type.g.template.json` - Database type choice (Oracle, Cosmos, None)
- `shared.front_end_type.template.json` - UI framework (None, React)
- `shared.owner.template.json` - Owning team name
- `shared.application_name.template.json` - Application naming parameters
- `shared.api_type.g.template.json` - API classification
- `shared.project_id.template.json` - Project identifier
- `shared.cli_runner.template.json` - CLI execution configuration

**`shared.custom_operations.template.json`**
Configures conditional syntax processing for different file types. This allows templates to include/exclude code based on symbol values:

- **PowerShell** (`.ps1`): `#if` / `#else` / `#elif` / `#endif` blocks
- **TypeSpec** (`.tsp`): `//#if` / `//#else` / `//#elif` / `//#endif` blocks
- **Markdown** (`.md`): `---#if` / `---#else` / `---#elif` / `---#endif` blocks

Example in PowerShell:

```powershell
#if (database_type == "oracle")
& $cli new saif-feature-database-oracle $databaseArgs.Split(' ') $allowScripts.Split(' ') $extraArgs.Split(' ')
#elseif (database_type == "cosmosdb")
& $cli new saif-feature-database-cosmosdb $databaseArgs.Split(' ') $allowScripts.Split(' ') $extraArgs.Split(' ')
#endif
```

### Post-Actions and Setup Scripts

Main API templates include post-actions that:

1. Make setup scripts executable on non-Windows platforms
2. Run `scripts/setup.ps1` with all symbol values substituted
3. The setup script orchestrates generation of feature templates based on user choices

**Example flow** when creating an Experience API with React and Cosmos DB:

```powershell
dotnet new saif-api-exp `
  --name MyApp `
  --database_type cosmosdb `
  --front_end_type React
```

The post-action calls `scripts/setup.ps1` which generates:

- `saif-feature-base` (core structure)
- `saif-feature-api` (API layer)
- `saif-feature-front-end-react` (React UI)
- `saif-feature-database-cosmosdb` (Cosmos DB integration)

All with parameters automatically substituted.

### Modifying Templates

When adding or changing template functionality:

1. **Add new parameters**

   - Edit shared symbol files for reusable parameters
   - Or add to `template.json` symbols section for template-specific parameters

2. **Add new files or structure**

   - Place files in the template directory
   - Use `sources.modifiers.rename` for hidden files (`.gitignore`, `.editorconfig`, etc.)

3. **Add conditional logic**

   - Use appropriate syntax based on file type (PowerShell, TypeSpec, or Markdown)
   - Example in PowerShell:
     ```powershell
     #if (is_external_app == true)
     # External-facing code
     #endif
     ```

4. **Update setup scripts**

   - Modify `scripts/setup.ps1` to invoke new feature templates
   - Pass parameters using placeholder names like `ApplicationName1`, `DatabaseType1`

5. **Test thoroughly**
   - Run tests with `dotnet test`
   - Use DiffEngineTray to review snapshot changes
   - Test multiple symbol combinations

### Symbol Replacement

Symbols use placeholder patterns in template files that get replaced with actual values during generation. Common placeholders:

- `ApplicationName1` → Your actual project name (from `--name` parameter)
- `BusinessDomain1` → Your business domain (from `--business_domain` parameter)
- `Owner1` → Your team name (from `--owner` parameter)
- `ProjectId1` → Your project identifier (from `--project_id` parameter)
- `DatabaseType1` → Selected database type (from `--database_type` parameter: oracle, cosmosdb, none)
- `FrontEndType1` → Selected UI framework (from `--front_end_type` parameter: None, React)

Setup scripts receive these values with symbols already replaced, enabling feature templates to inherit parameters from main templates. For example, when the post-action runs `scripts/setup.ps1`, all `ApplicationName1` references are already replaced with your actual project name.

## Development Prerequisites

- .NET SDK (includes `dotnet` CLI)
- Docker Desktop
- Visual Studio (recommended)
- [DiffEngineTray](https://github.com/SimonCropp/DiffEngine) (for test result comparison when modifying templates)

## Building Templates Locally

### Install Templates from Source

To build and install templates for local development:

```powershell
cd src/dotnet/SAIF.Platform.Templates
dotnet build --configuration Release
dotnet pack --no-build --configuration Release --output ./bin
dotnet new uninstall SAIF.Platform.Templates
dotnet new install ./bin/SAIF.Platform.Templates.1.0.0.nupkg
```

### Verify Installation

List all installed SAIF templates:

```powershell
dotnet new list saif-
```

## Creating and Using Templates

### Setup: Configure NuGet Source

Check that the SAIFCorporation package source is configured:

```powershell
dotnet nuget list source
```

If not present, add it:

```powershell
dotnet nuget add source https://pkgs.dev.azure.com/SAIFCorporation/_packaging/SAIFCorporation/nuget/v3/index.json -n SAIFCorporation
```

### Install Production Templates

Install the production templates package:

```powershell
dotnet new install SAIF.Platform.Templates
```

### Using dotnet new

Once templates are installed, create a new project using the `dotnet new` CLI:

```powershell
dotnet new saif-api-sys --name MyApi --business_domain IT --owner Architecture --force
```

#### Example: Experience API with Cosmos DB

```powershell
dotnet new saif-api-exp `
  --name MyExperienceApp `
  --business_domain pol `
  --owner Architecture `
  --front_end_type None `
  --is_external_app false `
  --database_type cosmosdb `
  --cosmos_api_type nosql `
  --allow-scripts yes
```

#### View Template Options

See all available parameters for a template:

```powershell
dotnet new saif-api-sys --help
```

#### Post-Generation

After generation:

- Open the solution in Visual Studio
- Press F5 to start the application and view it in the browser
- The Aspire dashboard will display your running services (API, Cosmos DB, etc.)

### Using SAIF CLI

The SAIF CLI provides a streamlined interface for working with templates, offering non-interactive and enhanced workflows:

```powershell
saif new saif-api-exp `
  --name MyExperienceApp `
  --business_domain pol `
  --owner Architecture `
  --front_end_type React `
  --database_type cosmosdb
```

Key differences when using the SAIF CLI:

- **Non-interactive**: Templates generate automatically without prompts (`--no-interactive`)
- **Automatic publishing**: Generated projects are ready to publish (`--no-publish` optional to skip)
- **Batch generation**: Feature templates are chained together seamlessly
- **Simplified parameters**: SAIF CLI handles parameter validation and defaults

The SAIF CLI ultimately invokes these templates behind the scenes, so both approaches use the same underlying template system. Choose based on your workflow preferences:

- Use **`dotnet new`** for interactive exploration and custom configurations
- Use **SAIF CLI** for automated, production-ready generation with sensible defaults

## Template Structure Overview

Templates in `src/templates/` use JSON configuration files following the [Microsoft dotnet new template schema](https://learn.microsoft.com/en-us/dotnet/core/tools/custom-templates). Each template is self-contained with its own configuration and can inherit shared symbol definitions from the `shared/` subdirectory.

## Running Tests Locally

When you modify templates, update the corresponding tests to account for your changes.

### Setup DiffEngineTray

[DiffEngineTray](https://github.com/VerifyTests/DiffEngine/blob/main/docs/tray.md) monitors pending snapshot changes and provides a visual interface for accepting them.

Install the tool:

```powershell
dotnet tool install -g DiffEngineTray
```

Launch it:

```powershell
diffenginetray
```

The tool runs in your Windows system tray. When tests produce snapshot differences, DiffEngineTray displays them grouped by solution and provides options to:

- **Accept all** - Accept all pending changes
- **Discard** - Clear all tracked items
- **Accept individual diffs** - Review and accept specific changes
- **View diffs** - Open changes in your configured diff tool
- **Purge verified files** - Clean up old snapshot files

For more details, see the [DiffEngineTray documentation](https://github.com/VerifyTests/DiffEngine/blob/main/docs/tray.md).

### Run Tests

```powershell
cd src/dotnet/tests/SAIF.Platform.Templates.UnitTests
dotnet test
```

### Review and Accept Changes

1. Click the DiffEngineTray icon in your system tray to view diffs
2. Accept or reject each diff as needed
3. If accepting changes, run the test command to accept pending snapshot changes:

```powershell
dotnet verify accept -y
```

4. Re-run tests to confirm they pass:

```powershell
dotnet test
```

## Using Templates

### Verify SAIFCorporation Source

Check that the SAIFCorporation package source is configured:

```powershell
dotnet nuget list source
```

If not present, add it:

```powershell
dotnet nuget add source https://pkgs.dev.azure.com/SAIFCorporation/_packaging/SAIFCorporation/nuget/v3/index.json -n SAIFCorporation
```

### Install Templates

Install the production templates package:

```powershell
dotnet new install SAIF.Platform.Templates
```

## Next Steps

- **Create a new project**: See [Creating and Using Templates](#creating-and-using-templates)
- **Run the generated app**: See [Post-Generation](#post-generation)
- **Contribute to templates**: See [Modifying Templates](#modifying-templates)
- **Learn about Forge**: See [About Forge](../../about/index.md)
