Packages
A robust WebSocket client library for Elixir, built on Gun transport for production-grade reliability. Designed for financial APIs with automatic reconnection, comprehensive error handling, and real-world testing.
Current section
Files
Jump to
Current section
Files
lib/mix/tasks/zen_websocket.usage.ex
defmodule Mix.Tasks.ZenWebsocket.Usage do
@shortdoc "Export ZenWebsocket usage rules for AI agents"
@moduledoc """
Mix task to export ZenWebsocket usage rules for AI agents and developers.
This task integrates with the usage_rules library to make ZenWebsocket's
usage patterns easily accessible in other projects.
## Usage
mix zen_websocket.usage
## Options
* `--format` - Output format: `markdown` (default) or `json`
* `--output` - Output file path (defaults to stdout)
* `--sections` - Comma-separated list of sections to include
## Examples
# Output to stdout
mix zen_websocket.usage
# Save to file
mix zen_websocket.usage --output my_rules.md
# Export specific sections
mix zen_websocket.usage --sections "quick_start,common_patterns,error_handling"
# Export as JSON for programmatic use
mix zen_websocket.usage --format json --output rules.json
"""
use Mix.Task
@usage_rules_path "USAGE_RULES.md"
@available_sections [
"core_principles",
"quick_start",
"essential_functions",
"common_patterns",
"configuration",
"platform_specific",
"error_handling",
"testing_rules",
"do_not",
"architecture_notes",
"monitoring",
"module_limits",
"common_mistakes",
"migration",
"performance",
"environment_variables",
"best_practices"
]
@impl Mix.Task
def run(args) do
{opts, _, _} =
OptionParser.parse(args,
strict: [
format: :string,
output: :string,
sections: :string
]
)
format = Keyword.get(opts, :format, "markdown")
output = Keyword.get(opts, :output)
sections = parse_sections(opts[:sections])
case format do
"markdown" -> export_markdown(output, sections)
"json" -> export_json(output, sections)
_ -> Mix.raise("Unknown format: #{format}. Use 'markdown' or 'json'.")
end
end
defp export_markdown(output, sections) do
content = read_usage_rules()
filtered = filter_sections(content, sections)
write_output(filtered, output)
Mix.shell().info("✅ ZenWebsocket usage rules exported successfully")
end
defp export_json(output, sections) do
content = read_usage_rules()
filtered = filter_sections(content, sections)
# Get version from mix.exs project config
version = :zen_websocket |> Application.spec(:vsn) |> to_string()
# Simple JSON structure with the markdown content
json_data = %{
"format" => "markdown",
"source" => "ZenWebsocket",
"version" => version,
"sections" => sections || "all",
"content" => filtered
}
json = Jason.encode!(json_data, pretty: true)
write_output(json, output)
Mix.shell().info("✅ ZenWebsocket usage rules exported as JSON")
end
defp read_usage_rules do
path = Path.join([File.cwd!(), @usage_rules_path])
case File.read(path) do
{:ok, content} ->
content
{:error, :enoent} ->
Mix.raise("USAGE_RULES.md not found. Please ensure it exists in the project root.")
{:error, reason} ->
Mix.raise("Failed to read USAGE_RULES.md: #{inspect(reason)}")
end
end
defp filter_sections(content, nil), do: content
defp filter_sections(content, sections) do
lines = String.split(content, "\n")
filtered =
lines
|> Enum.reduce({[], nil, false}, fn line, {acc, current_section, include} ->
cond do
String.starts_with?(line, "## ") ->
section = normalize_section(line)
include = section in sections
{maybe_add_line(acc, line, include), section, include}
String.starts_with?(line, "# ") ->
# Always include main title
{[line | acc], current_section, include}
true ->
{maybe_add_line(acc, line, include), current_section, include}
end
end)
|> elem(0)
|> Enum.reverse()
|> Enum.join("\n")
filtered
end
defp maybe_add_line(acc, line, true), do: [line | acc]
defp maybe_add_line(acc, _line, false), do: acc
defp normalize_section(line) do
line
|> String.replace("## ", "")
|> String.downcase()
|> String.replace(" ", "_")
|> String.replace("-", "_")
end
defp write_output(content, nil) do
IO.puts(content)
end
defp write_output(content, path) do
case File.write(path, content) do
:ok -> Mix.shell().info("Output written to: #{path}")
{:error, reason} -> Mix.raise("Failed to write output: #{inspect(reason)}")
end
end
defp parse_sections(nil), do: nil
defp parse_sections(sections_str) do
sections_str
|> String.split(",")
|> Enum.map(&String.trim/1)
|> Enum.map(&String.downcase/1)
|> Enum.map(&String.replace(&1, "-", "_"))
|> Enum.filter(&(&1 in @available_sections))
end
end