Compare commits

..

2 Commits

Author SHA1 Message Date
9fc4c23143 update docs 2026-05-06 12:04:19 -03:00
973f0a01c9 update sample app 2026-05-06 11:59:42 -03:00
15 changed files with 38 additions and 271 deletions

View File

@@ -2,44 +2,14 @@
Development workflow platform. Wraps existing applications with tools, testing, and documentation — without touching source code. Development workflow platform. Wraps existing applications with tools, testing, and documentation — without touching source code.
Cada paso deja huella. *Cada paso deja huella.*
## Quick Start ---
```bash
# Create a room
python -m init.cli myroom
# Build
python build.py --cfg myroom
# Run
cd gen/myroom/soleprint && docker compose up
# Visit http://localhost:12000
```
Or use the browser wizard: `python -m init.web` → http://localhost:9000
## Docs ## Docs
```bash ```bash
cd docs && python -m http.server 8080 cd docs && python -m http.server 8080
# http://localhost:8080
``` ```
## Structure Visit `http://localhost:8080`. Start with [Concepts](docs/data/en/concepts.md) for the mental model, then [Quickstart](docs/data/en/quickstart.md) to run your first room.
```
spr/
├── soleprint/ # Core framework
│ ├── artery/ # Connectors (veins, shunts, pulses)
│ ├── atlas/ # Documentation (books, templates)
│ └── station/ # Tools (tester, datagen, modelgen)
├── cfg/ # Room configurations
├── init/ # Room setup (CLI + web wizard)
├── docs/ # Documentation site
├── ctrl/ # Build/deploy scripts
├── build.py # Build tool: cfg/ → gen/
└── gen/ # Built instances (gitignored)
```

4
cfg/.gitignore vendored
View File

@@ -9,5 +9,9 @@ __pycache__/
*.pyc *.pyc
*.pyo *.pyo
standalone
sample
# standalone/ and sample/ are kept in the main soleprint repo as templates. # standalone/ and sample/ are kept in the main soleprint repo as templates.
# Other rooms (amar/, dlt/, etc.) are listed in the repo-root .gitignore. # Other rooms (amar/, dlt/, etc.) are listed in the repo-root .gitignore.

View File

@@ -1,14 +1,3 @@
{ {
"items": [ "items": []
{
"name": "feature-flow",
"slug": "feature-flow",
"title": "Feature Flow Pipeline",
"status": "ready",
"template": null,
"larder": null,
"output_larder": null,
"system": "atlas"
}
]
} }

View File

@@ -1,12 +1,3 @@
{ {
"items": [ "items": []
{
"name": "feature-form",
"slug": "feature-form",
"title": "Feature Forms",
"status": "ready",
"source_template": "feature-form",
"data_path": "album/book/feature-form-samples/feature-form"
}
]
} }

View File

@@ -1,22 +1,3 @@
{ {
"items": [ "items": []
{
"name": "turnos",
"slug": "turnos",
"title": "Turnos Monitor",
"status": "dev",
"system": "ward",
"description": "Pipeline view of requests → turnos. Shows vet-petowner at a glance.",
"path": "ward/monitor/turnos"
},
{
"name": "data_browse",
"slug": "data-browse",
"title": "Data Browse",
"status": "ready",
"system": "ward",
"description": "Quick navigation to test users and data states. Book/larder pattern with SQL mode for manual testing workflows.",
"path": "ward/monitor/data_browse"
}
]
} }

View File

@@ -1,5 +1,3 @@
{ {
"items": [ "items": []
{"name": "pawprint-local", "slug": "pawprint-local", "title": "Pawprint Local", "status": "dev", "config_path": "deploy/pawprint-local"}
]
} }

View File

@@ -1,18 +1,3 @@
{ {
"items": [ "items": []
{
"name": "mercadopago",
"slug": "mercadopago",
"title": "MercadoPago",
"status": "ready",
"description": "Mock payment API for testing"
},
{
"name": "example",
"slug": "example",
"title": "Example",
"status": "ready",
"description": "Example shunt template"
}
]
} }

