# Liquid Environment Pattern

Patrón para configurar variables según el ambiente (desarrollo vs producción) usando Liquid templates de Modyo.

---

## Problema

Los widgets necesitan diferentes configuraciones según el ambiente:
- **Desarrollo**: usar mocks, URLs locales
- **Producción**: usar APIs reales, URLs de Modyo

**Anti-patrón**: Usar `.env` con `VITE_USE_MOCKS=true`
- El archivo `.env` está reservado para variables de Modyo CLI (deploy)
- No permite que Modyo inyecte valores en producción

---

## Solución: Liquid Templates

Modyo procesa templates Liquid (`{{vars.x}}`) en producción. En desarrollo, usamos `liquidjs` para simular este comportamiento.

---

## Estructura de Archivos

```
src/
├── config/
│   ├── liquid.json        # Valores para desarrollo
│   ├── liquidConfig.ts    # Inicializa el parser
│   └── widgetConfig.ts    # Exporta configuración parseada
└── utils/
    └── liquidParser.ts    # Motor de parsing
```

---

## Implementación

### 1. `liquid.json` - Valores de Desarrollo

```json
{
  "site": {
    "name": "My Site",
    "language": "es",
    "url": "http://localhost:5173"
  },
  "vars": {
    "api-base-url": "https://api.example.com",
    "use-mocks": "true",
    "currency-symbol": "$",
    "currency-precision": "0",
    "currency-separator": ".",
    "currency-decimal": ","
  }
}
```

> **Nota**: En producción, estos valores son ignorados. Modyo inyecta los valores reales configurados en el sitio.

---

### 2. `liquidParser.ts` - Motor de Parsing

```ts
export default {
  library: {},
  engine: undefined as any,

  init(library: any, Liquid: any) {
    this.library = library;
    if (Liquid) {
      this.engine = new Liquid.Liquid({
        strictFilters: true,
        strictVariables: true,
      });
    }
  },

  parse(liquidString: string): string {
    if (this.engine) {
      // Desarrollo: parsea usando liquidjs
      return this.engine.parseAndRenderSync(liquidString, this.library);
    }
    // Producción: retorna sin procesar (Modyo lo parseará)
    return liquidString;
  },

  async parseAsync(liquidString: string): Promise<string> {
    if (this.engine) {
      return this.engine.parseAndRender(liquidString, this.library);
    }
    return liquidString;
  },
};
```

---

### 3. `liquidConfig.ts` - Inicialización

```ts
import liquidParser from '../utils/liquidParser';
import liquidConfig from './liquid.json';

liquidParser.init(
  liquidConfig,
  import.meta.env.MODE !== 'production' ? (await import('liquidjs')) : null,
);
```

> **Importante**: En producción (`MODE === 'production'`), no se carga `liquidjs` (ahorra bundle size). El parser simplemente retorna el template sin procesar.

---

### 4. `widgetConfig.ts` - Exportación de Variables

```ts
import './liquidConfig';  // Debe importarse primero para inicializar
import liquidParser from '../utils/liquidParser';

// Variables parseadas
export const SITE_LANG = liquidParser.parse('{{site.language}}');
export const API_BASE_URL = liquidParser.parse('{{vars.api-base-url}}');
export const USE_MOCKS = liquidParser.parse('{{vars.use-mocks}}') === 'true';

// Configuración de moneda
export const VARS_CURRENCY = {
  symbol: liquidParser.parse('{{vars.currency-symbol}}'),
  precision: Number(liquidParser.parse('{{vars.currency-precision}}')),
  separator: liquidParser.parse('{{vars.currency-separator}}'),
  decimal: liquidParser.parse('{{vars.currency-decimal}}'),
};

export const widgetConfig = {
  apiBaseUrl: API_BASE_URL,
  useMocks: USE_MOCKS,
  siteLang: SITE_LANG,
};
```

---

## Uso en Repositorios

