Milesoft Liquid SDK (liquid-sdk)

1. Overview

The Liquid SDK (liquid-sdk) provides a strongly-typed programmatic interface to the Liquid compilation and resolution microservice of the Milesoft platform. It supports high-performance rendering of dynamic text, email layouts, and JSON payloads based on the Liquid template language. It also manages account-level template layouts, global app-level libraries, and custom text filters with automated context lazy-loading.


2. Initialization

2.1 Dependency Installation

The liquid-sdk package is hosted in our secure Google Cloud Artifact Registry repository.

To consume liquid-sdk in your Spring Boot application, apply the Google Cloud Artifact Registry plugin and declare our secure repository in your build.gradle:

plugins {
    id "com.google.cloud.artifactregistry.gradle-plugin" version "2.2.5"
}

repositories {
    mavenCentral()
    maven { url "artifactregistry://us-west2-maven.pkg.dev/milesoft-repo/repo-maven" }
}

dependencies {
    // Declaring the standard liquid-sdk library dependency
    implementation "io.milesoft:liquid-sdk:2.1.1"
}

2.2 Central Spring Boot Configuration

Configure the underlying clients and LiquidService helper class inside your Spring configuration layer.

import io.milesoft.clients.PlatformClient;
import io.milesoft.clients.strategy.PlatformTokenProvider;
import io.milesoft.liquid.client.v2.LibraryClient;
import io.milesoft.liquid.client.v2.LiquidClient;
import io.milesoft.liquid.client.v2.TemplateClient;
import io.milesoft.liquid.services.LiquidService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class LiquidSdkConfig {

    private final LiquidClient liquidClient;
    private final LibraryClient libraryClient;
    private final TemplateClient templateClient;
    private final LiquidService liquidService;

    @Autowired
    public LiquidSdkConfig(PlatformClient platformClient,
                        @Value("${milesoft.liquid.baseUrl}") String baseUrl) {

       PlatformTokenProvider tokenProvider = new PlatformTokenProvider(platformClient);

       this.liquidClient = new LiquidClient(baseUrl, tokenProvider);
       this.libraryClient = new LibraryClient(baseUrl, tokenProvider);
       this.templateClient = new TemplateClient(baseUrl, tokenProvider);
       this.liquidService = new LiquidService(liquidClient);
    }

    @Bean
    public LiquidClient liquidClient() { return liquidClient; }

    @Bean
    public LibraryClient libraryClient() { return libraryClient; }

    @Bean
    public TemplateClient templateClient() { return templateClient; }

    @Bean
    public LiquidService liquidService() { return liquidService; }
}

3. Core SDK Clients & Method Specifications

Programmatic execution is managed across logical clients designed to completely abstract the underlying REST boundaries.

3.1 TemplateClient

Manages account-specific template configurations.

  • Templates list(String cursor, Integer limit, Actor actor): Lists active account templates.
  • Templates loadBulk(Ids payload, Actor actor): Batch resolves templates by ID lists.
  • Template create(SaveTemplate payload, Actor actor): Registers a template.
  • Template update(String templateId, SaveTemplate payload, Actor actor): Updates template content or metadata.
  • Template copy(String templateId, Actor actor): Clones an existing template within the account.
  • Template installLibrary(String libraryId, Actor actor): Clones an app-level library template into the account portfolio.
  • void delete(String templateId, Actor actor): Purges templates.

3.2 LibraryClient

Handles global app-level templates.

  • Templates listLibrary(String cursor, Integer limit, Actor actor): Lists app-level library templates.
  • Templates loadBulkLibrary(Ids payload, Actor actor): Batch resolves library templates.
  • Template createLibrary(SaveTemplate payload, Actor actor): Registers global templates.
  • Template updateLibrary(String id, SaveTemplate payload, Actor actor): Updates global templates.
  • Template cloneLibrary(String id, Actor actor): Clones library templates.
  • void deleteLibrary(String id, Actor actor): Purges library templates.

3.3 LiquidClient

Performs compilation and resolution of Liquid template layouts.

  • Resolved resolve(Resolve payload, Actor actor): Compiles raw Liquid strings using merge variables.
  • ResolvedTemplate resolveSaved(String templateId, MergeData payload, Actor actor): Resolves database templates using merge data.
  • ResolvedBulk resolveBulk(ResolveBulk payload, Actor actor): Compiles multiple raw Liquid strings in a single batch request.

3.4 LiquidService

A high-level convenience service designed for backend applications. It internally extracts the active Actor and handles direct compilation with the minimum boilerplate.

  • String resolve(String template, MergeData data): Directly compiles raw template text.

4. Custom Liquid Filters & Preloaded Contexts

4.1 Custom Template Filters

The Liquid service implements custom formatting filters directly inside the Shopify Liquid compilation engine:

Filter Name Class Example Usage Output / Behavior
json EscapeJsonFilter {{ value | json }} Escapes literal characters safely for raw JSON embedding.
money MoneyFilter {{ 1234.5 | money }} Formats numbers to currency string ($1,234.50).
iso IsoDateTimeFilter {{ created | iso }} Formats date/time, local date, or local time objects to ISO-8601 strings.
full FullDateTimeFilter {{ created | full }} Formats localized datetime using FormatStyle.FULL.
long LongDateTimeFilter {{ created | long }} Formats localized datetime using FormatStyle.LONG.
medium MediumDateTimeFilter {{ created | medium }} Formats localized datetime using FormatStyle.MEDIUM.
short ShortDateTimeFilter {{ created | short }} Formats localized datetime using FormatStyle.SHORT.
pretty PrettyDateTimeFilter {{ created | pretty }} Formats localized datetime using human-friendly pattern eee, d MMM h:mm a.
custom CustomDateTimeFilter {{ created | custom: "yyyy-MM-dd" }} Formats localized datetime using custom format patterns.
range DateTimeRangeFilter {{ start_time | range: stop_time }} Merges two localized datetimes into an optimized localized range span string.

