SoapJS CLI
Deterministic project and code generator for SoapJS services.
The CLI creates a runnable TypeScript service, records generated artifacts in .soap, and can add features, routes, API clients, OpenAPI docs, auth, databases, messaging, and realtime support without relying on interactive prompts.
Installation
Requirements:
- Node.js
>=24.17.0(Node 24 LTS or newer) - Generated projects include
.nvmrcwith24.17.0
npm install -g @soapjs/cli
soap --helpFor local development inside this repository:
npm install
npm run build
node build/index.js --helpQuick Start
soap create users-api \
--db postgres \
--auth jwt \
--docs openapi \
--api-client bruno \
--skip-install
cd users-api
npm install
npm run build
npm startIn another terminal:
curl http://localhost:3000/health
soap info
soap doctor
soap check routesInteractive Mode
Supported commands accept -i for guided prompts:
soap create users-api -i
soap add feature invoice -i
soap add route approve --feature invoice -i
soap generate bruno -i
soap remove route approve --feature invoice -iInteractive mode requires a TTY and uses the same deterministic planners as the flag-based CLI. Use --yes to skip final confirmation prompts where supported.
Detailed docs:
Developer guides:
- Developer guides index
- Regular CRUD API
- CQRS, events, Kafka, and WebSockets
- Auth and route policies
- Storage capabilities
- Quality, tests, and safe changes
soap create
soap create bootstraps a new service.
soap create users-api --skip-install
soap create users-api --install
soap create users-api --git-init --skip-install
soap create users-api --db mongo --auth api-key --api-client bruno --skip-install
soap create users-api --db mysql --db sqlite --skip-install
soap create users-api --architecture cqrs --messaging kafka --realtime ws --skip-install
soap create users-api --controller-layout per-feature --skip-installCommon options:
--architecture regular|cqrs--controller-layout per-route|per-feature--db mongo|postgres|mysql|sqlite|redis|none--auth jwt|api-key|local|none--messaging in-memory|kafka|none--telemetry logs|otel-noop|metrics|memory|none--docs openapi|none--contracts zod|none--api-client bruno|none--realtime ws|none--zones public,private,admin--package-manager npm|pnpm|yarn|bun--installto install dependencies after generation--git-initto initialize a local git repository without committing or pushing--forceand--write-newfor generated file conflicts
Generated projects use @soapjs/soap-auth 1.x with SoapAuth.create(...) and the @soapjs/soap-express/auth router/middleware helpers. Security defaults are generated through soap-express security config, including disabled x-powered-by, trust proxy, helmet, cors, and auth route throttling when auth is enabled.
soap add feature
Add a feature to an existing SoapJS project. soap add resource remains available as a deprecated compatibility alias.
soap add feature user --crud
soap add feature invoice --crud --db postgres --auth jwt --zone private
soap add feature invoice --crud --db mysql --auth jwt --zone private
soap add feature note --crud --db sqlite
soap add feature audit-log --db mongo --zone admin
soap add feature product --crud --field title:string --field price:number --field active:boolean:optional
soap add feature report --crud --auth jwt --policy roles:admin,editor
soap add feature report --crud --crud-route list:get:/search:jwt:private:admin:no-bruno
soap add feature identity --blankUse --dry-run to inspect the expanded plan before writing:
soap add feature order --crud --db postgres --dry-run
soap add feature order --crud --db postgres --yesCRUD features generate domain, repository, use-case or CQRS files, route controllers, route contracts, registry entries, and Bruno requests when Bruno is enabled. Projects default to one controller file per route; --controller-layout per-feature generates one controller file per feature.
Use --field name:type to store feature field metadata in the registry. Supported field types are string, number, boolean, and date. Add :optional to make a field optional.
Use --policy admin, --policy roles:a,b, or --policy custom:name to attach an auth policy to generated protected routes. Policies require route auth.
Use --crud-route operation:method:path[:auth][:zone][:policy][:bruno|no-bruno] to override CRUD route metadata per operation. Supported operations are list, get, create, update, and delete. Matrix policies use admin, roles=a,b, or custom=name.
Use --blank to register a feature and create only its folders, setup.ts, and index.ts. Blank features have no generated domain, repository, use cases, routes, controllers, or DI bindings, and are intended for manually adding components later.
soap add repository
Add a repository port and Mongo or SQL adapter to an existing feature:
soap add repository account --feature identity --db postgres
soap add repository account --feature identity --db postgres --entity profile
soap add repository account --feature identity --db postgres --entity profile --model AccountRowBy default, the repository generator creates a <Name>Record domain shape and a <Name>Row or <Name>Model persistence shape. Use --entity to reuse an existing domain entity from domain/<entity>.entity.ts, and --model to reuse an existing persistence type from the feature data folder.
soap add controller
Add an empty mock controller to an existing feature:
soap add controller admin-tools --feature users
soap add controller public-feed --feature users --path /feedThe generated controller is registered in src/config/controllers.ts and includes commented GET, POST, PUT, and DELETE examples.
soap add route
Add a route to an existing feature:
soap add route export --feature users --method get --path export
soap add route activate-user --feature users --method post --path :id/activate --auth jwt --zone private
soap add route approve --feature users --method post --path :id/approve --auth jwt --policy custom:approver
soap add route rebuild --feature users --method post --command rebuild-user
soap add route search --feature users --method get --query search-users
soap add route audit --feature users --method get --path audit --controller usersThe route path must stay under the feature path. Route names and feature names are normalized to kebab-case in the registry. --controller adds the route method to an existing generated controller in the feature. --policy supports admin, roles:a,b, custom:name, and none.
Bruno
Enable Bruno at project creation:
soap create users-api --api-client bruno --skip-installOr add it later:
soap update config --add-api-client bruno
soap generate brunoGenerated collection structure:
bruno/
bruno.json
environments/Local.bru
Health/health.bru
<Resource>/<Request>.bru
Run API tests:
npm run bruno
npm run test:api
make bruno
make test-apiGenerate a CRUD E2E flow:
soap generate bruno --e2e
npm run brunoBruno generation is registry-driven. Modified .bru files are skipped by default; use --force to overwrite or --write-new to write .new files.
OpenAPI
Enable OpenAPI at project creation:
soap create users-api --docs openapi --skip-installOr add it later:
soap update config --add-docs openapiWhen the app is running, fetch the generated spec:
soap generate openapi
soap generate openapi --output openapi.jsonThe generated app exposes:
/docs/openapi.json
Docker Flow
Generated projects include Dockerfile, docker-compose.yml, and Makefile.
make up
make db-seed
make logs
curl http://localhost:3000/health
make down
make down-cleanSelected capabilities update Docker services. For example, Redis adds a redis service and REDIS_URL, Postgres adds a postgres service and volume, MySQL adds a mysql service and volume, SQLite adds SQLITE_FILENAME, and Kafka adds Redpanda.
CRUD features with Mongo or SQL storage generate database init/seed/reset modules. Use npm run db:init, npm run db:seed, npm run db:reset, or the matching make db-init, make db-seed, and make db-reset targets. SQL seed runs create missing tables before inserting sample data based on feature fields.
.soap Folder
Every generated project includes:
.soap/
project.json
structure.json
api.json
registry.json
project.jsonstores project metadata and selected capabilities.structure.jsonstores source layout conventions.api.jsonstores API-level settings such as base URL, health path, auth defaults, and Bruno config.registry.jsonstores resources, routes, and generated file hashes.
The registry is what makes later commands deterministic and safe.
Generated Architecture
Default layout:
src/
index.ts
config/
config.ts
controllers.ts
dependencies.ts
resources.ts
common/
features/
<resource>/
domain/
application/
data/
api/
contracts/
Generated code keeps optional adapters in the composition root:
- database clients in
src/config/dependencies.ts - controllers in
src/config/controllers.ts - resource registration in
src/config/resources.ts - OpenAPI plugin in
src/index.ts - auth strategies in
src/features/auth
Capabilities
Supported MVP capabilities:
- Framework:
express - Architecture:
regular,cqrs - Databases:
mongo,postgres,mysql,sqlite,redis - Auth:
jwt,api-key,local - Messaging:
in-memory,kafka - Realtime:
ws - Telemetry:
logs,otel-noop - Docs:
openapi - Contracts:
zod - API client:
bruno
Add capabilities after project creation:
soap update config --add-db redis
soap update config --add-db mysql
soap update config --add-auth api-key
soap update config --add-docs openapi
soap update config --add-contracts zod
soap update config --add-api-client bruno
soap update config --refreshSafety and Overwrite Behavior
The CLI tracks generated file hashes in .soap/registry.json.
Default behavior:
- Existing unmodified generated files can be updated.
- Manually modified generated files are skipped.
--forceoverwrites or deletes modified generated files.--write-newwrites a.newfile for supported generators.--dry-runprints planned writes/deletes without changing files.
Safe removal:
soap remove route create-user --feature users
soap remove feature users
soap remove controller admin-tools --feature users
soap remove entity user --feature users
soap remove use-case approve-user --feature users
soap remove repository user --feature users --impl
soap remove route create-user --feature users --forcesoap remove only deletes files tracked in the registry. If a target file was manually modified, the operation is skipped unless --force is used.
Validation
soap info
soap doctor
soap check routessoap check routes verifies route uniqueness, zones, auth strategies, contracts, and Bruno request files when Bruno is enabled.
MVP Limitations
- Only the Express adapter is supported.
- The generator is template-based; it does not perform broad AST mutation of user-edited app code.
- Dependency installation is explicit. Use
--installor answer yes in interactive mode. - Git initialization is explicit. Use
--git-init; the CLI does not commit or push. - Update commands are add-only for capabilities.
- Redis is currently wired as dependency/config/Docker capability; resource repositories are implemented for memory, Mongo, Postgres, MySQL, and SQLite paths.
- Generated code is intended as a clean starting point and integration surface, not as a migration engine for arbitrary existing apps.
License
MIT