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.
|
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
4
cfg/.gitignore
vendored
@@ -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.
|
||||||
|
|||||||
@@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
{
|
{
|
||||||
"items": [
|
"items": []
|
||||||
{"name": "pawprint-local", "slug": "pawprint-local", "title": "Pawprint Local", "status": "dev", "config_path": "deploy/pawprint-local"}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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": [
|
"items": []
|
||||||
{
|
|
||||||
"name": "feature-form",
|
|
||||||
"slug": "feature-form",
|
|
||||||
"title": "Feature Form Template",
|
|
||||||
"status": "ready",
|
|
||||||
"template_path": "data/template/feature-form",
|
|
||||||
"system": "album"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 |
|
|
||||||
@@ -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.
|
||||||
|
|||||||
@@ -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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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)]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user