4.2 Lazy-Loaded Context Variables

Render requests leverage lazy-loading mechanisms, fetching metadata from database repositories only if referenced inside the template text:

  1. today (TodayModel): Localized ZonedDateTime, LocalDate, or LocalTime.
  2. app (AppModel): Active application configurations (id, title, url, logo_url, version).
  3. account (AccountModel): Active subscriber metadata, branding colors, and company URLs.
  4. profile (ProfileModel): Profile details of the active operator (id, name, first_name, last_name, email, phone).
  5. user (UserModel): Evaluated if userId is passed in context. Exposes target user profile fields.
  6. contact (ContactModel): Evaluated if contactId is passed in context. Exposes contact directory fields (names, phones, emails, addresses, dates, tags).
  7. users (UsersModel): Plural map of users resolved via userQualifiers.
  8. contacts (ContactsModel): Plural map of contacts resolved via contactQualifiers.

5. Code Examples

5.1 Rendering a Welcome Document

import io.milesoft.liquid.services.LiquidService;
import io.milesoft.primitives.merge.MergeData;
import io.milesoft.primitives.merge.Model;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
import java.util.Map;

@Service
public class DocumentRenderer {

    private final LiquidService liquidService;

    @Autowired
    public DocumentRenderer(LiquidService liquidService) {
        this.liquidService = liquidService;
    }

    public String generateWelcomeEmail(String userId, String contactId, String organizationName) {
        // Construct custom dataset models
        Model companyModel = Model.builder()
            .key("organization")
            .data(Map.of("name", organizationName))
            .build();

        // Populate context merge data
        MergeData mergeData = MergeData.builder()
            .userId(userId)
            .contactId(contactId)
            .models(List.of(companyModel))
            .build();

        String rawTemplate = "Dear {{ contact.first_name }},\n\n"
            + "Our customer success agent, {{ user.name }}, welcomes you on behalf of {{ organization.name }}! "
            + "Your account was successfully provisioned on {{ today.date | pretty }}.\n\n"
            + "Warm regards,\n{{ app.title }} Support";

        // Resolve compiled output using the high-level service helper
        return liquidService.resolve(rawTemplate, mergeData);
    }
}

6. SDK Data Transfer Objects (DTOs)

Ids

Bulk lookup ID parameter payload.

Field Type Description / Constraints
ids List List of unique identifiers. Required / Not Null.

MergeData

Main context container containing all inputs needed to resolve dynamic tokens inside Liquid strings.

Field Type Description / Constraints
userId String Target user ID to bind under user.
contactId String Target contact ID to bind under contact.
userQualifiers List List of custom user qualifiers.
contactQualifiers List List of custom contact qualifiers.
models List Custom model payload lists.

Model

A custom variable payload map to merge dynamically into the Liquid template environment.

Field Type Description / Constraints
key String Root variable namespace (e.g. organization). Required / Not Blank.
data Map<String, Object> Map of keys and values. Required / Not Null. Excluded from toString logging.

Qualifier

A lookup tuple to map a dynamic key to a specific record ID.

Field Type Description / Constraints
key String Context variable key. Required / Not Blank.
id String Target record database ID. Required / Not Blank.

Resolve

Execution parameters to parse a single content string.

Field Type Description / Constraints
content String Target template text. Required / Not Blank. Excluded from toString logging.
data MergeData Contextual merge parameters.

ResolveBulk

Execution parameters to parse a collection of content strings.

Field Type Description / Constraints
content Map<String, String> Dictionary of keys to template text. Required / Not Null. Size >= 1. Excluded from toString logging.
data MergeData Contextual merge parameters.

Resolved

Result from a single content string resolution.

Field Type Description / Constraints
content String Rendered plain text. Required / Not Blank. Excluded from toString logging.

ResolvedBulk

Result from a bulk content string resolution.

Field Type Description / Constraints
content Map<String, String> Dictionary of keys to rendered plain text. Required / Not Null. Size >= 1. Excluded from toString logging.

ResolvedTemplate

Rendered outputs from a database-persisted template.

Field Type Description / Constraints
name String Template name. Required / Not Blank.
content String Rendered main content. Required / Not Blank. Excluded from toString logging.
extra Map<String, String> Rendered dictionary of auxiliary templates. Excluded from toString logging.

SaveTemplate

Represents request payload to write or modify a template.

Field Type Description / Constraints
name String Name of the template. Required / Not Blank.
content String Raw Liquid template body. Required / Not Blank. Excluded from toString logging.
extra Map<String, String> Optional auxiliary template content map. Excluded from toString logging.
order Integer Ordinal sorting value. Required / Not Null. Min(0).
metadata Map<String, Object> Optional custom metadata.

Template

Represents a persisted template model.

Field Type Description / Constraints
id String Unique identifier. Required / Not Blank.
name String Template name. Required / Not Blank.
content String Raw Liquid template body. Required / Not Blank. Excluded from toString logging.
extra Map<String, String> Auxiliary content map. Excluded from toString logging.
order Integer Sort order. Required / Not Null. Min(0).
metadata Map<String, Object> Custom metadata.
created ZonedDateTime Creation timestamp. Required / Not Null.
updated ZonedDateTime Last update timestamp. Required / Not Null.

Templates

A paged container of templates.

Field Type Description / Constraints
templates List