Wrm 3.1.0

There is a newer version of this package available.
See the version list below for details.
dotnet tool install --global Wrm --version 3.1.0
                    
This package contains a .NET tool you can call from the shell/command line.
dotnet new tool-manifest
                    
if you are setting up this repo
dotnet tool install --local Wrm --version 3.1.0
                    
This package contains a .NET tool you can call from the shell/command line.
#tool dotnet:?package=Wrm&version=3.1.0
                    
nuke :add-package Wrm --version 3.1.0
                    

WormScript (WRM)

Version: 2.9.5 Framework: .NET 9.0 License: Furniss Software (c) 2026

WRM pronounced "Worm", is a command line code generation tool that transforms database schemas into complete full-stack applications. Using a database-first approach, WormScript automatically generates RESTful APIs, data models, CRUD operations, and modern web components from your database structure.

Basic Usage

  1. Initialize a new project with wrm init MyProject react.
  2. Edit the generated .wrm/MyProject.wrm with your connection string.
  3. Run wrm build.
  4. Sit back and watch your complete application being generated!

Table of Contents

Additional Documentation:


Features

  • Database-First Development - Generate entire applications from existing database schemas
  • Multi-Database Support - PostgreSQL (primary), MySQL templates available
  • Full-Stack Generation - Backend APIs + Frontend components in one command
  • Three-Tier Architecture - Separate Data, API, and Web projects
  • RESTful API Generation - Complete CRUD controllers with filtering and custom queries
  • Modern Web Components - React, CoreUI support
  • Dapper ORM Integration - Lightweight, performant repositories with multi-mapping
  • Smart Code Generation - Automatic finder methods based on foreign keys and column annotations
  • Tree Model Support - Hierarchical models with nested sub-objects
  • Soft/Hard Delete Support - Configurable deletion strategies
  • Multi-Tenancy Ready - Organization-based data isolation
  • GraphQL Support - Optional GraphQL API layer
  • Model Context Protocol (MCP) - AI integration capabilities
  • Docker Support - Container configurations for PostgreSQL and MySQL
  • Swagger/OpenAPI - Automatic API documentation
  • Modular Features - Plugin-style feature system with dependency management
  • Paged Data - Built-in pagination support for API endpoints

Future Features

  • SQL Server Support
  • Azure Cosmos DB Support
  • Vue.js Frontend Support
  • Angular Frontend Support
  • Enhanced Test Data Generation

Supported Technologies

Backend

  • .NET 8.0/9.0 - Core framework
  • ASP.NET Core - Web API
  • Entity Framework Core - Schema reading
  • Dapper - Generated CRUD operations with multi-mapping
  • Serilog - Logging

Frontend

  • React - Modern UI library
  • React JSX - Advanced component patterns
  • CoreUI - Bootstrap-based admin templates

Databases

  • PostgreSQL (primary, fully supported)
  • MySQL (templates available)

Docker

  • Docker - Containerization of database + API
  • Docker Compose - Multi-container orchestration

Installation

Install WormScript as a global .NET tool:

dotnet tool install --global Wrm

Verify installation:

wrm help

Quick Start

1. Initialize a New Project

Choose the name of your project wisely, it will be used throughout the generated code. No spaces or underlines. Case sensitive.

wrm init MyProject react
cd MyProject

This creates:

  • .wrm/MyProject.wrm - Build script
  • .wrm/MyProject.sql - Database schema

2. Define Your Database Schema

Edit .wrm/MyProject.sql:

-- STAR-SYSTEMS
DROP TABLE IF EXISTS star_systems;
CREATE TABLE star_systems(
    star_system_id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    system_name VARCHAR(255) NOT NULL
);

-- STARS - Stars that belong in a star-system
DROP TABLE IF EXISTS stars;
CREATE TABLE stars(
    star_id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    star_system_id INTEGER,
    star_name VARCHAR(255) NOT NULL
);

-- PLANETS
DROP TABLE IF EXISTS planets;
CREATE TABLE planets(
    planet_id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    star_id INTEGER,
    planet_name VARCHAR(255) NOT NULL,
    planet_code VARCHAR(25) NOT NULL
);

3. Create and Run Your Database

Create a PostgreSQL database named MyProject and run the SQL script to set up the schema.

