Skip to content

Technical

Frontend

If you want to create a custom flow using the generate value functionality you can use the custom platform service ValueGeneratorService. It is available using a call to the platform.get function.

Web component example

import {
    ValueConfig,
    ValueGeneratorService,
    ValueGeneratorServiceName,
} from "src/services/value-generator.interface";

class MyComponent {
    private get valueGenerator(): ValueGeneratorService {
        return this.platform.get(ValueGeneratorServiceName);
    }

    public async generateValue() {
        const context = {
            limetype: "person",
            id: 1001,
        };
        const valueConfig = {
            formula: "{{ company.id }}",
        };

        const generatedValue = await this.valueGenerator.GenerateValue(
            context,
            valueConfig
        );
        console.log("The generated value", generatedValue);
    }
}

Service Interface

To use the service in the platform, the following file must be copied by hand to frontend/src/services/value-generator.interface.ts in your project.

import {
    LimeType,
    LimeWebComponentContext,
} from "@limetech/lime-web-components";

export const ValueGeneratorServiceName =
    "limepkg-standard-actions.value-generator.service";

declare module "@limetech/lime-web-components" {
    interface LimeWebComponentPlatform {
        get(service: typeof ValueGeneratorServiceName): ValueGeneratorService;
    }
}

export interface ValueGeneratorService {
    /**
     * Generate multiple values for a lime object.
     *
     * The values will be generated based on the provided value templates.
     *
     * The generated values will be type casted based on the limetype.
     *
     * The generated values will be returned as a record with the same keys as the value templates.
     *
     * If a value template has a formula, the formula will be evaluated (as jinja2) and the result will be returned.
     *
     * If a value template has a constant, the constant will be returned.
     *
     * If a value template has neither a formula nor a constant, null will be returned.
     *
     * If a value template has an expected output type, the value will be type casted to that type.
     *
     * If a value template has no expected output type, the value will be type casted to the type of the property in the limetype.
     *
     * @param limetype The limetype of the object, will be used for type casting each value.
     * @param context The context, what object the formula has as source.
     * @param valuesTemplate The value templates to generate.
     * @param customContext The extra optional object that the formula has as a source.
     * @returns The generated values.
     */
    GenerateValues(
        limetype: LimeType,
        context: LimeWebComponentContext,
        valuesTemplate: Record<string, ValueConfig>,
        customContext?: Record<string, unknown>
    ): Promise<Record<string, unknown>>;

    /**
     * Generate a single value.
     *
     * The value will be generated based on the provided value configuration.
     *
     * If the value config has an expected output type, the value will be type casted to that type.
     *
     * If the value config has no expected output type, the value will be type casted to the type of the given property in the context limetype.
     *
     * If the value config has no expected output type and no property name, the value will be casted to the best "guess" based on the value.
     *
     * If the value config has a formula, the formula will be evaluated (as jinja2) and the result will be returned.
     *
     * If the value config has a constant, the constant will be returned.
     *
     * If the value config has neither a formula nor a constant, null will be returned.
     *
     * @param context The context, what object the formula has as source.
     * @param valueConfig The value configuration.
     * @param propertyName The name of the property, used for type casting.
     * @param customContext The extra optional object that the formula has as a source.
     * @returns The generated value.
     */
    GenerateValue(
        context: LimeWebComponentContext,
        valueConfig: ValueConfig,
        propertyName?: string,
        customContext?: Record<string, unknown>
    ): Promise<unknown>;
}

export type OutputType =
    | "auto"
    | "int"
    | "float"
    | "str"
    | "datetime"
    | "list"
    | "bool";

export interface ValueConfig {
    constant?: unknown;
    formula?: string;
    expectedOutputType?: OutputType;
}

Backend

If you want to create a custom flow using the generate value functionality you can use our SDK package. It can be imported using limepkg_standard_actions.sdk

Python example

In the below example we expect that you have a LimeApplication called app

import limepkg_standard_actions.sdk as actions_sdk

source_limeobject = app.limetypes.get_limeobject("person", 1001)
value_config = {
    "formula": "{{ company.id }}",
}

generated_value =  actions_sdk.generate_value(
    app=app,
    context_object=source_limeobject,
    value_config=value_config,
)
logger.info(f"Generated value: {generated_value}")

Chained command output

For commands chained via next command, the previous command's result is exposed to formulas via previousCommand.output. See Chained command output for the formula-side usage.

If you're authoring your own command and want its output to be addressable as {{ previousCommand.output.<X> }} without overwriting source properties, register it with the chained-limeobject-output tag:

this.commandBus.register(
    MyCommand,
    new MyHandler(this.limeTypes, this.platform),
    {
        title: '...',
        description: '...',
        tags: ['object', 'chained-limeobject-output'],
        // ...
    }
);

{{ previousCommand.output.<X> }} is available for every chained producer, tagged or not — including custom and external commands such as the Run AI agent command. The tag only controls the top-level spread: without it, the chained output is also spread at top level (so {{ <X> }} resolves too) and may overwrite source properties with matching names. The Standard Actions commands (create-new, update-limeobject, open-form) all carry the tag to suppress that spread; untagged producers keep it for backwards compatibility.

Detecting a cancelled action

By default, when a user cancels an action — dismissing a dialog it opens (e.g. open-form) or declining its confirmation prompt — the dispatched command resolves like any other no-op, so a caller can't tell a cancel apart from a completed action. The cancel is intentionally not surfaced as an error notification.

If a caller needs to react to a cancellation, set throwOnCancel: true on the dispatched command. The handler then throws an ActionAbortedError (an Error whose name is ActionAbortedError) instead of resolving. The flag is opt-in (default off), so existing fire-and-forget callers are unaffected.

Detect it with the exported isActionAbortedError type guard. It matches on the error's name rather than instanceof, so it also works across package boundaries (each package bundles its own copy of the class):

import { isActionAbortedError } from "@lundalogik/limepkg-standard-actions";

try {
    await this.commandBus.handle({
        commandId: "limepkg_standard_actions.open-form",
        context: { limetype: "person", id: 1001 },
        throwOnCancel: true,
    });
    // The action completed (e.g. the form was saved).
} catch (error) {
    if (isActionAbortedError(error)) {
        // The user cancelled — stop here instead of treating it as done.
        return;
    }

    throw error;
}

limepkg-dynamic-checklist uses this so a checklist item's "run actions when done" doesn't mark the item as done when the user cancels.