View File

@@ -1,38 +0,0 @@
# {{nombre_flujo}}
## Tipo de usuario
{{tipo_usuario}}
## Donde empieza
{{punto_entrada}}
## Que quiere hacer el usuario
{{objetivo}}
## Pasos
1. {{paso_1}}
2. {{paso_2}}
3. {{paso_3}}
## Que deberia pasar
- {{resultado_1}}
- {{resultado_2}}
## Problemas comunes
- {{problema_1}}
- {{problema_2}}
## Casos especiales
- {{caso_especial_1}}
## Flujos relacionados
- {{flujo_relacionado_1}}
## Notas tecnicas
- {{nota_tecnica_1}}

View File

@@ -1,12 +1,3 @@
{ {
"items": [ "items": []
{
"name": "feature-form",
"slug": "feature-form",
"title": "Feature Form Template",
"status": "ready",
"template_path": "data/template/feature-form",
"system": "album"
}
]
} }

View File

@@ -1,47 +1,36 @@
{ {
"items": [ "items": [
{
"name": "tester",
"slug": "tester",
"title": "Contract Tests",
"status": "live",
"system": "ward",
"type": "app",
"description": "HTTP contract test runner with multi-environment support. Filter, run, and track tests against dev/stage/prod.",
"path": "ward/tools/tester",
"url": "/tools/tester/"
},
{ {
"name": "datagen", "name": "datagen",
"slug": "datagen", "slug": "datagen",
"title": "Test Data Generator", "title": "Datagen",
"status": "live", "status": "live",
"system": "ward", "system": "station",
"type": "cli", "type": "app",
"description": "Generate realistic test data for Amar domain (users, pets, services) and MercadoPago API responses. Used by mock veins and test seeders.", "description": "Generate realistic test data via faker-backed generators.",
"path": "ward/tools/datagen", "path": "station/tools/datagen",
"cli": "python -m datagen" "url": "/station/tools/datagen/"
}, },
{ {
"name": "generate_test_data", "name": "graphgen",
"slug": "generate-test-data", "slug": "graphgen",
"title": "DB Test Data Extractor", "title": "Graphgen",
"status": "dev", "status": "live",
"system": "ward", "system": "station",
"type": "cli", "type": "app",
"description": "Extract representative subsets from PostgreSQL dumps for testing/development.", "description": "Render the data model as an interactive graph (entities + FK edges).",
"path": "ward/tools/generate_test_data", "path": "station/tools/graphgen",
"cli": "python -m generate_test_data" "url": "/station/tools/graphgen/"
}, },
{ {
"name": "modelgen", "name": "modelgen",
"slug": "modelgen", "slug": "modelgen",
"title": "Model Generator", "title": "Modelgen",
"status": "dev", "status": "live",
"system": "ward", "system": "station",
"type": "cli", "type": "cli",
"description": "Generate platform-specific models (Pydantic, Django, Prisma) from JSON Schema.", "description": "Generate platform-specific models (Pydantic, Django, Prisma) from JSON Schema.",
"path": "ward/tools/modelgen", "path": "station/tools/modelgen",
"cli": "python -m modelgen" "cli": "python -m modelgen"
} }
] ]

View File

@@ -1,60 +1,12 @@
{ {
"items": [ "items": [
{
"name": "jira",
"slug": "jira",
"title": "Jira",
"status": "live",
"system": "artery"
},
{
"name": "slack",
"slug": "slack",
"title": "Slack",
"status": "building",
"system": "artery"
},
{ {
"name": "google", "name": "google",
"slug": "google", "slug": "google",
"title": "Google", "title": "Google",
"status": "building",
"system": "artery"
},
{
"name": "maps",
"slug": "maps",
"title": "Maps",
"status": "planned",
"system": "artery"
},
{
"name": "whatsapp",
"slug": "whatsapp",
"title": "WhatsApp",
"status": "planned",
"system": "artery"
},
{
"name": "gnucash",
"slug": "gnucash",
"title": "GNUCash",
"status": "planned",
"system": "artery"
},
{
"name": "vpn",
"slug": "vpn",
"title": "VPN",
"status": "planned",
"system": "artery"
},
{
"name": "ia",
"slug": "ia",
"title": "IA",
"status": "live", "status": "live",
"system": "artery" "system": "artery",
"description": "Google OAuth login + Drive/Calendar/Gmail APIs."
} }
] ]
} }

View File

@@ -1,44 +0,0 @@
# Fixture Invoicing — Soleprint Demo
> **This book describes a deliberately-fake invoicing app used as a test
> fixture for the Soleprint framework.** It is not a real product.
## Purpose
The fixture exercises every soleprint tool end-to-end so we can iterate on
the framework without needing a real managed app. See
[`examples/fixture-invoicing/`](../../../../../../examples/fixture-invoicing/)
for the app itself.
## Data model
```
Customer ──< Invoice ──< LineItem
└──────< Payment
```
| Table | Key fields |
|-------------|-------------------------------------------------|
| `customer` | id · name · email · created_at |
| `invoice` | id · number · customer_id · issued_at · status |
| `line_item` | id · invoice_id · description · qty · unit_price|
| `payment` | id · invoice_id · amount · method · paid_at |
## Happy-path flow
1. Create a customer (`POST /api/customers`)
2. Create a draft invoice for them (`POST /api/invoices`)
3. Add one or more line items (`POST /api/line-items/invoices/{id}`)
4. Record a payment (`POST /api/payments/invoices/{id}`) — if the total
paid ≥ total billed, the invoice auto-transitions to `paid`.
## How this connects to Soleprint
| Soleprint tool | Fixture hook |
|----------------|--------------|
| datagen | `station/tools/datagen/fixture.py` — FixtureInvoicingGenerator |
| graphgen | `station/tools/graphgen/schema.json` — 4 models + FK edges |
| databrowse | `station/tools/databrowse/depot/{schema,views}.json` |
| tester | `station/tools/tester/tests/fixture/` |
| link | SQLAlchemy reflection against `customer`, `invoice`, etc. |
| sbwrapper | Injected into fixture's Vue frontend by nginx |

View File

@@ -32,9 +32,9 @@ At build time, room-specific books are merged into the output:
``` ```
soleprint/atlas/books/ # Core books (all rooms) soleprint/atlas/books/ # Core books (all rooms)
cfg/amar/atlas/books/ # Amar-specific books cfg/<room>/atlas/books/ # Room-specific books
↓ build.py ↓ build.py
gen/amar/soleprint/atlas/books/ # Merged output gen/<room>/soleprint/atlas/books/ # Merged output
``` ```
Core books ship with every room. Room books add to or override them. The build copies the core first, then overlays the room-specific content. Core books ship with every room. Room books add to or override them. The build copies the core first, then overlays the room-specific content.

View File

@@ -11,7 +11,6 @@ A room is an isolated configuration. Each room lives in `cfg/<room>/` and contai
``` ```
cfg/ cfg/
standalone/ # Soleprint only, no managed app standalone/ # Soleprint only, no managed app
amar/ # Soleprint wrapping the Amar application
myroom/ # Your room myroom/ # Your room
``` ```

View File

@@ -28,7 +28,7 @@ Rooms subclass a base generator and provide domain-specific data factories:
```python ```python
from station.tools.datagen.base import BaseGenerator from station.tools.datagen.base import BaseGenerator
class AmarDataGenerator(BaseGenerator): class RoomDataGenerator(BaseGenerator):
def generate_customers(self, count=10): def generate_customers(self, count=10):
return [self.fake_customer() for _ in range(count)] return [self.fake_customer() for _ in range(count)]