Optionally don't use the DATABASE RUN command in the Wrm script and rely on an existing database.

4. Configure Your Wrm Script

Edit .wrm/MyProject.wrm:

CREATE PROJECT MyProject
    DOC SWAGGER
    USE SOFT DELETE
    CONNECTION POSTGRES 'Host=localhost:5432;Username=postgres;Password=postgres;Database=MyProject'

DATABASE RUN '.wrm/MyProject.sql'

CREATE TESTDATA IFEMPTY USECASES 10
CREATE MODELS
CREATE API CONTROLLERS
CREATE API SERVICE
CREATE COMPONENTS

5. Build Your Project

wrm build

Your complete application is now generated!


Usage

Commands

wrm <init|build|test|list|help> [options]

  • init - Initialize a new project
  • build - Build the project
  • test - Test database connectivity
  • list - List project components for debugging
wrm init [ProjectName] [WebComponentType]

Creates a new WormScript project structure. A base set of components is created for each entity table in the required web framework form.

wrm init MyProject react      # React components
wrm init MyProject coreui     # CoreUI components
wrm build

Executes the .wrm script and generates all code.

wrm build
wrm test connection

Tests database connectivity.

wrm test connection
wrm list [OPTION]

Lists project components for debugging.

Options:

  • ENTITIES - All entity tables
  • MODELS - Generated models
  • PORTS - API ports configuration
  • TEMPLATES - Available templates
  • TABLES - Database tables
  • FEATURES - Enabled features
  • CONFIG - Configuration settings
  • CONNECTION - Database connection info (masked)
wrm list tables
wrm list features
wrm database

Shows database information and connection details.

wrm database
wrm help [command]

Shows help information.

wrm help
wrm help init
wrm help build

WRM Script Syntax

WormScript uses a simple, declarative syntax:

Basic Structure
-- Comments start with -- or //

CREATE PROJECT ProjectName
    DOC SWAGGER              -- Enable Swagger docs
    USE SOFT DELETE          -- Use soft delete (is_deleted column)
    -- USE HARD DELETE       -- Alternative: permanent deletion
    CONNECTION POSTGRES 'Host=localhost;Database=mydb;Username=user;Password=pass'

DATABASE RUN '.wrm/schema.sql'

CREATE MODELS               -- Generate model classes
CREATE API CONTROLLERS      -- Generate API controllers
CREATE API SERVICE          -- Generate microservice code
CREATE COMPONENTS           -- Generate web components
CREATE TESTDATA IFEMPTY USECASES 10  -- Generate test data
Commands
Command Description
CREATE PROJECT <name> Initialize project configuration (required first)
DATABASE RUN '<filepath>' Execute SQL script to create/update schema
CREATE MODELS Generate C# model classes from database tables
CREATE MODEL <tablename> Generate single model
CREATE API SERVICE Generate all API controllers
CREATE COMPONENTS Generate web UI components
CREATE LOOKUP Generate lookup/finder methods
CREATE TESTDATA [options] Generate test data
CREATE TESTTABLE [name] Create test table with all data types
Connection Strings
-- PostgreSQL
CONNECTION POSTGRES 'Host=localhost:5432;Database=mydb;Username=user;Password=pass'

-- MySQL
CONNECTION MYSQL 'Server=localhost;Database=mydb;User=user;Password=pass'

Features System

WormScript includes a modular feature system. Enable features with the FEATURE sub command:

CREATE PROJECT <name>
FEATURE BASE           -- Base functionality (required by others)
FEATURE AUTH           -- Authentication/Authorization (JWT)
FEATURE ORGANISATIONS  -- Multi-tenancy support with hierarchical organizations
FEATURE USERS          -- User management tables
FEATURE FILEHANDLING   -- File attachment support
FEATURE GRAPHQL        -- GraphQL API layer
FEATURE ENTITIES       -- Entity configuration framework
FEATURE MCP;           -- Model Context Protocol (AI integration)
FEATURE RPC            -- Remote Procedure Call support

WARNING: The current implementation of FEATURES will DROP EVERYTHING in the public schema and recreate the public schema with nothing in it. Use with caution on existing databases.

See Features.md for full list and descriptions.

Feature Dependencies:

