Compare commits
2 Commits
38c2cfe50f
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| 9fc4c23143 | |||
| 973f0a01c9 |
36
README.md
36
README.md
@@ -2,44 +2,14 @@
|
||||
|
||||
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
|
||||
|
||||
```bash
|
||||
cd docs && python -m http.server 8080
|
||||
# http://localhost:8080
|
||||
```
|
||||
|
||||
## Structure
|
||||
|
||||
```
|
||||
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)
|
||||
```
|
||||
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.
|
||||
|
||||
4
cfg/.gitignore
vendored
4
cfg/.gitignore
vendored
@@ -9,5 +9,9 @@ __pycache__/
|
||||
*.pyc
|
||||
*.pyo
|
||||
|
||||
standalone
|
||||
sample
|
||||
|
||||
|
||||
# standalone/ and sample/ are kept in the main soleprint repo as templates.
|
||||
# Other rooms (amar/, dlt/, etc.) are listed in the repo-root .gitignore.
|
||||
|
||||
@@ -1,14 +1,3 @@
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"name": "feature-flow",
|
||||
"slug": "feature-flow",
|
||||
"title": "Feature Flow Pipeline",
|
||||
"status": "ready",
|
||||
"template": null,
|
||||
"larder": null,
|
||||
"output_larder": null,
|
||||
"system": "atlas"
|
||||
}
|
||||
]
|
||||
"items": []
|
||||
}
|
||||
|
||||
@@ -1,12 +1,3 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
"items": []
|
||||
}
|
||||
|
||||
@@ -1,22 +1,3 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
"items": []
|
||||
}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
{
|
||||
"items": [
|
||||
{"name": "pawprint-local", "slug": "pawprint-local", "title": "Pawprint Local", "status": "dev", "config_path": "deploy/pawprint-local"}
|
||||
]
|
||||
"items": []
|
||||
}
|
||||
|
||||
@@ -1,18 +1,3 @@
|
||||
{
|
||||
"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"
|
||||
}
|
||||
]
|
||||
"items": []
|
||||
}
|
||||
|
||||
@@ -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}}
|
||||
@@ -1,12 +1,3 @@
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"name": "feature-form",
|
||||
"slug": "feature-form",
|
||||
"title": "Feature Form Template",
|
||||
"status": "ready",
|
||||
"template_path": "data/template/feature-form",
|
||||
"system": "album"
|
||||
}
|
||||
]
|
||||
"items": []
|
||||
}
|
||||
|
||||
@@ -1,47 +1,36 @@
|
||||
{
|
||||
"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",
|
||||
"slug": "datagen",
|
||||
"title": "Test Data Generator",
|
||||
"title": "Datagen",
|
||||
"status": "live",
|
||||
"system": "ward",
|
||||
"type": "cli",
|
||||
"description": "Generate realistic test data for Amar domain (users, pets, services) and MercadoPago API responses. Used by mock veins and test seeders.",
|
||||
"path": "ward/tools/datagen",
|
||||
"cli": "python -m datagen"
|
||||
"system": "station",
|
||||
"type": "app",
|
||||
"description": "Generate realistic test data via faker-backed generators.",
|
||||
"path": "station/tools/datagen",
|
||||
"url": "/station/tools/datagen/"
|
||||
},
|
||||
{
|
||||
"name": "generate_test_data",
|
||||
"slug": "generate-test-data",
|
||||
"title": "DB Test Data Extractor",
|
||||
"status": "dev",
|
||||
"system": "ward",
|
||||
"type": "cli",
|
||||
"description": "Extract representative subsets from PostgreSQL dumps for testing/development.",
|
||||
"path": "ward/tools/generate_test_data",
|
||||
"cli": "python -m generate_test_data"
|
||||
"name": "graphgen",
|
||||
"slug": "graphgen",
|
||||
"title": "Graphgen",
|
||||
"status": "live",
|
||||
"system": "station",
|
||||
"type": "app",
|
||||
"description": "Render the data model as an interactive graph (entities + FK edges).",
|
||||
"path": "station/tools/graphgen",
|
||||
"url": "/station/tools/graphgen/"
|
||||
},
|
||||
{
|
||||
"name": "modelgen",
|
||||
"slug": "modelgen",
|
||||
"title": "Model Generator",
|
||||
"status": "dev",
|
||||
"system": "ward",
|
||||
"title": "Modelgen",
|
||||
"status": "live",
|
||||
"system": "station",
|
||||
"type": "cli",
|
||||
"description": "Generate platform-specific models (Pydantic, Django, Prisma) from JSON Schema.",
|
||||
"path": "ward/tools/modelgen",
|
||||
"path": "station/tools/modelgen",
|
||||
"cli": "python -m modelgen"
|
||||
}
|
||||
]
|
||||
|
||||
@@ -1,60 +1,12 @@
|
||||
{
|
||||
"items": [
|
||||
{
|
||||
"name": "jira",
|
||||
"slug": "jira",
|
||||
"title": "Jira",
|
||||
"status": "live",
|
||||
"system": "artery"
|
||||
},
|
||||
{
|
||||
"name": "slack",
|
||||
"slug": "slack",
|
||||
"title": "Slack",
|
||||
"status": "building",
|
||||
"system": "artery"
|
||||
},
|
||||
{
|
||||
"name": "google",
|
||||
"slug": "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",
|
||||
"system": "artery"
|
||||
"system": "artery",
|
||||
"description": "Google OAuth login + Drive/Calendar/Gmail APIs."
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -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 |
|
||||
@@ -31,10 +31,10 @@ Core books live in `soleprint/atlas/books/`. Room-specific books live in `cfg/<r
|
||||
At build time, room-specific books are merged into the output:
|
||||
|
||||
```
|
||||
soleprint/atlas/books/ # Core books (all rooms)
|
||||
cfg/amar/atlas/books/ # Amar-specific books
|
||||
soleprint/atlas/books/ # Core books (all rooms)
|
||||
cfg/<room>/atlas/books/ # Room-specific books
|
||||
↓ 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.
|
||||
|
||||
@@ -11,7 +11,6 @@ A room is an isolated configuration. Each room lives in `cfg/<room>/` and contai
|
||||
```
|
||||
cfg/
|
||||
standalone/ # Soleprint only, no managed app
|
||||
amar/ # Soleprint wrapping the Amar application
|
||||
myroom/ # Your room
|
||||
```
|
||||
|
||||
|
||||
@@ -28,7 +28,7 @@ Rooms subclass a base generator and provide domain-specific data factories:
|
||||
```python
|
||||
from station.tools.datagen.base import BaseGenerator
|
||||
|
||||
class AmarDataGenerator(BaseGenerator):
|
||||
class RoomDataGenerator(BaseGenerator):
|
||||
def generate_customers(self, count=10):
|
||||
return [self.fake_customer() for _ in range(count)]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user