Metadata-Version: 2.4
Name: urban-workflow
Version: 0.2.0
Summary: Moteur de workflow piloté par un DSL métier — portage Python de Black-Beard-Sdk/Workflow, sorties JSON normalisées via urban-json (JSLT).
Author-email: Gael Beard <gaelgael5@gmail.com>
License: MIT License
        
        Copyright (c) 2026 black beard
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
Project-URL: Homepage, https://github.com/gaelgael5/urban-workflow
Project-URL: Issues, https://github.com/gaelgael5/urban-workflow/issues
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Software Development :: Libraries
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: urban-json>=0.2.1
Provides-Extra: sql
Requires-Dist: sqlalchemy>=2.0; extra == "sql"
Provides-Extra: schemas
Requires-Dist: PyYAML>=6.0; extra == "schemas"
Requires-Dist: jsonschema>=4.18; extra == "schemas"
Provides-Extra: dev
Requires-Dist: pytest>=7; extra == "dev"
Requires-Dist: ruff>=0.4; extra == "dev"
Requires-Dist: sqlalchemy>=2.0; extra == "dev"
Requires-Dist: fastapi>=0.110; extra == "dev"
Requires-Dist: uvicorn>=0.27; extra == "dev"
Requires-Dist: httpx>=0.27; extra == "dev"
Requires-Dist: PyYAML>=6.0; extra == "dev"
Requires-Dist: jsonschema>=4.18; extra == "dev"
Dynamic: license-file

# urban-workflow

Moteur de workflow piloté par un **langage dédié** (DSL) — portage Python de
[Black-Beard-Sdk/Workflow](https://github.com/Black-Beard-Sdk/Workflow)
(.NET), dont le système de normalisation des sorties JSON est remplacé par
[urban-json](https://pypi.org/project/urban-json/) (moteur JSLT) : les
messages produits par le moteur sont décrits par des templates `.jslt`
déclaratifs, modifiables sans redéploiement.

## Un workflow en quelques lignes

```sql
NAME ValidationAchat VERSION 1
MATCHING (Type = 'achat')

DEFINE EVENT  DemandeSoumise 'une demande est déposée';
DEFINE RULE   MontantInferieur (DECIMAL seuil) 'montant sous le seuil';
DEFINE ACTION NotifierValideur (TEXT dossier)  'demande d''approbation';
DEFINE CONST  seuil_auto 500 'approbation automatique sous ce montant';

INITIALIZE WORKFLOW
    ON EVENT DemandeSoumise RECURSIVE SWITCH Tri

DEFINE STATE Tri 'aiguillage'
    ON EVENT DemandeSoumise
        WHEN MontantInferieur(seuil = seuil_auto)
            SWITCH Approuvee
        EXECUTE NotifierValideur(dossier = @Workflow.ExternalId)
            SWITCH EnValidation
;
DEFINE STATE Approuvee    'approbation automatique' ;
DEFINE STATE EnValidation 'en attente d''un valideur'
    EXPIRE AFTER 3 DAY SWITCH Expiree
;
DEFINE STATE Expiree      'sans réponse' ;
```

```python
from urban_workflow import (
    FunctionRegistry, MemoryStorage, Workflow,
    WorkflowEngine, WorkflowFactory, WorkflowProcessor, WorkflowsConfig,
)
from urban_workflow.dsl import parse_config
from urban_workflow.outputs import default_memory_output

rules = FunctionRegistry("rule")
rules.add("MontantInferieur", lambda ctx, seuil: float(
    ctx.incoming_event.extended_datas.get("Montant", 0)) < seuil)

storage = MemoryStorage()
configs = WorkflowsConfig().add_document(parse_config(SCRIPT, rules=rules))
processor = WorkflowProcessor(configs, WorkflowFactory())
processor.load_existing_workflows_by_external_id = (
    lambda key: storage.get_by(Workflow, key, "external_id"))
processor.output_actions = default_memory_output(storage)
engine = WorkflowEngine(processor)

engine.evaluate_event({"Name": "DemandeSoumise", "ExternalId": "DA-42",
                       "Type": "achat", "Montant": 120})
```

## Documentation

| Guide | Contenu |
|---|---|
| [docs/guide-dsl.md](docs/guide-dsl.md) | **Créer un workflow** : référence complète du langage — création d'instances, transitions `SWITCH`, conditions `WHEN`, actions, expiration, fragments |
| [docs/guide-regles.md](docs/guide-regles.md) | **Règles et scripts** : `DEFINE RULE … AS @script`, `ScriptRegistry` multi-langage, langage `expression` (opérateurs, fonctions, sémantique `NULL`), contrôles |
| [docs/guide-artefacts.md](docs/guide-artefacts.md) | **Artefacts JSON** : `DEFINE ARTIFACT … AS @schema USING @script`, scripts `jslt` (urban-json), `@artifact.Nom` dans les actions, validation par schéma |
| [docs/guide-integration.md](docs/guide-integration.md) | **L'utiliser dans du code** : règles métier, assemblage du moteur, templates JSLT, chaîne de sorties, événements techniques |
| [docs/guide-tests.md](docs/guide-tests.md) | **Le tester** : règles pures, configuration, templates, scénarios de bout en bout |
| [docs/analyse-portage.md](docs/analyse-portage.md) | Analyse du projet source et choix structurants du portage |

English versions: [docs/en/dsl-guide.md](docs/en/dsl-guide.md) ·
[docs/en/rules-guide.md](docs/en/rules-guide.md) ·
[docs/en/artifacts-guide.md](docs/en/artifacts-guide.md) ·
[docs/en/integration-guide.md](docs/en/integration-guide.md) ·
[docs/en/testing-guide.md](docs/en/testing-guide.md)

## Playground

Des **composants web indépendants** (éditeur avec intellisense,
diagramme, schémas, scripts, simulation sur le vrai moteur…) qu'une
application monte selon ses besoins, et une page qui les assemble —
distribution séparée [`urban-workflow-playground`](playground/README.md) :

```bash
pip install urban-workflow-playground
urban-workflow-playground     # http://127.0.0.1:8777
```

## Installation et développement

```bash
pip install -e .[dev]
python3 -m pytest -q
```

Dépendance unique du cœur : `urban-json` (qui apporte le runtime ANTLR du
parseur DSL). Python ≥ 3.10.

## État du portage

Socle, DSL (grammaires ANTLR reprises du source), moteur, templating
urban-json et persistance SQL (extra `[sql]`, SQLAlchemy Core) sont
fonctionnels et testés (scénarios de bout en bout *script DSL →
événements → états → messages*, cycle de vie persisté en SQL), avec CI
GitHub Actions (tests Python 3.10 → 3.13, lint ruff). Les bugs connus du
moteur source ne sont pas reproduits — chacun est couvert par un test
dédié.

## Licence

Voir [LICENSE](LICENSE).