Features automatically enable their dependencies. For example:

  • ORGANISATIONS requires BASE
  • AUTH requires BASE and USERS
  • FILEHANDLING requires BASE

Project Structure

After running wrm init MyProject react and wrm build, you get:

MyProject/
├── .wrm/
│   ├── MyProject.wrm              # Build script
│   └── MyProject.sql              # Database schema
│
├── MyProjectData/                 # Data Access Layer
│   ├── Config/
│   │   └── DbConnectionConfig.cs
│   ├── Database/
│   │   └── BaseRepository.cs      # Base repository class
│   ├── Models/
│   │   ├── IDatabaseModel.cs      # Model interface
│   │   ├── UserDbModel.cs         # Entity models
│   │   ├── UserFlatModel.cs       # Flat/joined models
│   │   └── UserTreeModel.cs       # Hierarchical models
│   ├── Repositories/
│   │   ├── UserRepository.cs      # Dapper CRUD operations
│   │   └── ...
│   └── MyProjectData.csproj
│
├── MyProjectService/              # API Service Layer
│   ├── Controllers/
│   │   ├── UserController.cs
│   │   └── ...
│   ├── GraphQL/                   # (if GRAPHQL feature enabled)
│   │   ├── UserQLQuery.cs
│   │   └── UserQLMutation.cs
│   ├── MCP/                       # (if MCP feature enabled)
│   │   └── UserMCPController.cs
│   ├── Security/                  # (if AUTH feature enabled)
│   │   ├── AuthController.cs
│   │   └── JwtTokenService.cs
│   ├── Config/
│   ├── Logging/
│   ├── Program.cs
│   ├── appsettings.json
│   └── MyProjectService.csproj
│
├── MyProjectReact/                # Web UI (React)
│   ├── src/
│   │   ├── components/
│   │   │   └── project/
│   │   │       └── User/
│   │   │           ├── UserApi.js
│   │   │           ├── UserForm.jsx
│   │   │           ├── UserTable.jsx
│   │   │           ├── UserCard.jsx
│   │   │           └── UserDropdown.jsx
│   │   ├── routes/
│   │   └── layouts/
│   └── package.json
│
├── MyProject.Tests/               # Unit Tests
│   ├── UserDbFullTests.cs
│   ├── UserDbQuickTests.cs
│   └── MyProject.Tests.csproj
│
├── docker/                        # Docker Configurations
│   ├── docker-compose.yml
│   ├── docker-compose.prod.yml
│   └── Dockerfile
│
└── MyProject.sln                  # Solution file

Generated Output

API Controllers

For each table, WormScript generates:

UserController.cs:

[ApiController]
[Route("api/[controller]")]
public class UserController : ControllerBase
{
    private readonly UserRepository _repository;

    [HttpGet]
    public async Task<IActionResult> GetAll() { ... }

    [HttpGet("paged")]
    public async Task<IActionResult> GetAllPaged(int page, int pageSize) { ... }

    [HttpGet("{id}")]
    public async Task<IActionResult> GetById(int id) { ... }

    [HttpPost]
    public async Task<IActionResult> Create([FromBody] UserDbModel model) { ... }

    [HttpPut("{id}")]
    public async Task<IActionResult> Update(int id, [FromBody] UserDbModel model) { ... }

    [HttpDelete("{id}")]
    public async Task<IActionResult> Delete(int id) { ... }

    // Custom finder methods based on column annotations
    [HttpGet("email/{email}")]
    public async Task<IActionResult> FindByEmail(string email) { ... }
}

Data Models

WormScript generates three types of models:

Standard Models (UserDbModel.cs):

public class UserDbModel : IDatabaseModel
{
    public int UserId { get; set; }
    public DateTime CreatedAt { get; set; }
    public int? CreatedBy { get; set; }
    public DateTime? UpdatedAt { get; set; }
    public int? UpdatedBy { get; set; }
    public bool IsDeleted { get; set; }
    public string Username { get; set; }
    public string Email { get; set; }
}

Flat Models (UserFlatModel.cs): Read-only models for joined queries across tables.

Tree Models (UserTreeModel.cs): Hierarchical models with nested sub-objects for parent-child relationships.

Dapper Repositories

UserRepository.cs:

