JS20

Documentation

JS20 - Documentation

Chained actions

Actions are reusable code blocks that can be used within endpoints for repeating business logic. An action takes an input, validates it by the inputSchema, runs the action, then validates the output by the outputSchema & finally returns the output.

// app.action is just a helper method to get proper typing
const assertMaxCarsPerUser = app.action({
    outputSchema: {
        count: sInteger().type(),
        message: sString().type(),
    },
    run: async (system) => {
        const maxCarsPerUser = 3;
        const count = await system.models.car.count();
        const isAllowed = count < maxCarsPerUser;

        if (!isAllowed) {
            throw new Error(`You can only create up to ${maxCarsPerUser} cars.`);
        }

        return {
            count,
            message: 'Ok'
        };
    }
});

app.addEndpoint({
    path: '/cars',
    method: 'POST',
    inputSchema: sCar,
    outputSchema: Schema.withInstance(sCar),
    isLoggedIn: true,
    run: async (system, input) => {
        // system.run() ensures system is passed along to the next action
        // as well as ensures input/output validation
        await system.run(assertMaxCarsPerUser);
        return system.models.car.create(input);
    },
});

What's happening here?

  • We have an action called "assertMaxCarsPerUser" that prevents more than 3 cars per user
  • If the action doesn't throw, we proceed to create the car
  • app.action() - This is just a helper method to get types correct (so system.models include your models)
  • Make sure you initialized your app like new App<Models>()!
  • No input is used by this action, hence inputSchema is undefined and there is no input parameter in the run function
  • Use system.run() to start an action. This ensures that the system object & validation works
JS20