Templating Language inside a Code Transformer

Hi Alumio,

I’ve heard you’re working on/thinking about a Code Transformer. I guess a lot of people would be happy with something like this (including myself), but actually I’d like to suggest prioritizing something similar but also somewhat different.

I wouldn’t know what to call it, but something like a ‘Template Transformer’. I’m used to working with different templating languages (like Laravel’s Blade) for frontend and something like XSLT, which is a templating language specifically for XML.

Templating languages allow you to “start with the end in mind”. For example if you’ve got XML:

<xml>
  <order id="500">
    <adres straat="Newtonlaan" huisnummer="201" />
    <inhoud>
      <product sku="ABC" aantal="1" />
    </inhoud>
  </order>
</xml>

But this needs another format, you could write this XSLT:

<transport>
  <id><xsl:value-of select="order/@id"/></id>
  <street><xsl:value-of select="order/adres/@straat"/></street>
  <number><xsl:value-of select="order/adres/@huisnummer"/></number>
  <orderlines>
    <orderline>
      <sku><xsl:value-of select="order/inhoud/product/@sku"/></sku>
      <quantity><xsl:value-of select="order/inhoud/product/@aantal"/></quantity>
    </orderline>
  </orderlines>
</transport>

Ofcourse, this is XML. But the concept is great: you could simply copy the needed JSON from API Documentation, and “fill in the blanks”. This is possible in a very limited way with JMESPath already, but because JMESPath is a query language it allows too little flexibility for loops, foreaches, etc.

I would really love a “limited” templating language like Laravel’s Blade ( Blade Templates - Laravel 10.x - The PHP Framework For Web Artisans ) to be implemented for this. My guess is you’d often need 50-60% less transformers while maintaining readability (which you do not have in Javascript transforming for example). Also, because these templating languages are generally already meant for “secure environments”, it’s often relatively easy to make sure you’re not able to do certain things (like infinite loops).

Another example of a system using something like this, is Shopware. Shopware uses Twig ( https://twig.symfony.com/ ) for both frontend templates as well as backend stuff like sending webhooks and creating product feeds. You can use Twig to write specific JSON in Shopware. It works somewhat awkwardly sometimes, but that’s likely something that can be fixed with a specific implementation.

Just to give an example what Shopware does.

In Shopware you can send a webhook based on certain flows/events within the system, and you can define a webhook using Twig. This looks like this:

{
    "orderNumber": "{{ order.orderNumber }}",
    "orderLines": [
        {% for lineItem in order.LineItems %}
        {
            "productName": "{{ lineItem.label }}",
            "productQuantity": "{{ lineItem.quantity }}",
            "productLineTaxTotal": "{{ lineItem.price.calculatedTaxes.amount }}",
            "productLineTotal": "{{ lineItem.totalPrice }}",
            "productEntityId": "{{ lineItem.productId }}"
        }{% if not loop.last %},{% endif %}
        {% endfor %}
    ],
    "orderShippingAddress": {
        {% for delivery in order.deliveries %}
        "shippingCompany": "{{ delivery.shippingOrderAddress.company }}",
        "shippingName": "{{ delivery.shippingOrderAddress.firstName }} {{ delivery.shippingOrderAddress.lastName }}",
        "shippingAddress": "{{ delivery.shippingOrderAddress.street }}",
        "shippingPostCode": "{{ delivery.shippingOrderAddress.zipcode }}",
        "shippingCity": "{{ delivery.shippingOrderAddress.city }}",
        "shippingCountryId": "{{ delivery.shippingOrderAddress.country.iso }}",
        "shippingPhone": "{{ delivery.shippingOrderAddress.phoneNumber }}"
        {% endfor %}
    },
    "shippingEmail": "{{ order.orderCustomer.email }}",
    "orderBillingAddress": {
        {% set billingAddress = order.addresses.get(order.billingAddressId) %}
        "billingCompany": "{{ billingAddress.company }}",
        "billingName": "{{ billingAddress.firstName }} {{ billingAddress.lastName }}",
        "billingAddress": "{{ billingAddress.street }}",
        "billingPostCode": "{{ billingAddress.zipcode }}",
        "billingCity": "{{ billingAddress.city }}",
        "billingCountryId": "{{ billingAddress.country.iso }}"
    },
    "orderTotalPrice": "{{ order.price.totalPrice }}",
    "orderTaxes": [
        {% for tax in order.price.calculatedTaxes %}
        {
            "tax": "{{ tax.tax }}"
        }{% if not loop.last %},{% endif %}
        {% endfor %}
    ],
    "invoiceCurrencyCode": "EUR",
    "invoiceDiscountAmount": "0.0000",
    "invoiceSubTotal": "{{ order.amountNet }}",
    "invoiceAmount": "0.0000",
    {% for shippingCost in order.deliveries %}
        "invoiceShippingAmount": "{{ shippingCost.shippingCosts.totalPrice }}",
    {% endfor %}
    "paymentReference": "{{ order.orderNumber }}",
    "affiliateCode": "{{ order.affiliateCode }}",
    "orderInternalId": "{{ order.id }}"
}

As you can see, this is very readable. It has some awkwardness as well: because JSON requires arrays to have comma’s up until the end, you have to check in every ‘node’ of an array whether it’s the last one in the array. But stuff like that could be fixed in the implementation

Hi @floris

Thank you for your feedback regarding templating functionality inside a Code Transformer. I understand how improving the technical aspect of Alumio would benefit you and other users.

Therefore, I will pass your feedback to the team and notify you if there are any updates.

Have a great weekend ahead!

1 Like