public class UserRepository : BaseRepository
{
    public async Task<UserDbModel> GetById(int id) { ... }
    public async Task<IEnumerable<UserDbModel>> GetAll() { ... }
    public async Task<PagedResult<UserDbModel>> GetAllPaged(int page, int pageSize) { ... }
    public async Task<int> Create(UserDbModel model) { ... }
    public async Task<bool> Update(UserDbModel model) { ... }
    public async Task<bool> Delete(int id) { ... }
    public async Task<bool> Upsert(UserDbModel model) { ... }

    // Custom finders based on ## annotations
    public async Task<UserDbModel> FindByEmail(string email) { ... }
}

Web Components

UserApi.js:

const API_BASE = '/api/user';

export const UserApi = {
    getAll: () => fetch(API_BASE),
    getById: (id) => fetch(`${API_BASE}/${id}`),
    create: (data) => fetch(API_BASE, { method: 'POST', body: JSON.stringify(data) }),
    update: (id, data) => fetch(`${API_BASE}/${id}`, { method: 'PUT', body: JSON.stringify(data) }),
    delete: (id) => fetch(`${API_BASE}/${id}`, { method: 'DELETE' }),
};

Configuration

Database Annotations

Use SQL comments to control code generation:

CREATE TABLE users(
    user_id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    email VARCHAR(255) NOT NULL,           
    username VARCHAR(255) NOT NULL,
    organization_id INTEGER,                -- '_id' allows for automatic foreign key detection
    nickname VARCHAR(100)
);
COMMENT ON COLUMN user.email IS '##';       -- Creates FindByEmail() method in API
COMMENT ON COLUMN user.username IS '##';    -- Creates FindByUsername() method in API
COMMENT ON COLUMN user.nickname IS 'HIDE';  -- field is hidden from API and UI

COMMENT ON TABLE users IS 'PAGED';          -- API must use the skip & take parameters for paging

The ## fieldname annotation tells WormScript to generate a finder method for that column.

Special Comment Annotations

FindBy

Creation of a lookup/finder method for the field. Add ',PAGED' to indicate the method should return paged results.

COMMENT ON COLUMN table.field IS '##'
Name

Marks the field as a "name" field for display purposes.

COMMENT ON COLUMN table.field IS 'NAME'

Every table should have one field as the designated name field. If one is not specified, WormScript will look for common candidates like name, title, or description. This may be used in dropdowns and other UI elements. It doesn't have to be unique.

Hide

Hides the field from API and UI.

COMMENT ON COLUMN table.field IS 'HIDE'
Enumeration tables

Defines the table as an enumeration.

COMMENT ON TABLE table IS 'ENUM'
PAGED tables

Defines the table as an enumeration.

COMMENT ON TABLE table IS 'ENUM'

Column Naming Conventions

Columns with certain names are treated specially for UI generation:

Column Name Contains UX Effect
latitude UX builds data-entry and validation relevant to a latitude or longitude
longitude UX builds data-entry and validation relevant to a latitude or longitude
email Email UX and validation
password Password UX and validation
enum Builds radio selection based on the referenced ENUM TABLE
w3w UX data-entry and handling for What3Words

Database Support