```ts
// src/services/repositories/AccountsRepository.ts
import { USE_MOCKS, API_BASE_URL } from '../../config/widgetConfig';
import { accountsMock } from '../mocks/data/accounts';
import { api } from '../api/client';

export async function getAccounts(signal?: AbortSignal): Promise<Account[]> {
  if (USE_MOCKS) {
    await new Promise(resolve => setTimeout(resolve, 500)); // Simula latencia
    return accountsMock;
  }

  const { data } = await api.get<Account[]>('/accounts', { signal });
  return data;
}
```

---

## Flujo por Ambiente

### Desarrollo (`npm run dev`)

```
liquid.json          liquidParser           widgetConfig          Repository
     │                    │                      │                     │
"use-mocks": "true" ──→ parse() ──→ USE_MOCKS = true ──→ return mocks
     │
     └── liquidjs procesa el template con valores de liquid.json
```

### Producción (Modyo)

```
Template en código      Modyo Server           widgetConfig          Repository
        │                    │                      │                     │
"{{vars.use-mocks}}" ──→ "false" ──→ USE_MOCKS = false ──→ call API
        │
        └── Modyo reemplaza el template con el valor configurado en el sitio
```

---

## Variables Comunes

| Variable | Template | Uso |
|----------|----------|-----|
| `use-mocks` | `{{vars.use-mocks}}` | Toggle mocks/API |
| `api-base-url` | `{{vars.api-base-url}}` | URL base de API |
| `site.language` | `{{site.language}}` | Idioma del sitio |
| `site.url` | `{{site.url}}` | URL del sitio |
| `currency-symbol` | `{{vars.currency-symbol}}` | Símbolo moneda ($) |
| `currency-precision` | `{{vars.currency-precision}}` | Decimales |

---

## Cambiar Configuración en Desarrollo

Para alternar entre mocks y API real, edita `liquid.json`:

```json
{
  "vars": {
    "use-mocks": "true"   // Usa datos mock
  }
}
```

```json
{
  "vars": {
    "use-mocks": "false"  // Usa API real
  }
}
```

> Requiere reiniciar el servidor de desarrollo (`npm run dev`).

---

## Configuración en Modyo (Producción)

En el panel de Modyo, configura las variables del sitio:

1. Ir a **Channels > Sites > [Tu Sitio] > Settings > Custom Variables**
2. Agregar variables:
   - `use-mocks` = `false`
   - `api-base-url` = `https://api.production.com`

Estas variables se inyectan automáticamente cuando Modyo sirve el widget.

---

## Anti-patrones a Evitar

### ❌ Usar `.env` para configuración de ambiente

```bash
# .env - INCORRECTO
VITE_USE_MOCKS=true
VITE_API_BASE_URL=http://localhost:3000
```

Problemas:
- `.env` está reservado para Modyo CLI
- No funciona en producción (Modyo no lee `.env`)
- Requiere rebuild para cambiar valores

### ✅ Usar Liquid templates

```json
// liquid.json - CORRECTO
{
  "vars": {
    "use-mocks": "true",
    "api-base-url": "http://localhost:3000"
  }
}
```

---

## Checklist de Implementación

- [ ] Crear `src/config/liquid.json` con valores de desarrollo
- [ ] Crear `src/utils/liquidParser.ts` con el motor de parsing
- [ ] Crear `src/config/liquidConfig.ts` que inicializa el parser
- [ ] Crear/actualizar `src/config/widgetConfig.ts` con exports
- [ ] Repositorios importan `USE_MOCKS` desde `widgetConfig`
- [ ] NO usar `import.meta.env.VITE_*` para configuración de ambiente
- [ ] NO crear archivo `.env` para mocks

---

## Ver También

- `modyo://docs/widgets/patterns-repository`
- `modyo://docs/widgets/patterns-api-clients`
- `modyo://docs/widgets/reference-architecture`
