@upcsoft/ddd
DDD Project Generator
A command-line tool to quickly scaffold Vue applications with the Domain-Driven Design (DDD) folder conventions taught at UPC (Universidad Peruana de Ciencias Aplicadas). It provides a Vite + Vue foundation with domain layers, shared components, internationalization, and documentation templates.
Install
Global:
npm install -g @upcsoft/ddd
Local:
npm install @upcsoft/ddd
Or run without installing:
npx @upcsoft/ddd create my-exam
Quick start (exam flow)
ddd create practice-pc1
cd practice-pc1
ddd init sales inventory
npm run dev
create— scaffolds a Vue (JavaScript) Vite projectinit— applies the Vue entry templates, installs dependencies, and adds DDD core folders/files (optional domain names)- Keep coding; add more domains later with
create-domain
Commands
ddd create <project-name>
Alias: c
Creates a new Vite project with the Vue JavaScript template, then applies the application entry files, router, Pinia, i18n, styles, and core environment templates. Installs the course UI dependencies, Pinia, Vue Router, and JSON Server. Run ddd init inside the generated project to add shared views and translations.
ddd create practice-pc1
# or
ddd c practice-pc1
ddd init [domain-names...]
Alias: i
Run in the root of an existing Vue project with package.json. Applies the same Vue entry files and dependency installation as create, and creates docs, server, src/shared, and src/locales. Pass domain names to create them under src/ as well. This also works with a project created directly through Vite.
ddd init sales inventory
# or
npx @upcsoft/ddd init sales inventory
To initialize a project without using ddd create:
npm create vite@latest my-app -- --template vue
cd my-app
ddd init sales inventory
npm run dev
init replaces src/main.js, src/app.vue, src/i18n.js, src/pinia.js, src/router.js, src/style.css, src/vite-env.d.ts, and the two .env files with the entry templates. It removes the uppercase src/App.vue and preserves existing component and asset folders.
Example after ddd init sales inventory:
.
├── docs <-- documentation folder
│ ├── class-diagram.puml
│ └── user-stories.md
├── LICENSE.md <-- license file
├── README.md <-- readme file
├── server <-- local API template
│ ├── db.json <-- empty JSON object
│ ├── routes.json <-- /api/v1/* route mapping
│ └── start.sh
└── src
├── inventory <-- domain folder
│ ├── application
│ │ └── inventory.store.js
│ ├── domain
│ │ └── model
│ │ └── entity.entity.js <-- example entity file
│ ├── infrastructure
│ │ ├── entity.assembler.js <-- example assembler file
│ │ └── inventory-api.js
│ └── presentation
│ ├── inventory-routes.js
│ ├── components
│ └── views
├── locales <-- i18n folder
│ ├── en.json <-- english translations
│ └── es.json <-- spanish translations
├── sales <-- domain folder
│ ├── application
│ │ └── sales.store.js
│ ├── domain
│ │ └── model
│ │ └── entity.entity.js
│ ├── infrastructure
│ │ ├── entity.assembler.js
│ │ └── sales-api.js
│ └── presentation
│ ├── sales-routes.js
│ ├── components
│ └── views
└── shared <-- shared domain folder
├── application
├── domain
│ └── model
├── infrastructure
│ ├── base-api.js
│ ├── base-endpoint.js
│ ├── error.interceptor.js
│ └── logo-dev-api.js
└── presentation
├── components
│ ├── language-switcher.vue
│ └── layout.vue
└── views
├── home.vue
└── page-not-found.vue
ddd create-domain <domain-names...>
Alias: cd
Run inside src/ (or the folder where domains live) when you need another domain later. Each name gets the standard layers plus starter templates (domain/model, infrastructure assembler, application store, empty presentation/components / presentation/views).
Both init and create-domain also create presentation/<domain-name>-routes.js, exporting an empty routes array with a commented example. Add your views there and import the routes into src/router.js. Existing routes files are preserved.
They also create application/<domain-name>.store.js, a generic Pinia setup store with items, loading status, errors, a computed count, and example actions. Its store ID matches the domain name so different domains keep separate state. Connect fetchItems to your API and assembler through its loader callback. Existing store files are preserved.
The generic Entity in domain/model/entity.entity.js provides id and name fields. EntityAssembler imports it and converts HTTP response arrays or collections wrapped under a configurable key (default: items). Adapt these examples to your domain entities.
infrastructure/<domain-name>-api.js exports a generic DomainApi class that extends BaseApi and uses BaseEndpoint for CRUD operations. Its constructor accepts the endpoint path, defaulting to /items. Existing API files are preserved.
ddd create-domain shipping
# or
ddd cd shipping
ddd generate
Alias: g
Generate pieces on demand:
-d/--docs— docs template-s/--sharedDomain— shared domain folder-l/--locales— locales folder
Help
ddd --help
ddd --version
Dependencies
The Vue application stack includes:
| Package | Purpose |
|---|---|
vue |
Reactive user interfaces |
primevue |
UI components |
@primeuix/themes |
Themes for UI components |
primeflex |
CSS utilities for layout and styling |
primeicons |
Icons |
axios |
HTTP requests |
vue-i18n |
Internationalization |
pinia |
Shared application state |
vue-router |
Navigation between views |
Development tools:
vite— development server and production builds.@vitejs/plugin-vue— Vue support in Vite.json-server— local REST API simulation.
Both ddd create and ddd init install PrimeVue, themes, PrimeFlex, PrimeIcons, Axios, Vue I18n, Pinia, and Vue Router. They also install JSON Server as a development dependency with --save-exact, saving "json-server": "0.17.4" for the compatible --routes option. Vue and Vite come from the existing Vite project.
They add "server": "cd server && sh start.sh" to package.json scripts when it is missing. Existing scripts (including a custom server script) and other package fields are preserved; npm updates the dependency sections during installation.
The CLI itself uses commander to handle commands and arguments.
Application template
/redirects to/home; unknown routes display the shared page-not-found view.- The layout includes Home navigation and an English/Spanish language switcher.
.env.developmentand.env.productioncontain only core configuration, including the Logo.dev and PrimeVue values from the reference project. SetVITE_PLATFORM_API_URLfor your API and customizeVITE_LOGO_URLfor your application.BaseApiconfigures Axios with the shared response interceptor;BaseEndpointprovides reusable CRUD requests.
Local API server
ddd init creates server/start.sh, server/routes.json, and an empty server/db.json ({}). Existing server files are preserved.
ddd init installs the compatible JSON Server version and adds the server script. Start it from the project root:
npm run server
The server uses port 3000 by default. Add resource arrays to server/db.json; routes.json maps /api/v1/* to those resources.
Notes
initalways createsdocs,server, rootLICENSE.md/README.md,src/shared, andsrc/locales.createandinitapply the Vue entry templates and install course dependencies;initrequires an existing project root withpackage.json.- Empty folders that npm cannot publish are recreated at runtime (
application,presentation, etc.).
Related Packages
Version History
| Version | Released | License |
|---|---|---|
| 0.3.1 | MIT | |
| 0.3.0 | MIT | |
| 0.2.1 | MIT | |
| 0.2.0 | MIT | |
| 0.1.8 | MIT | |
| 0.1.7 | MIT | |
| 0.1.6 | MIT | |
| 0.1.5 | MIT | |
| 0.1.4 | MIT | |
| 0.1.3 | MIT | |
| 0.1.2 | MIT | |
| 0.1.1 | MIT | |
| 0.1.0 | MIT |