v0.5.0
This commit is contained in:
parent
aaf7d22374
commit
8d6b53e431
@ -31,8 +31,8 @@ export class FastReportTemplateResolver {
|
|||||||
return this.resolveJoin([module, "templates", companySlug, languageCode]);
|
return this.resolveJoin([module, "templates", companySlug, languageCode]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// <root>/templates/<companySlug>/<module>/<languageCode>
|
// <root>/templates/<module>/<languageCode>
|
||||||
return this.resolveJoin([companySlug, module, languageCode]);
|
return this.resolveJoin([module, languageCode]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Resuelve una ruta de recurso relativa al directorio de plantilla */
|
/** Resuelve una ruta de recurso relativa al directorio de plantilla */
|
||||||
|
|||||||
@ -0,0 +1,97 @@
|
|||||||
|
import { existsSync, readFileSync } from "node:fs";
|
||||||
|
|
||||||
|
import Handlebars from "handlebars";
|
||||||
|
import { lookup } from "mime-types";
|
||||||
|
|
||||||
|
import { RendererTemplateResolver } from "./renderer-template-resolver-SOBRA";
|
||||||
|
|
||||||
|
export class HandlebarsTemplateResolver extends RendererTemplateResolver {
|
||||||
|
protected readonly hbs = Handlebars.create();
|
||||||
|
protected registered = false;
|
||||||
|
protected readonly assetCache = new Map<string, string>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Registra el helper "asset".
|
||||||
|
*
|
||||||
|
* - Si el fichero termina en .b64 → se asume que el contenido ya es base64
|
||||||
|
* - Si no → se lee binario y se convierte a base64
|
||||||
|
*/
|
||||||
|
protected registerAssetHelper(templateDir: string) {
|
||||||
|
// Si ya está registrado, no hacer nada
|
||||||
|
if (this.registered) return;
|
||||||
|
|
||||||
|
this.hbs.registerHelper("asset", (resource: string) => {
|
||||||
|
const assetPath = this.resolveAssetPath(templateDir, resource);
|
||||||
|
const cacheKey = `${assetPath}`;
|
||||||
|
|
||||||
|
// 1) Caché en memoria
|
||||||
|
const cached = this.assetCache.get(cacheKey);
|
||||||
|
if (cached) {
|
||||||
|
return cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!existsSync(assetPath)) {
|
||||||
|
throw new Error(`Asset not found: ${assetPath}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3) Modo "base64"
|
||||||
|
const isPreencoded = assetPath.endsWith(".b64");
|
||||||
|
|
||||||
|
let base64: string;
|
||||||
|
let mimeType: string;
|
||||||
|
let value: string;
|
||||||
|
|
||||||
|
if (isPreencoded) {
|
||||||
|
// Fichero ya contiene el base64 en texto plano
|
||||||
|
base64 = readFileSync(assetPath, "utf8").trim();
|
||||||
|
|
||||||
|
// Para el MIME usamos el nombre "original" sin .b64
|
||||||
|
const mimeLookupPath = assetPath.replace(/\.b64$/, "");
|
||||||
|
mimeType = (lookup(mimeLookupPath) || "application/octet-stream") as string;
|
||||||
|
value = `data:${mimeType};base64,${base64}`;
|
||||||
|
} else {
|
||||||
|
// Fichero normal
|
||||||
|
|
||||||
|
// Si es un CSS no se convierte y se incrusta
|
||||||
|
const isCSS = assetPath.endsWith(".css");
|
||||||
|
if (isCSS) {
|
||||||
|
const buffer = readFileSync(assetPath);
|
||||||
|
value = buffer.toString();
|
||||||
|
} else {
|
||||||
|
// En otro caso, se transforma a Base64
|
||||||
|
const buffer = readFileSync(assetPath);
|
||||||
|
mimeType = (lookup(assetPath) || "application/octet-stream") as string;
|
||||||
|
base64 = buffer.toString("base64");
|
||||||
|
value = `data:${mimeType};base64,${base64}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.assetCache.set(cacheKey, value);
|
||||||
|
return value;
|
||||||
|
});
|
||||||
|
|
||||||
|
this.registered = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Compilación directa desde string (sin resolución de rutas) */
|
||||||
|
public compile(templateSource: string) {
|
||||||
|
return this.hbs.compile(templateSource);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Localiza → lee → registra helpers → compila */
|
||||||
|
public compileTemplate(
|
||||||
|
module: string,
|
||||||
|
companySlug: string,
|
||||||
|
templateName: string
|
||||||
|
): Handlebars.TemplateDelegate {
|
||||||
|
// 1) Directorio de plantillas
|
||||||
|
const templateDir = this.resolveTemplateDirectory(module, companySlug);
|
||||||
|
const templatePath = this.resolveTemplatePath(module, companySlug, templateName); // 2) Path completo del template
|
||||||
|
const source = this.readTemplateFile(templatePath); // Contenido
|
||||||
|
|
||||||
|
this.registerAssetHelper(templateDir);
|
||||||
|
|
||||||
|
// 5) Compilar
|
||||||
|
return this.compile(source);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,61 @@
|
|||||||
|
import { existsSync, readFileSync } from "node:fs";
|
||||||
|
import { join } from "node:path";
|
||||||
|
|
||||||
|
import type { IRendererTemplateResolver } from "../../../application";
|
||||||
|
|
||||||
|
import { FastReportTemplateNotFoundError } from "./fastreport";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resuelve rutas de plantillas para desarrollo y producción.
|
||||||
|
*/
|
||||||
|
export abstract class RendererTemplateResolver implements IRendererTemplateResolver {
|
||||||
|
constructor(protected readonly rootPath: string) {}
|
||||||
|
|
||||||
|
/** Une partes de ruta relativas al rootPath */
|
||||||
|
protected resolveJoin(parts: string[]): string {
|
||||||
|
return join(this.rootPath, ...parts);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Devuelve el directorio donde residen las plantillas de un módulo/empresa
|
||||||
|
* según el entorno (dev/prod).
|
||||||
|
*/
|
||||||
|
protected resolveTemplateDirectory(module: string, companySlug: string): string {
|
||||||
|
const isDev = process.env.NODE_ENV === "development";
|
||||||
|
|
||||||
|
if (isDev) {
|
||||||
|
// <root>/<module>/templates/<companySlug>/
|
||||||
|
return this.resolveJoin([module, "templates", companySlug]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// <root>/templates/<module>/<companySlug>/
|
||||||
|
//return this.resolveJoin(["templates", module, companySlug]);
|
||||||
|
return this.resolveJoin([module]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Resuelve una ruta de recurso relativa al directorio de plantilla */
|
||||||
|
protected resolveAssetPath(templateDir: string, relative: string): string {
|
||||||
|
return join(templateDir, relative);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Devuelve la ruta absoluta del fichero de plantilla.
|
||||||
|
*/
|
||||||
|
public resolveTemplatePath(module: string, companySlug: string, templateName: string): string {
|
||||||
|
const dir = this.resolveTemplateDirectory(module, companySlug);
|
||||||
|
const filePath = this.resolveAssetPath(dir, templateName);
|
||||||
|
|
||||||
|
if (!existsSync(filePath)) {
|
||||||
|
throw new FastReportTemplateNotFoundError(
|
||||||
|
`Template not found: module=${module} company=${companySlug} name=${templateName}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Lee el contenido de un fichero plantilla */
|
||||||
|
protected readTemplateFile(templatePath: string): string {
|
||||||
|
return readFileSync(templatePath, "utf8");
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_VERSION="1.2.8"
|
SCRIPT_VERSION="1.2.9"
|
||||||
|
|
||||||
# =====================================================
|
# =====================================================
|
||||||
# FACTUGES Build Script
|
# FACTUGES Build Script
|
||||||
@ -194,6 +194,7 @@ if [[ "$MODE" == "api" || "$MODE" == "all" ]]; then
|
|||||||
# Recopilar plantillas
|
# Recopilar plantillas
|
||||||
${SCRIPT_DIR}/build-templates.sh ${COMPANY}
|
${SCRIPT_DIR}/build-templates.sh ${COMPANY}
|
||||||
TEMPLATES_DIR="${PROJECT_DIR}/out/${COMPANY}/templates"
|
TEMPLATES_DIR="${PROJECT_DIR}/out/${COMPANY}/templates"
|
||||||
|
echo "📑 Plantillas ${TEMPLATES_DIR}"
|
||||||
|
|
||||||
cd "${PROJECT_DIR}"
|
cd "${PROJECT_DIR}"
|
||||||
echo "🐳 Construyendo imagen Docker..."
|
echo "🐳 Construyendo imagen Docker..."
|
||||||
|
|||||||
@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
SCRIPT_VERSION="0.0.2"
|
SCRIPT_VERSION="0.0.3"
|
||||||
|
|
||||||
# =====================================================
|
# =====================================================
|
||||||
# TEMPLATES Build Script
|
# TEMPLATES Build Script
|
||||||
@ -54,7 +54,7 @@ rm -rf "${TARGET_DIR:?}/"*
|
|||||||
for module in "$SOURCE_DIR"/*; do
|
for module in "$SOURCE_DIR"/*; do
|
||||||
if [ -d "$module/templates/$COMPANY" ]; then
|
if [ -d "$module/templates/$COMPANY" ]; then
|
||||||
module_name=$(basename "$module")
|
module_name=$(basename "$module")
|
||||||
echo "→ Copying templates for module: $module_name"
|
echo "📑 → Copying templates for module: $module_name"
|
||||||
|
|
||||||
mkdir -p "$TARGET_DIR/$module_name"
|
mkdir -p "$TARGET_DIR/$module_name"
|
||||||
cp -Rv "$module/templates/$COMPANY/." "$TARGET_DIR/$module_name/"
|
cp -Rv "$module/templates/$COMPANY/." "$TARGET_DIR/$module_name/"
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Loading…
Reference in New Issue
Block a user