NovinkaZverejnili sme 50+ Laravel balíkov ako open source
Custom AI apps, agents and automation — Roundly ConsultingRoundly
Všetky balíky
Workflows for Laravel

Definície a verzie

Definície

$definition = Workflows::definitions()->create(
    key: 'purchase-approval', name: 'Purchase approval',
    subjectType: 'purchase_request', owner: $team, description: null,
);                                                  // or createWith(CreateDefinitionData)

Workflows::definitions()->find('purchase-approval', $team);
Workflows::definitions()->exists('purchase-approval', $team);
Workflows::definitions()->all($team);
Workflows::definitions()->restore('purchase-approval', $team);   // un-trash a soft-deleted definition
  • Nová definícia je v stave draft a jej verzia 1 je koncept s minimálnym grafom (ručný spúšťač → end).
  • Kľúče zodpovedajú ^[a-z0-9][a-z0-9._-]{0,99}$ a sú jedinečné v rámci vlastníka (definície celej aplikácie zdieľajú jeden rozsah). Zmazaná definícia si kľúč stále drží: create() vyhodí DefinitionKeyTakenException a restore() ju vráti späť.

Koncepty a publikovanie

$handle = Workflows::definition('purchase-approval', $team);

$handle->model();                         // WorkflowDefinition (UnknownDefinitionException if missing)
$handle->draft();                         // the draft version or null
$handle->edit($graph, $expectedChecksum); // save the draft (a graph array or a GraphBuilder; created as a copy of the current version)
$handle->discardDraft();
$handle->validate();                      // ValidationReport of the draft
$handle->publish(by: $admin);             // the draft becomes the current version
$handle->retire();                        // no new starts; running instances finish
$handle->activate();                      // allow starts again
$handle->resolveFlag($node, $path);       // dismiss a template review flag
$handle->rotateWebhook();                 // a new webhook id
$handle->versions();                      // every version, by number
$handle->version(3);
$handle->instances(InstanceStatus::Failed, perPage: 25);   // cursor-paginated history
$handle->start($subject);                 // PendingStart
$handle->dryRun(?int $version);           // PendingDryRun (NoVersionException for a missing version)
$handle->export(?int $version);           // TemplatePayload (NoVersionException for a missing version)
  • Jeden koncept na definíciu, vynútený zámkom riadka definície. edit() s $expectedChecksum, ktorý sa líši od konceptu, vyhodí DraftConflictException — dve karty editora sa navzájom neprepíšu.
  • Publikované verzie sú nemenné. Graf, spúšťač, aktér, nastavenia, kontrolný súčet a publikujúci sa po nastavení published_at nedajú zmeniť (PublishedVersionImmutableException). Mení sa len stav (published → superseded) a kurzor plánu.
  • publish() spraví úplnú validáciu, zmrazí koncept, nahradí predchádzajúcu verziu, nastaví aktuálnu verziu, aktivuje definíciu, nastaví kurzor plánu na teraz a po commite vyšle VersionPublished. Bez konceptu → NothingToPublishException. Publikovanie vyradenej definície ju znova aktivuje.
  • Bežiace inštancie si verziu ponechajú. Obnovenie, opakovanie aj eskalácie vždy používajú vlastný graf inštancie. Spustenie beží na verzii, ktorá je aktuálna vo chvíli, keď drží zámok definície: spustenie súbežné s publikovaním začne na novej verzii.
  • Vyradené definície odmietnu každé spustenie (DefinitionNotActiveException), aj také, ktoré už prebiehalo v čase vyradenia.
  • Spustenie zo subjektu — Workflows::for($request)->start($key) a $request->workflows() — najprv hľadá definíciu vlastníka subjektu a potom definíciu celej aplikácie s rovnakým kľúčom. S výslovne zadaným vlastníkom alebo cez Workflows::start($key, $subject, $owner) sa hľadá len v danom rozsahu.

Definície ako súbory

Systémové workflowy celej aplikácie (aj východiskové workflowy pre nových tenantov) môžu byť vo vašom repozitári ako JSON súbory v obálke šablóny — presne to, čo zapisuje workflows:export — a synchronizovať sa pri nasadení:

php artisan workflows:export purchase-approval --path=resources/workflows   # writes purchase-approval.json
php artisan workflows:validate --file=resources/workflows/purchase-approval.json
php artisan workflows:sync resources/workflows --publish                   # create / draft / publish; no-op when unchanged
php artisan workflows:sync --dry                                           # report what would change, write nothing
$report = Workflows::definitions()->sync(resource_path('workflows'), owner: $team, publish: true, dryRun: false);
$report->definitions;    // list<SyncedDefinition{file, key, status, draftOverwritten, version, message, report}>
$report->untracked;      // keys of the owner's definitions no file describes
$report->failed();       // any invalid or failed file
  • Každý súbor *.json (adresár alebo jeden súbor; predvolene workflows.sync.path) je payload roundly.workflows.template/v1: definition.{key, name, subject_type, description} a graph.
  • Chýbajúca definícia sa vytvorí (created). Graf, ktorého kanonický kontrolný súčet sa líši od aktuálnej verzie aj od konceptu, sa uloží ako koncept (drafted); s publish sa potom publikuje, ak je platný (published), inak sa nahlási ako invalid s reportom a z daného súboru sa nič nepublikuje. Nezmenený súbor nič nerobí (unchanged): dvojitá synchronizácia nevytvorí druhú verziu.
  • Id uzlov ostávajú tak, ako sú zapísané — na rozdiel od importu šablóny, ktorý ich premapuje — takže súbor sa synchronizuje vždy rovnako a verzie sa dajú porovnať uzol po uzle. Zachovajú sa aj hodnoty špecifické pre vlastníka.
  • Koncept upravený inde (v editore), ktorý súbor nahradí, sa nahlási (draftOverwritten).
  • Nič sa nevyradí ani nezmaže: definície vlastníka bez súboru sa uvedú ako untracked.
  • Vlastník: predvolene celá aplikácia; v príkazoch --owner-type=<morph alias> --owner-id=. Zápisy idú cez akcie definícií, takže sa vysielajú udalosti.

Porovnanie

$diff = Workflows::versions()->diff($v1, $v2);   // VersionDiff

$diff->identical;
$diff->nodesAdded;        // ids
$diff->nodesRemoved;
$diff->nodesChanged;      // list<NodeChange{node, typeChanged, configChanges, retryChanged, escalationsChanged}>
$diff->nodesMoved;        // ui-only changes
$diff->edgesAdded;
$diff->edgesRemoved;
$diff->edgesRelabelled;   // list<EdgeChange{from, to, before, after}>
$diff->triggerChanges;
$diff->settingsChanges;

configChanges sú JSON pointery listov, ktoré sa líšia. Na poradí v mape nezáleží, na poradí v zozname áno. Verzie rôznych definícií → InvalidDiffException.

Šablóny

$payload = Workflows::versions()->export($version);         // or $handle->export()
$result = Workflows::versions()->import($payload, $otherTeam, key: null);   // ImportResult

$result->definition;   // a new draft definition (key suffixed -2, -3 … when taken)
$result->idMap;        // old node id => new node id
$result->flags;        // list<ReviewFlag{node, path, reason}> — cleared owner-specific values

Workflows::definition($result->definition->key, $otherTeam)->resolveFlag('n_k3x9q2m7ab', '/recipients');

Payload (roundly.workflows.template/v1) nesie kľúč, názov, kľúč typu subjektu a popis definície, graf, exported_at a kontrolný súčet zdroja — žiadneho vlastníka, žiadne id, žiadne názvy tried. Hodnoty špecifické pre vlastníka sa zachovajú (opätovný import u toho istého vlastníka je bezstratový) a uvedú v review. Import:

  • overí payload a typ subjektu;
  • premapuje každé id uzla na nové n_ + 10 znakov base32 a prepíše hrany, odkazy steps.<id> a polia podmienok, vstupy start_workflow, dáta notifikácií a každý reťazec konfigurácie, ktorého schéma uvádza format: node-id;
  • vymaže každú hodnotu špecifickú pre vlastníka (strany typu user, kalendáre opening_hours: v trvaniach a nastaveniach, ciele start_workflow, ktoré nový vlastník nemá, endpointy webhookov, cesty, ktoré deklaruje typ) a na koncepte zaznamená ReviewFlag{node, path, reason};
  • vytvorí novú definíciu v stave draft (ak je kľúč obsadený, dostane príponu -2, -3 …).

Publikovanie blokuje unresolved_import_reference, kým sa každá označená cesta nenastaví (úprava príznak zruší) alebo sa príznak nezruší cez resolveFlag(). Používatelia, kalendáre a definície jedného tímu sa nikdy nedostanú k inému tímu.

Prejavte lásku k open source

Tento balík je zadarmo pod licenciou MIT. Ak vám šetrí čas, jednorazový príspevok alebo členstvo na Patreone nám pomôže ho ďalej udržiavať, testovať a dokumentovať.

Ďalšie spôsoby podpory vrátane kryptomien

Odoslaním daru súhlasíte s našimi podmienkami prijímania darov.

Chcete to zabudovať do svojho produktu?

Naše balíky integrujeme do zákazkových Laravel a AI riešení. Napíšte nám, na čom pracujete, a ozveme sa do 48 hodín.