Quick Start with Moost Workflows
This guide walks you through setting up a simple Moost workflow-enabled application, from initial project creation to running your first workflow.
Steps
1. Create a New Moost App
Run the interactive project generator and choose HTTP for this example:
npm create moost@latest
Follow the prompts to generate a new Moost-HTTP application (Web APP). After creation, navigate to the project directory:
cd your-app-name
2. Install the Workflow Adapter
Install the workflow package to enable workflow features:
npm install @moostjs/event-wf
3. Define the Workflow Controller
Create a wf.controller.ts
in src/controllers
:
// src/controllers/wf.controller.ts
import { Step, Workflow, WorkflowParam, WorkflowSchema } from "@moostjs/event-wf";
import { Controller, Injectable, Param } from "moost";
export interface TQuadraticRootsContext {
a: number;
b: number;
c: number;
discriminant: number;
result: string;
}
export interface TQuadraticRootsInputs {
a: number;
b: number;
c: number;
}
@Injectable("FOR_EVENT")
@Controller()
export class WfController {
@WorkflowParam("context")
ctx!: TQuadraticRootsContext;
@Workflow("quadratic-roots")
@WorkflowSchema<TQuadraticRootsContext>([
"validateInputs",
"calculateDiscriminant",
{ condition: (ctx) => ctx.discriminant < 0, id: "noSolutions" },
{ condition: (ctx) => ctx.discriminant === 0, id: "calc/single" },
{ condition: (ctx) => ctx.discriminant > 0, id: "calc/double" },
])
entryPoint() {
// Empty entry method
}
@Step("validateInputs")
validateInputs(@WorkflowParam("input") input?: Partial<TQuadraticRootsInputs>) {
if (input?.a === undefined || input?.b === undefined || input?.c === undefined) {
return { inputRequired: true };
}
this.ctx.a = +input.a; this.ctx.b = +input.b; this.ctx.c = +input.c;
if (this.ctx.a === 0) throw new Error("a cannot be zero");
}
@Step("calculateDiscriminant")
calculateDiscriminant() {
this.ctx.discriminant = this.ctx.b * this.ctx.b - 4 * this.ctx.a * this.ctx.c;
}
@Step("noSolutions")
noSolutions() {
this.writeResult("No real solutions");
}
@Step("calc/:roots(single|double)")
calcSingleRoot(@Param("roots") roots: "single" | "double") {
if (roots === "single") {
this.writeResult(`x = ${this.ctx.b / (2 * this.ctx.a)}`);
} else {
this.writeResult(
`x1=${(-this.ctx.b + Math.sqrt(this.ctx.discriminant)) / (2 * this.ctx.a)}, x2=${(-this.ctx.b - Math.sqrt(this.ctx.discriminant)) / (2 * this.ctx.a)}`
);
}
}
writeResult(x: string) {
this.ctx.result = x;
}
}
This defines a workflow (@Workflow("quadratic-roots")
) with a schema that chooses different steps based on the discriminant value. Steps are defined to validate inputs, calculate the discriminant, and compute roots or report no solutions.
4. Update Main Controller to Trigger the Workflow
In src/controllers/app.controller.ts
:
// src/controllers/app.controller.ts
import { Get } from '@moostjs/event-http'
import { Controller, Param } from 'moost'
import { MoostWf } from '@moostjs/event-wf';
import { TQuadraticRootsContext, TQuadraticRootsInputs } from './wf.controller';
@Controller()
export class AppController {
constructor(private wf: MoostWf<Partial<TQuadraticRootsContext>>) {}
@Get("quadratic-roots/:a/:b/:c")
async quadraticRoots(@Param("a") a: number, @Param("b") b: number, @Param("c") c: number) {
const output = await this.wf.start<TQuadraticRootsInputs>("quadratic-roots", {});
if (output.inputRequired && output.resume) {
const { state } = await output.resume({ a, b, c });
return { resumed: true, result: state.context.result };
}
return output.state.context.result;
}
}
We start the workflow with no initial input. If inputRequired
is encountered, we resume the workflow with the provided parameters.
5. Register the Workflow Adapter and Controllers
Update src/main.ts
:
// src/main.ts
import { MoostHttp } from '@moostjs/event-http'
import { MoostWf } from '@moostjs/event-wf'
import { AppController } from './controllers/app.controller'
import { WfController } from './controllers/wf.controller'
import { Moost } from 'moost'
const app = new Moost()
app.adapter(new MoostHttp()).listen(3000)
app.adapter(new MoostWf())
app.registerControllers(AppController, WfController).init();
6. Run the App
npm run dev
Open http://localhost:3000/quadratic-roots/2/5/2
in your browser or use curl
.
What Happens?
- The request triggers the
@Get("quadratic-roots/:a/:b/:c")
endpoint inAppController
. - This starts the workflow "quadratic-roots".
- The workflow initially has no input, so it asks for it (
inputRequired
). - The controller resumes the workflow with
a=2,b=5,c=2
. - Steps run:
validateInputs
,calculateDiscriminant
, then sincediscriminant > 0
, thecalc/double
step executes. - The final result is returned, showing the computed roots.
Next Steps
Explore more about workflows:
By building on these concepts, you can create complex, interactive, and resilient workflows tailored to your application's needs.