CREATE TABLE users(
    user_id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    username VARCHAR(255) NOT NULL,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

Features:

  • GENERATED ALWAYS AS IDENTITY for auto-increment
  • LIKE clause for table inheritance
  • TIMESTAMPTZ for timestamps
  • JSON/JSONB support
  • Schema support

MySQL (Partial support)

CREATE TABLE users(
    user_id INT PRIMARY KEY AUTO_INCREMENT,
    username VARCHAR(255) NOT NULL,
    created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

Examples

Complete Example

1. Create project:

wrm init BlogApp react
cd BlogApp

2. Define schema (.wrm/BlogApp.sql):

DROP TABLE IF EXISTS posts;
CREATE TABLE posts(
    post_id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    title VARCHAR(255) NOT NULL,
    content TEXT,
    author_id INTEGER NOT NULL,
    -- ## author_id
    published_at TIMESTAMPTZ,
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
    is_deleted BOOLEAN NOT NULL DEFAULT FALSE
);

DROP TABLE IF EXISTS comments;
CREATE TABLE comments(
    comment_id INTEGER PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
    post_id INTEGER NOT NULL,
    -- ## post_id
    content TEXT NOT NULL,
    author_name VARCHAR(255),
    created_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
);

3. Configure build (.wrm/BlogApp.wrm):

CREATE PROJECT BlogApp
    DOC SWAGGER
    USE SOFT DELETE
    CONNECTION POSTGRES 'Host=localhost:5432;Database=blogapp;Username=postgres;Password=postgres'
    FEATURE BASE
    FEATURE USERS

DATABASE RUN '.wrm/BlogApp.sql'

CREATE TESTDATA IFEMPTY USECASES 20
CREATE MODELS
CREATE API SERVICE
CREATE COMPONENTS

4. Build:

wrm build

5. Run API:

cd BlogAppService
dotnet run

Your API is now running with:

  • GET /api/post - Get all posts
  • GET /api/post/paged?page=1&pageSize=10 - Get paged posts
  • GET /api/post/{id} - Get post by ID
  • GET /api/post/author/{authorId} - Get posts by author
  • POST /api/post - Create post
  • PUT /api/post/{id} - Update post
  • DELETE /api/post/{id} - Soft delete post
  • GET /api/comment/post/{postId} - Get comments by post

Naming Conventions

WormScript intelligently converts between naming conventions:

Context Convention Example
Database snake_case user_profile
C# Classes PascalCase UserProfile
C# Properties PascalCase UserProfile
JavaScript camelCase userProfile
UI Labels Spaced User Profile
Singular Forms Auto usersUser

Dependencies

Runtime Requirements

  • .NET 8.0 or 9.0 SDK/Runtime
  • Database server (PostgreSQL or MySQL)

Generated Project Dependencies

The generated projects include:

  • ASP.NET Core 8.0/9.0
  • Dapper 2.1.66
  • Npgsql (for PostgreSQL)
  • Serilog (logging)
  • Swagger/OpenAPI
  • Optional: JWT Bearer, Entity Framework Core

Contributing

WormScript is developed by Furniss Software. For issues, feature requests, or contributions:

  1. Check existing issues
  2. Follow the project's coding standards
  3. Test generated code thoroughly
  4. Submit pull requests with clear descriptions

License

Copyright (c) 2025 Furniss Software. All rights reserved.


Support

  • Documentation: Check .wrm/ folder examples after running wrm init
  • Issues: Report bugs via the project repository
  • Database Connection: Use wrm test connection to diagnose connectivity
  • Debugging: Use wrm list commands to inspect project state

Changelog

v2.8.0

  • Refactored ComponentWriter to RepositoryWriter for better semantics
  • Added Tree model support with Dapper multi-mapping
  • Improved nested block handling in conditional processing
  • Performance improvements in comment skipping (O(n) vs O(n^2))

v2.2.0

  • Docker Compose enhancements and fixes

v2.1.2

  • Bug fix in JWT security

v2.1.1

  • Numerous bug fixes
  • AUTH feature
  • Paged data support

v2.0.0

  • Model Context Protocol (MCP) integration
  • Enhanced API unit test templates
  • Improved database namespace organization
  • Updated comment syntax (//WRM_ prefix)

Happy Coding with WormScript!

Transform your database into a complete application in minutes.

Product Compatible and additional computed target framework versions.
.NET net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

This package has no dependencies.

Version Downloads Last Updated
3.3.4 85 4/13/2026
3.3.2 101 3/5/2026
3.3.1 85 3/5/2026
3.3.0 91 2/27/2026
3.2.2 101 2/15/2026
3.2.1 85 2/15/2026
3.2.0 91 2/15/2026
3.1.1 124 2/3/2026 3.1.1 is deprecated.
3.1.0 95 2/3/2026
3.0.0 109 1/22/2026
2.9.4 98 1/22/2026
2.9.2 99 1/22/2026
2.9.0 102 1/21/2026
2.8.0 117 1/12/2026 2.8.0 is deprecated.
2.7.0 686 12/1/2025 2.7.0 is deprecated.
2.6.1 109 1/12/2026 2.6.1 is deprecated.
2.6.0 682 12/1/2025 2.6.0 is deprecated.
2.5.0 681 12/1/2025 2.5.0 is deprecated.
2.3.0 200 11/24/2025 2.3.0 is deprecated.
2.2.0 421 11/20/2025 2.2.0 is deprecated.
Loading failed