Date: 2025-03-10
Status
Proposed
Context
The Codexis system requires robust metadata management through YAML files (meta.yaml and config.yaml). The metadata system needs to handle:
- Book metadata (title, author, ISBN, etc.)
- Build configuration
- Format-specific settings
- Cover image specifications
- Asset management configuration
Decision
We will implement a comprehensive metadata management system with the following components:
1. YAML Schema Definition
defmodule Codexis.Metadata.Schema do
@metadata_schema %{
# Book Metadata
title: [type: :string, required: true],
subtitle: [type: :string],
author: [type: :string, required: true],
publisher: [type: :string, required: true],
isbn: [type: :string, required: true, format: ~r/^\d{13}$/],
language: [type: :string, required: true],
publication_date: [type: :date, required: true],
# Cover Image
cover: %{
path: [type: :string, required: true],
formats: [
type: {:list, :string},
allowed_values: ["jpg", "png", "pdf"],
required: true
]
},
# Format Settings
formats: %{
pdf: [type: :map, default: %{}],
epub: [type: :map, default: %{}],
mobi: [type: :map, default: %{}],
kfx: [type: :map, default: %{}],
wikijs: [type: :map, default: %{}]
}
}
def schema, do: @metadata_schema
end
2. Metadata Loading and Validation
defmodule Codexis.Metadata.Loader do
def load_metadata(meta_path, config_path) do
with {:ok, meta_yaml} <- YamlElixir.read_from_file(meta_path),
{:ok, config_yaml} <- YamlElixir.read_from_file(config_path),
{:ok, merged} <- merge_metadata(meta_yaml, config_yaml),
:ok <- validate_metadata(merged) do
{:ok, merged}
end
end
defp merge_metadata(meta, config) do
# Deep merge strategy
{:ok, DeepMerge.deep_merge(meta, config)}
end
defp validate_metadata(metadata) do
case Vex.validate(metadata, Codexis.Metadata.Schema.schema()) do
{:ok, _} -> :ok
{:error, errors} -> {:error, format_errors(errors)}
end
end
end
3. Format-Specific Transformations
defmodule Codexis.Metadata.FormatTransformer do
def transform_for_format(metadata, format) do
base = get_base_metadata(metadata)
format_specific = get_format_metadata(metadata, format)
merge_and_transform(base, format_specific, format)
end
defp merge_and_transform(base, format_specific, :pdf) do
# PDF-specific transformation
end
defp merge_and_transform(base, format_specific, :wikijs) do
# WikiJS-specific transformation
end
# Other format transformations...
end
4. Cover Image Processing
defmodule Codexis.Metadata.CoverProcessor do
def process_cover(metadata) do
with {:ok, cover_path} <- get_cover_path(metadata),
{:ok, formats} <- get_cover_formats(metadata) do
generate_cover_variants(cover_path, formats)
end
end
defp generate_cover_variants(path, formats) do
formats
|> Task.async_stream(fn format ->
generate_cover_variant(path, format)
end)
|> Enum.reduce(%{}, fn {:ok, {format, path}}, acc ->
Map.put(acc, format, path)
end)
end
end
5. Metadata Access API
defmodule Codexis.Metadata do
def get(key, metadata) do
get_in(metadata, List.wrap(key))
end
def get!(key, metadata) do
case get(key, metadata) do
nil -> raise KeyError, "key #{inspect(key)} not found in metadata"
value -> value
end
end
def update(key, value, metadata) do
put_in(metadata, List.wrap(key), value)
end
end
Consequences
Positive
- Validation: Strong schema validation ensures metadata integrity
- Flexibility: Easy to add new metadata fields and validations
- Transformation: Clean separation of format-specific transformations
- Cover Management: Integrated cover image processing
- API: Simple, consistent metadata access
Negative
- Complexity: More complex than simple YAML parsing
- Performance: Additional validation and transformation overhead
- Dependencies: Requires multiple dependencies (yaml_elixir, vex, etc.)
Risks
- Schema Evolution: Need strategy for handling schema changes
- Backward Compatibility: Must maintain compatibility with existing metadata
- Performance Impact: Monitor validation and transformation overhead
Compliance
Metadata handling must:
- Validate against defined schema
- Transform appropriately for each format
- Handle cover image processing
- Maintain backward compatibility
- Report validation errors clearly
Notes
- Consider caching validated metadata
- Monitor performance metrics
- Document schema changes
- Maintain format compatibility matrix