updat edeps
This commit is contained in:
parent
281aef095c
commit
77d2a6ca30
15 changed files with 600 additions and 82 deletions
10
.gitignore
vendored
10
.gitignore
vendored
|
|
@ -61,3 +61,13 @@ gleam@@compile.erl
|
||||||
/.expert
|
/.expert
|
||||||
.envrc
|
.envrc
|
||||||
.worktrees/
|
.worktrees/
|
||||||
|
|
||||||
|
# Nix development environment state
|
||||||
|
.nix-mix/
|
||||||
|
.nix-hex/
|
||||||
|
.nix-postgres/
|
||||||
|
.nix-postgres-version
|
||||||
|
.nix-services-started
|
||||||
|
.direnv/
|
||||||
|
# Generated by pre-commit-hooks.nix (symlink into /nix/store)
|
||||||
|
.pre-commit-config.yaml
|
||||||
|
|
|
||||||
124
flake.lock
generated
Normal file
124
flake.lock
generated
Normal file
|
|
@ -0,0 +1,124 @@
|
||||||
|
{
|
||||||
|
"nodes": {
|
||||||
|
"flake-compat": {
|
||||||
|
"flake": false,
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1767039857,
|
||||||
|
"narHash": "sha256-vNpUSpF5Nuw8xvDLj2KCwwksIbjua2LZCqhV1LNRDns=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "flake-compat",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"flake-parts": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs-lib": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1769996383,
|
||||||
|
"narHash": "sha256-AnYjnFWgS49RlqX7LrC4uA+sCCDBj0Ry/WOJ5XWAsa0=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"rev": "57928607ea566b5db3ad13af0e57e921e6b12381",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "flake-parts",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"gitignore": {
|
||||||
|
"inputs": {
|
||||||
|
"nixpkgs": [
|
||||||
|
"pre-commit-hooks",
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1709087332,
|
||||||
|
"narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=",
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"rev": "637db329424fd7e46cf4185293b9cc8c88c95394",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "hercules-ci",
|
||||||
|
"repo": "gitignore.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"nixpkgs": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1784120854,
|
||||||
|
"narHash": "sha256-KesHgItiZPgGX740axSiQLcIQ8D24MDqNpkKYWIek8k=",
|
||||||
|
"owner": "NixOS",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"rev": "753cc8a3a87467296ddd1fa93f0cc3e81120ee46",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "NixOS",
|
||||||
|
"ref": "nixos-unstable",
|
||||||
|
"repo": "nixpkgs",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"pre-commit-hooks": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-compat": "flake-compat",
|
||||||
|
"gitignore": "gitignore",
|
||||||
|
"nixpkgs": [
|
||||||
|
"nixpkgs"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1769939035,
|
||||||
|
"narHash": "sha256-Fok2AmefgVA0+eprw2NDwqKkPGEI5wvR+twiZagBvrg=",
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "pre-commit-hooks.nix",
|
||||||
|
"rev": "a8ca480175326551d6c4121498316261cbb5b260",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "cachix",
|
||||||
|
"repo": "pre-commit-hooks.nix",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": {
|
||||||
|
"inputs": {
|
||||||
|
"flake-parts": "flake-parts",
|
||||||
|
"nixpkgs": "nixpkgs",
|
||||||
|
"pre-commit-hooks": "pre-commit-hooks",
|
||||||
|
"systems": "systems"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"systems": {
|
||||||
|
"locked": {
|
||||||
|
"lastModified": 1681028828,
|
||||||
|
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||||
|
"type": "github"
|
||||||
|
},
|
||||||
|
"original": {
|
||||||
|
"owner": "nix-systems",
|
||||||
|
"repo": "default",
|
||||||
|
"type": "github"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"root": "root",
|
||||||
|
"version": 7
|
||||||
|
}
|
||||||
73
flake.nix
Normal file
73
flake.nix
Normal file
|
|
@ -0,0 +1,73 @@
|
||||||
|
{
|
||||||
|
description = "aprs.me - Phoenix LiveView APRS packet mapping platform";
|
||||||
|
|
||||||
|
inputs = {
|
||||||
|
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
|
||||||
|
|
||||||
|
flake-parts = {
|
||||||
|
url = "github:hercules-ci/flake-parts";
|
||||||
|
inputs.nixpkgs-lib.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
|
||||||
|
systems.url = "github:nix-systems/default";
|
||||||
|
|
||||||
|
pre-commit-hooks = {
|
||||||
|
url = "github:cachix/pre-commit-hooks.nix";
|
||||||
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
outputs =
|
||||||
|
inputs@{
|
||||||
|
self,
|
||||||
|
nixpkgs,
|
||||||
|
flake-parts,
|
||||||
|
systems,
|
||||||
|
pre-commit-hooks,
|
||||||
|
}:
|
||||||
|
flake-parts.lib.mkFlake { inherit inputs; } {
|
||||||
|
# nixpkgs 26.11 dropped x86_64-darwin support
|
||||||
|
systems = builtins.filter (s: s != "x86_64-darwin") (import systems);
|
||||||
|
|
||||||
|
perSystem =
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
self',
|
||||||
|
inputs',
|
||||||
|
pkgs,
|
||||||
|
system,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
{
|
||||||
|
_module.args.pkgs = import nixpkgs {
|
||||||
|
inherit system;
|
||||||
|
overlays = [
|
||||||
|
# Pin specific Elixir and Erlang versions to match .tool-versions
|
||||||
|
# Elixir 1.20.2-otp-29, Erlang 29.0.1
|
||||||
|
(final: prev: {
|
||||||
|
# Use Erlang 29 — no top-level erlang_29 yet, use beam.interpreters
|
||||||
|
erlang = prev.beam.interpreters.erlang_29;
|
||||||
|
|
||||||
|
# Use Elixir 1.20 with Erlang 29 (1.20.2-otp-29)
|
||||||
|
elixir = prev.beam.packages.erlang_29.elixir_1_20;
|
||||||
|
|
||||||
|
# Ensure beam packages use our pinned versions
|
||||||
|
beamPackages = prev.beam.packages.erlang_29.extend (
|
||||||
|
self: super: {
|
||||||
|
elixir = super.elixir_1_20;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
})
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
# Development shell with PostgreSQL (PostGIS), LSPs, formatters
|
||||||
|
devShells.default = pkgs.callPackage ./nix/shell.nix {
|
||||||
|
pre-commit-hooks = inputs.pre-commit-hooks.lib.${system};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Nix formatter for flake files
|
||||||
|
formatter = pkgs.nixfmt;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -35,15 +35,15 @@
|
||||||
{assigns[:page_title] || "Aprs"}
|
{assigns[:page_title] || "Aprs"}
|
||||||
</.live_title>
|
</.live_title>
|
||||||
<link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} />
|
<link phx-track-static rel="stylesheet" href={~p"/assets/css/app.css"} />
|
||||||
|
|
||||||
<!-- Minimal vendor CSS -->
|
<!-- Minimal vendor CSS -->
|
||||||
<link phx-track-static rel="stylesheet" href={~p"/assets/vendor/css/minimal-bundle.css"} />
|
<link phx-track-static rel="stylesheet" href={~p"/assets/vendor/css/minimal-bundle.css"} />
|
||||||
|
|
||||||
<!-- Core utilities - always loaded -->
|
<!-- Core utilities - always loaded -->
|
||||||
<script phx-track-static src={~p"/assets/vendor/js/core-bundle.js"}>
|
<script phx-track-static src={~p"/assets/vendor/js/core-bundle.js"}>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Conditional loading based on page type -->
|
<!-- Conditional loading based on page type -->
|
||||||
<script>
|
<script>
|
||||||
window.VendorLoader = {
|
window.VendorLoader = {
|
||||||
mapBundleUrl: '/assets/vendor/js/map-bundle.js',
|
mapBundleUrl: '/assets/vendor/js/map-bundle.js',
|
||||||
|
|
@ -72,12 +72,12 @@
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- App scripts -->
|
<!-- App scripts -->
|
||||||
<script phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
|
<script phx-track-static type="text/javascript" src={~p"/assets/app.js"}>
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<!-- Privacy-friendly analytics by Plausible -->
|
<!-- Privacy-friendly analytics by Plausible -->
|
||||||
<script async src="https://a.w5isp.com/js/pa-7BkaTcdFcxr5y-7yhqhlJ.js">
|
<script async src="https://a.w5isp.com/js/pa-7BkaTcdFcxr5y-7yhqhlJ.js">
|
||||||
</script>
|
</script>
|
||||||
<script>
|
<script>
|
||||||
|
|
|
||||||
|
|
@ -363,8 +363,8 @@ defmodule AprsmeWeb.ApiDocsLive do
|
||||||
RESTful JSON API for accessing APRS packet data and station information.
|
RESTful JSON API for accessing APRS packet data and station information.
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- API Overview -->
|
<!-- API Overview -->
|
||||||
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10 mb-8">
|
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10 mb-8">
|
||||||
<div class="px-6 py-8">
|
<div class="px-6 py-8">
|
||||||
<h2 class="text-2xl font-semibold text-gray-900 dark:text-white">Overview</h2>
|
<h2 class="text-2xl font-semibold text-gray-900 dark:text-white">Overview</h2>
|
||||||
|
|
@ -415,8 +415,8 @@ defmodule AprsmeWeb.ApiDocsLive do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- API Endpoints -->
|
<!-- API Endpoints -->
|
||||||
<div class="space-y-8">
|
<div class="space-y-8">
|
||||||
<!-- Callsign Endpoint -->
|
<!-- Callsign Endpoint -->
|
||||||
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
||||||
|
|
@ -499,8 +499,8 @@ defmodule AprsmeWeb.ApiDocsLive do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Weather Nearby Endpoint -->
|
<!-- Weather Nearby Endpoint -->
|
||||||
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
||||||
<div class="px-6 py-8">
|
<div class="px-6 py-8">
|
||||||
<div class="flex items-center justify-between mb-4">
|
<div class="flex items-center justify-between mb-4">
|
||||||
|
|
@ -627,8 +627,8 @@ defmodule AprsmeWeb.ApiDocsLive do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Response Fields Documentation -->
|
<!-- Response Fields Documentation -->
|
||||||
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
||||||
<div class="px-6 py-8">
|
<div class="px-6 py-8">
|
||||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">Response Fields</h2>
|
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">Response Fields</h2>
|
||||||
|
|
@ -726,8 +726,8 @@ defmodule AprsmeWeb.ApiDocsLive do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- HTTP Status Codes -->
|
<!-- HTTP Status Codes -->
|
||||||
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
||||||
<div class="px-6 py-8">
|
<div class="px-6 py-8">
|
||||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">HTTP Status Codes</h2>
|
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">HTTP Status Codes</h2>
|
||||||
|
|
@ -789,8 +789,8 @@ defmodule AprsmeWeb.ApiDocsLive do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Future Endpoints -->
|
<!-- Future Endpoints -->
|
||||||
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
||||||
<div class="px-6 py-8">
|
<div class="px-6 py-8">
|
||||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">Planned Endpoints</h2>
|
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">Planned Endpoints</h2>
|
||||||
|
|
@ -843,8 +843,8 @@ defmodule AprsmeWeb.ApiDocsLive do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Interactive API Testing -->
|
<!-- Interactive API Testing -->
|
||||||
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
||||||
<div class="px-6 py-8">
|
<div class="px-6 py-8">
|
||||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">Test the API</h2>
|
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">Test the API</h2>
|
||||||
|
|
@ -897,8 +897,8 @@ defmodule AprsmeWeb.ApiDocsLive do
|
||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Error Display -->
|
<!-- Error Display -->
|
||||||
<%= if @error do %>
|
<%= if @error do %>
|
||||||
<div class="rounded-md bg-red-50 p-4 dark:bg-red-500/10 mt-4 max-w-md">
|
<div class="rounded-md bg-red-50 p-4 dark:bg-red-500/10 mt-4 max-w-md">
|
||||||
<div class="flex">
|
<div class="flex">
|
||||||
|
|
@ -920,8 +920,8 @@ defmodule AprsmeWeb.ApiDocsLive do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Results Display -->
|
<!-- Results Display -->
|
||||||
<%= if @api_result do %>
|
<%= if @api_result do %>
|
||||||
<div class="mt-4">
|
<div class="mt-4">
|
||||||
<h4 class="text-lg font-medium mb-2">API Response</h4>
|
<h4 class="text-lg font-medium mb-2">API Response</h4>
|
||||||
|
|
@ -946,8 +946,8 @@ defmodule AprsmeWeb.ApiDocsLive do
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Contact and Support -->
|
<!-- Contact and Support -->
|
||||||
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
<div class="bg-white shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
||||||
<div class="px-6 py-8">
|
<div class="px-6 py-8">
|
||||||
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">Support</h2>
|
<h2 class="text-xl font-semibold text-gray-900 dark:text-white">Support</h2>
|
||||||
|
|
|
||||||
|
|
@ -185,8 +185,8 @@
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Map showing station location -->
|
<!-- Map showing station location -->
|
||||||
<%= if @packet.lat && @packet.lon do %>
|
<%= if @packet.lat && @packet.lon do %>
|
||||||
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10 h-full">
|
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10 h-full">
|
||||||
<% {symbol_table, symbol_code} = AprsmeWeb.AprsSymbol.extract_from_packet(@packet) %>
|
<% {symbol_table, symbol_code} = AprsmeWeb.AprsSymbol.extract_from_packet(@packet) %>
|
||||||
|
|
@ -202,8 +202,8 @@
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Row for Device Information and Other SSIDs -->
|
<!-- Row for Device Information and Other SSIDs -->
|
||||||
<div class="lg:col-span-2 grid grid-cols-1 gap-4 lg:grid-cols-2">
|
<div class="lg:col-span-2 grid grid-cols-1 gap-4 lg:grid-cols-2">
|
||||||
<!-- Device information -->
|
<!-- Device information -->
|
||||||
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10">
|
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10">
|
||||||
|
|
@ -293,8 +293,8 @@
|
||||||
</dl>
|
</dl>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Other SSIDs -->
|
<!-- Other SSIDs -->
|
||||||
<%= if length(@other_ssids) > 0 do %>
|
<%= if length(@other_ssids) > 0 do %>
|
||||||
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10">
|
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10">
|
||||||
<div class="px-6 py-6">
|
<div class="px-6 py-6">
|
||||||
|
|
@ -407,8 +407,8 @@
|
||||||
<% end %>
|
<% end %>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Neighboring stations -->
|
<!-- Neighboring stations -->
|
||||||
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10">
|
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10">
|
||||||
<div class="px-6 py-6">
|
<div class="px-6 py-6">
|
||||||
<div class="flex items-center mb-3">
|
<div class="flex items-center mb-3">
|
||||||
|
|
@ -502,8 +502,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Stations that heard this callsign on RF -->
|
<!-- Stations that heard this callsign on RF -->
|
||||||
<%= if length(@heard_by_stations) > 0 do %>
|
<%= if length(@heard_by_stations) > 0 do %>
|
||||||
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10 mt-6">
|
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10 mt-6">
|
||||||
<div class="px-6 py-6">
|
<div class="px-6 py-6">
|
||||||
|
|
@ -607,8 +607,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Stations heard directly by this callsign -->
|
<!-- Stations heard directly by this callsign -->
|
||||||
<%= if length(@stations_heard_by) > 0 do %>
|
<%= if length(@stations_heard_by) > 0 do %>
|
||||||
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10 mt-6">
|
<div class="bg-white shadow-xs sm:rounded-lg ring-1 ring-gray-950/5 dark:bg-gray-800/50 dark:shadow-none dark:ring-white/10 mt-6">
|
||||||
<div class="px-6 py-6">
|
<div class="px-6 py-6">
|
||||||
|
|
|
||||||
|
|
@ -1457,8 +1457,8 @@ defmodule AprsmeWeb.MapLive.Index do
|
||||||
{gettext("Real-time APRS packet tracking")}
|
{gettext("Real-time APRS packet tracking")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Content -->
|
<!-- Content -->
|
||||||
<div class="relative flex-1 overflow-y-auto bg-white px-5 py-5 dark:bg-gray-800 dark:after:absolute dark:after:inset-y-0 dark:after:left-0 dark:after:w-px dark:after:bg-white/10">
|
<div class="relative flex-1 overflow-y-auto bg-white px-5 py-5 dark:bg-gray-800 dark:after:absolute dark:after:inset-y-0 dark:after:left-0 dark:after:w-px dark:after:bg-white/10">
|
||||||
<div class="space-y-5">
|
<div class="space-y-5">
|
||||||
<!-- Callsign Search -->
|
<!-- Callsign Search -->
|
||||||
|
|
@ -1507,8 +1507,8 @@ defmodule AprsmeWeb.MapLive.Index do
|
||||||
<% end %>
|
<% end %>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Other SSIDs -->
|
<!-- Other SSIDs -->
|
||||||
<%= if @tracked_callsign != "" and @other_ssids != [] do %>
|
<%= if @tracked_callsign != "" and @other_ssids != [] do %>
|
||||||
<div class="rounded-lg bg-gray-50 p-4 ring-1 ring-gray-950/5 dark:bg-gray-900/50 dark:ring-white/10">
|
<div class="rounded-lg bg-gray-50 p-4 ring-1 ring-gray-950/5 dark:bg-gray-900/50 dark:ring-white/10">
|
||||||
<label class="mb-3 flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
|
<label class="mb-3 flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
|
||||||
|
|
@ -1558,8 +1558,8 @@ defmodule AprsmeWeb.MapLive.Index do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- Trail Duration -->
|
<!-- Trail Duration -->
|
||||||
<div class="rounded-lg bg-gray-50 p-4 ring-1 ring-gray-950/5 dark:bg-gray-900/50 dark:ring-white/10">
|
<div class="rounded-lg bg-gray-50 p-4 ring-1 ring-gray-950/5 dark:bg-gray-900/50 dark:ring-white/10">
|
||||||
<label class="mb-3 flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
|
<label class="mb-3 flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
|
||||||
<svg class="h-3.5 w-3.5 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="h-3.5 w-3.5 text-emerald-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
|
@ -1572,7 +1572,7 @@ defmodule AprsmeWeb.MapLive.Index do
|
||||||
</svg>
|
</svg>
|
||||||
{gettext("Trail Duration")}
|
{gettext("Trail Duration")}
|
||||||
</label>
|
</label>
|
||||||
<form phx-change="update_trail_duration">
|
<form id="trail-duration-form" phx-change="update_trail_duration">
|
||||||
<select
|
<select
|
||||||
name="trail_duration"
|
name="trail_duration"
|
||||||
class="block w-full rounded-md bg-white px-3 py-2 text-sm text-gray-900 shadow-xs outline-1 -outline-offset-1 outline-gray-300 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 dark:bg-gray-800 dark:text-white dark:outline-white/10 dark:focus:outline-indigo-500"
|
class="block w-full rounded-md bg-white px-3 py-2 text-sm text-gray-900 shadow-xs outline-1 -outline-offset-1 outline-gray-300 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 dark:bg-gray-800 dark:text-white dark:outline-white/10 dark:focus:outline-indigo-500"
|
||||||
|
|
@ -1598,8 +1598,8 @@ defmodule AprsmeWeb.MapLive.Index do
|
||||||
</select>
|
</select>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Historical Data -->
|
<!-- Historical Data -->
|
||||||
<div class="rounded-lg bg-gray-50 p-4 ring-1 ring-gray-950/5 dark:bg-gray-900/50 dark:ring-white/10">
|
<div class="rounded-lg bg-gray-50 p-4 ring-1 ring-gray-950/5 dark:bg-gray-900/50 dark:ring-white/10">
|
||||||
<label class="mb-3 flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
|
<label class="mb-3 flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
|
||||||
<svg class="h-3.5 w-3.5 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="h-3.5 w-3.5 text-amber-500" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
|
@ -1612,7 +1612,7 @@ defmodule AprsmeWeb.MapLive.Index do
|
||||||
</svg>
|
</svg>
|
||||||
{gettext("Historical Data")}
|
{gettext("Historical Data")}
|
||||||
</label>
|
</label>
|
||||||
<form phx-change="update_historical_hours">
|
<form id="historical-hours-form" phx-change="update_historical_hours">
|
||||||
<select
|
<select
|
||||||
name="historical_hours"
|
name="historical_hours"
|
||||||
class="block w-full rounded-md bg-white px-3 py-2 text-sm text-gray-900 shadow-xs outline-1 -outline-offset-1 outline-gray-300 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 dark:bg-gray-800 dark:text-white dark:outline-white/10 dark:focus:outline-indigo-500"
|
class="block w-full rounded-md bg-white px-3 py-2 text-sm text-gray-900 shadow-xs outline-1 -outline-offset-1 outline-gray-300 focus:outline-2 focus:-outline-offset-2 focus:outline-indigo-600 dark:bg-gray-800 dark:text-white dark:outline-white/10 dark:focus:outline-indigo-500"
|
||||||
|
|
@ -1635,8 +1635,8 @@ defmodule AprsmeWeb.MapLive.Index do
|
||||||
</select>
|
</select>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Navigation -->
|
<!-- Navigation -->
|
||||||
<div class="border-t border-gray-200 pt-4 dark:border-white/10">
|
<div class="border-t border-gray-200 pt-4 dark:border-white/10">
|
||||||
<label class="mb-3 flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
|
<label class="mb-3 flex items-center gap-2 text-xs font-semibold uppercase tracking-wider text-gray-500 dark:text-gray-400">
|
||||||
<svg class="h-3.5 w-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
<svg class="h-3.5 w-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||||
|
|
@ -1658,8 +1658,8 @@ defmodule AprsmeWeb.MapLive.Index do
|
||||||
/>
|
/>
|
||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Status Footer -->
|
<!-- Status Footer -->
|
||||||
<div class="border-t border-gray-200 pt-4 dark:border-white/10">
|
<div class="border-t border-gray-200 pt-4 dark:border-white/10">
|
||||||
<div class="grid grid-cols-2 gap-4">
|
<div class="grid grid-cols-2 gap-4">
|
||||||
<div>
|
<div>
|
||||||
|
|
|
||||||
|
|
@ -70,8 +70,8 @@ defmodule AprsmeWeb.StatusLive.ConnectionCardComponent do
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Packet Statistics -->
|
<!-- Packet Statistics -->
|
||||||
<div class="border-t border-gray-200 dark:border-white/10 my-4"></div>
|
<div class="border-t border-gray-200 dark:border-white/10 my-4"></div>
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-sm font-medium mb-3">Packet Statistics</h3>
|
<h3 class="text-sm font-medium mb-3">Packet Statistics</h3>
|
||||||
|
|
|
||||||
|
|
@ -140,8 +140,8 @@ defmodule AprsmeWeb.StatusLive.Index do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<% end %>
|
<% end %>
|
||||||
|
|
||||||
<!-- APRS-IS Connection Status -->
|
<!-- APRS-IS Connection Status -->
|
||||||
<div class="mb-8">
|
<div class="mb-8">
|
||||||
<h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-white">{gettext("APRS-IS Connection")}</h2>
|
<h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-white">{gettext("APRS-IS Connection")}</h2>
|
||||||
<div class="rounded-lg bg-gray-50 p-6 dark:bg-gray-700/50">
|
<div class="rounded-lg bg-gray-50 p-6 dark:bg-gray-700/50">
|
||||||
|
|
@ -206,8 +206,8 @@ defmodule AprsmeWeb.StatusLive.Index do
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Packet Statistics -->
|
<!-- Packet Statistics -->
|
||||||
<div class="border-t border-gray-200 dark:border-white/10 my-4"></div>
|
<div class="border-t border-gray-200 dark:border-white/10 my-4"></div>
|
||||||
<div>
|
<div>
|
||||||
<h3 class="text-sm font-medium mb-3 text-gray-900 dark:text-white">{gettext("Packet Statistics")}</h3>
|
<h3 class="text-sm font-medium mb-3 text-gray-900 dark:text-white">{gettext("Packet Statistics")}</h3>
|
||||||
|
|
@ -285,8 +285,8 @@ defmodule AprsmeWeb.StatusLive.Index do
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Health Score -->
|
<!-- Health Score -->
|
||||||
<div class="border-t border-gray-200 dark:border-white/10 my-4"></div>
|
<div class="border-t border-gray-200 dark:border-white/10 my-4"></div>
|
||||||
<div class="flex items-center justify-between">
|
<div class="flex items-center justify-between">
|
||||||
<span class="text-sm font-medium text-gray-500 dark:text-gray-400">{gettext("Connection Health:")}</span>
|
<span class="text-sm font-medium text-gray-500 dark:text-gray-400">{gettext("Connection Health:")}</span>
|
||||||
|
|
@ -317,8 +317,8 @@ defmodule AprsmeWeb.StatusLive.Index do
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Cluster Information (if available) -->
|
<!-- Cluster Information (if available) -->
|
||||||
<%= if Map.has_key?(@aprs_status, :cluster_info) do %>
|
<%= if Map.has_key?(@aprs_status, :cluster_info) do %>
|
||||||
<div class="mb-8">
|
<div class="mb-8">
|
||||||
<h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-white">{gettext("Cluster Status")}</h2>
|
<h2 class="text-xl font-semibold mb-4 text-gray-900 dark:text-white">{gettext("Cluster Status")}</h2>
|
||||||
|
|
|
||||||
|
|
@ -97,8 +97,8 @@ defmodule AprsmeWeb.UserSettingsLive do
|
||||||
</div>
|
</div>
|
||||||
</.simple_form>
|
</.simple_form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Change Callsign Section -->
|
<!-- Change Callsign Section -->
|
||||||
<div class="bg-white px-6 py-8 shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
<div class="bg-white px-6 py-8 shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
||||||
<h2 class="text-xl font-semibold text-gray-900 mb-6 dark:text-white">Change Callsign</h2>
|
<h2 class="text-xl font-semibold text-gray-900 mb-6 dark:text-white">Change Callsign</h2>
|
||||||
|
|
||||||
|
|
@ -179,8 +179,8 @@ defmodule AprsmeWeb.UserSettingsLive do
|
||||||
</div>
|
</div>
|
||||||
</.simple_form>
|
</.simple_form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Change Password Section -->
|
<!-- Change Password Section -->
|
||||||
<div class="bg-white px-6 py-8 shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
<div class="bg-white px-6 py-8 shadow-sm sm:rounded-lg dark:bg-gray-800/50 dark:shadow-none dark:outline dark:-outline-offset-1 dark:outline-white/10">
|
||||||
<h2 class="text-xl font-semibold text-gray-900 mb-6 dark:text-white">Change Password</h2>
|
<h2 class="text-xl font-semibold text-gray-900 mb-6 dark:text-white">Change Password</h2>
|
||||||
|
|
||||||
|
|
|
||||||
4
mix.exs
4
mix.exs
|
|
@ -94,7 +94,7 @@ defmodule Aprsme.MixProject do
|
||||||
{:phoenix_html, "~> 4.3.0"},
|
{:phoenix_html, "~> 4.3.0"},
|
||||||
{:phoenix_live_dashboard, "~> 0.8"},
|
{:phoenix_live_dashboard, "~> 0.8"},
|
||||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||||
{:phoenix_live_view, "~> 1.1.26"},
|
{:phoenix_live_view, "~> 1.2"},
|
||||||
{:postgrex, ">= 0.0.0"},
|
{:postgrex, ">= 0.0.0"},
|
||||||
{:swoosh, "~> 1.23"},
|
{:swoosh, "~> 1.23"},
|
||||||
{:telemetry_metrics, "~> 1.0"},
|
{:telemetry_metrics, "~> 1.0"},
|
||||||
|
|
@ -102,7 +102,7 @@ defmodule Aprsme.MixProject do
|
||||||
{:prom_ex, "~> 1.12"},
|
{:prom_ex, "~> 1.12"},
|
||||||
aprs_dep(),
|
aprs_dep(),
|
||||||
{:esbuild, "~> 0.10", runtime: Mix.env() == :dev},
|
{:esbuild, "~> 0.10", runtime: Mix.env() == :dev},
|
||||||
{:tailwind, "~> 0.4.0", runtime: Mix.env() == :dev},
|
{:tailwind, "~> 0.5", runtime: Mix.env() == :dev},
|
||||||
{:bandit, "~> 1.5"},
|
{:bandit, "~> 1.5"},
|
||||||
{:req, "~> 0.5"},
|
{:req, "~> 0.5"},
|
||||||
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
|
{:credo, "~> 1.7", only: [:dev, :test], runtime: false},
|
||||||
|
|
|
||||||
18
mix.lock
18
mix.lock
|
|
@ -3,7 +3,7 @@
|
||||||
"bandit": {:hex, :bandit, "1.12.0", "6c5214daa2469644ac4ab0113b98abc24f75e348378e6a974c6343b3e5da22ef", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.5", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "45dac82dc86f45cf4a196dee9cc5a8b791d9c9469d996055f055e6ee36c66e20"},
|
"bandit": {:hex, :bandit, "1.12.0", "6c5214daa2469644ac4ab0113b98abc24f75e348378e6a974c6343b3e5da22ef", [:mix], [{:hpax, "~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}, {:plug, "~> 1.18", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:thousand_island, "~> 1.5", [hex: :thousand_island, repo: "hexpm", optional: false]}, {:websock, "~> 0.5", [hex: :websock, repo: "hexpm", optional: false]}], "hexpm", "45dac82dc86f45cf4a196dee9cc5a8b791d9c9469d996055f055e6ee36c66e20"},
|
||||||
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.3.2", "d50091e3c9492d73e17fc1e1619a9b09d6a5ef99160eb4d736926fd475a16ca3", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "471be5151874ae7931911057d1467d908955f93554f7a6cd1b7d804cac8cef53"},
|
"bcrypt_elixir": {:hex, :bcrypt_elixir, "3.3.2", "d50091e3c9492d73e17fc1e1619a9b09d6a5ef99160eb4d736926fd475a16ca3", [:make, :mix], [{:comeonin, "~> 5.3", [hex: :comeonin, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.6", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "471be5151874ae7931911057d1467d908955f93554f7a6cd1b7d804cac8cef53"},
|
||||||
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
|
"bunt": {:hex, :bunt, "1.0.0", "081c2c665f086849e6d57900292b3a161727ab40431219529f13c4ddcf3e7a44", [:mix], [], "hexpm", "dc5f86aa08a5f6fa6b8096f0735c4e76d54ae5c9fa2c143e5a1fc7c1cd9bb6b5"},
|
||||||
"castore": {:hex, :castore, "1.0.19", "6903cabdfd9d1af46454126e7c8385186659dd33ecfb74a885cae52221ad6109", [:mix], [], "hexpm", "3669e6cab13f54c2df26b3e6833745d647f35b6e30d8ddd5975df0d5c842ca98"},
|
"castore": {:hex, :castore, "1.0.20", "455e48f7115eca98c9f2b0e7a152b5a2e8f2a8a4f964c96e95bd31645ee5fa59", [:mix], [], "hexpm", "940eafbfd8b14bee649f083bc11b3b54ec555b54c3e4ea8213351ff6fee39c10"},
|
||||||
"cc_precompiler": {:hex, :cc_precompiler, "0.1.11", "8c844d0b9fb98a3edea067f94f616b3f6b29b959b6b3bf25fee94ffe34364768", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3427232caf0835f94680e5bcf082408a70b48ad68a5f5c0b02a3bea9f3a075b9"},
|
"cc_precompiler": {:hex, :cc_precompiler, "0.1.11", "8c844d0b9fb98a3edea067f94f616b3f6b29b959b6b3bf25fee94ffe34364768", [:mix], [{:elixir_make, "~> 0.7", [hex: :elixir_make, repo: "hexpm", optional: false]}], "hexpm", "3427232caf0835f94680e5bcf082408a70b48ad68a5f5c0b02a3bea9f3a075b9"},
|
||||||
"circular_buffer": {:hex, :circular_buffer, "1.0.1", "01f0e3d5fe945080692cf6521c0988e9dbb5dc312831cefe77e5b63a4e658160", [:mix], [], "hexpm", "7d4ece3137d49c1f8dd0b3e0aa7c484f4d83a0be5d4b516c282085c1d5f2d7b9"},
|
"circular_buffer": {:hex, :circular_buffer, "1.0.1", "01f0e3d5fe945080692cf6521c0988e9dbb5dc312831cefe77e5b63a4e658160", [:mix], [], "hexpm", "7d4ece3137d49c1f8dd0b3e0aa7c484f4d83a0be5d4b516c282085c1d5f2d7b9"},
|
||||||
"comeonin": {:hex, :comeonin, "5.5.1", "5113e5f3800799787de08a6e0db307133850e635d34e9fab23c70b6501669510", [:mix], [], "hexpm", "65aac8f19938145377cee73973f192c5645873dcf550a8a6b18187d17c13ccdb"},
|
"comeonin": {:hex, :comeonin, "5.5.1", "5113e5f3800799787de08a6e0db307133850e635d34e9fab23c70b6501669510", [:mix], [], "hexpm", "65aac8f19938145377cee73973f192c5645873dcf550a8a6b18187d17c13ccdb"},
|
||||||
|
|
@ -11,7 +11,7 @@
|
||||||
"db_connection": {:hex, :db_connection, "2.10.2", "ae391e803a5adff104da913c2fc1c0c14a37f8b10001dcef568796e1fb7bf95c", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "510b14482330f1af6490a2fa0efd8d4f1435d1529b165647df22ac0f2df0fa93"},
|
"db_connection": {:hex, :db_connection, "2.10.2", "ae391e803a5adff104da913c2fc1c0c14a37f8b10001dcef568796e1fb7bf95c", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "510b14482330f1af6490a2fa0efd8d4f1435d1529b165647df22ac0f2df0fa93"},
|
||||||
"decimal": {:hex, :decimal, "3.1.1", "430d87b04011ce6cbd4fd205be758311a81f87d552d40904abd00f015935b1d0", [:mix], [], "hexpm", "c5f25f2ced74a0587d03e6023f595db8e924c9d3922c8c8ffd9edfc4498cf1f6"},
|
"decimal": {:hex, :decimal, "3.1.1", "430d87b04011ce6cbd4fd205be758311a81f87d552d40904abd00f015935b1d0", [:mix], [], "hexpm", "c5f25f2ced74a0587d03e6023f595db8e924c9d3922c8c8ffd9edfc4498cf1f6"},
|
||||||
"dialyxir": {:hex, :dialyxir, "1.4.7", "dda948fcee52962e4b6c5b4b16b2d8fa7d50d8645bbae8b8685c3f9ecb7f5f4d", [:mix], [{:erlex, ">= 0.2.8", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b34527202e6eb8cee198efec110996c25c5898f43a4094df157f8d28f27d9efe"},
|
"dialyxir": {:hex, :dialyxir, "1.4.7", "dda948fcee52962e4b6c5b4b16b2d8fa7d50d8645bbae8b8685c3f9ecb7f5f4d", [:mix], [{:erlex, ">= 0.2.8", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "b34527202e6eb8cee198efec110996c25c5898f43a4094df157f8d28f27d9efe"},
|
||||||
"ecto": {:hex, :ecto, "3.14.0", "2fa64521eebfcb2670d907a86e4ad947290e9933706bb315e6fb5c21b172cb26", [:mix], [{:decimal, "~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "130d69ffb4285f9ce4792b65dfbb994fd13ea4cbc3cbea2524b199aa3de84af3"},
|
"ecto": {:hex, :ecto, "3.14.1", "7b740d87bdf45996aa0c2c2e081640906f10caa7ce5ba328fd294c7d49d0cc6f", [:mix], [{:decimal, "~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "24b991956796700f467d0a3ef3d303138a3ef9ddddf8b98f43758ee067b20a30"},
|
||||||
"ecto_sql": {:hex, :ecto_sql, "3.14.0", "06446ab8410d2f85bfbb80857ee224ab3b693700cbb38f6535d507449a627b2e", [:mix], [{:db_connection, "~> 2.9", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.14.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.8", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f4d8d36faf294c9417b5a37ec7ac8217ee2abdef5fcf197ba690f361548d3949"},
|
"ecto_sql": {:hex, :ecto_sql, "3.14.0", "06446ab8410d2f85bfbb80857ee224ab3b693700cbb38f6535d507449a627b2e", [:mix], [{:db_connection, "~> 2.9", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:ecto, "~> 3.14.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.8", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.19 or ~> 1.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.1 or ~> 2.2", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "f4d8d36faf294c9417b5a37ec7ac8217ee2abdef5fcf197ba690f361548d3949"},
|
||||||
"elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
|
"elixir_make": {:hex, :elixir_make, "0.9.0", "6484b3cd8c0cee58f09f05ecaf1a140a8c97670671a6a0e7ab4dc326c3109726", [:mix], [], "hexpm", "db23d4fd8b757462ad02f8aa73431a426fe6671c80b200d9710caf3d1dd0ffdb"},
|
||||||
"erlex": {:hex, :erlex, "0.2.9", "7debbbaa9f4f368b8cd648983e0f1d7963028508e9c59e9d4ed504e94ef52a55", [:mix], [], "hexpm", "8cfffc0ec7159e6d73de2ab28a588064de80f88b2798d5cbe4482cbbc200178b"},
|
"erlex": {:hex, :erlex, "0.2.9", "7debbbaa9f4f368b8cd648983e0f1d7963028508e9c59e9d4ed504e94ef52a55", [:mix], [], "hexpm", "8cfffc0ec7159e6d73de2ab28a588064de80f88b2798d5cbe4482cbbc200178b"},
|
||||||
|
|
@ -33,7 +33,7 @@
|
||||||
"lazy_html": {:hex, :lazy_html, "0.1.11", "136c8e9cd616b4f4e9c1562daa683880891120b759606dc4c3b6b18058ba5d79", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.9.0", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1.0", [hex: :fine, repo: "hexpm", optional: false]}], "hexpm", "3b1be592929c31eca1a21673d25696e5c14cddfe922d9d1a3e3b48be4163883b"},
|
"lazy_html": {:hex, :lazy_html, "0.1.11", "136c8e9cd616b4f4e9c1562daa683880891120b759606dc4c3b6b18058ba5d79", [:make, :mix], [{:cc_precompiler, "~> 0.1", [hex: :cc_precompiler, repo: "hexpm", optional: false]}, {:elixir_make, "~> 0.9.0", [hex: :elixir_make, repo: "hexpm", optional: false]}, {:fine, "~> 0.1.0", [hex: :fine, repo: "hexpm", optional: false]}], "hexpm", "3b1be592929c31eca1a21673d25696e5c14cddfe922d9d1a3e3b48be4163883b"},
|
||||||
"libcluster": {:hex, :libcluster, "3.5.0", "5ee4cfde4bdf32b2fef271e33ce3241e89509f4344f6c6a8d4069937484866ba", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.3", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ebf6561fcedd765a4cd43b4b8c04b1c87f4177b5fb3cbdfe40a780499d72f743"},
|
"libcluster": {:hex, :libcluster, "3.5.0", "5ee4cfde4bdf32b2fef271e33ce3241e89509f4344f6c6a8d4069937484866ba", [:mix], [{:jason, "~> 1.1", [hex: :jason, repo: "hexpm", optional: false]}, {:telemetry, "~> 1.3", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "ebf6561fcedd765a4cd43b4b8c04b1c87f4177b5fb3cbdfe40a780499d72f743"},
|
||||||
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
|
"mime": {:hex, :mime, "2.0.7", "b8d739037be7cd402aee1ba0306edfdef982687ee7e9859bee6198c1e7e2f128", [:mix], [], "hexpm", "6171188e399ee16023ffc5b76ce445eb6d9672e2e241d2df6050f3c771e80ccd"},
|
||||||
"mint": {:hex, :mint, "1.9.1", "3bc120b743ed2e99ad920910f2613e9faebabb2257731b0e2ea4d8ccd9eceede", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "831101bd560b086316fab5f7adb21a4f3455717d8e4bc8368b052e09aa9163e0"},
|
"mint": {:hex, :mint, "1.9.3", "3337184d69179695c7a9f1714d92c11e629d36c8c037a21cf490131d3d150554", [:mix], [{:castore, "~> 0.1.0 or ~> 1.0", [hex: :castore, repo: "hexpm", optional: true]}, {:hpax, "~> 0.1.1 or ~> 0.2.0 or ~> 1.0", [hex: :hpax, repo: "hexpm", optional: false]}], "hexpm", "5f7c9342480c069dbbc4eeac3490303c9e01870ff01a7f1d29b6107054fc1e74"},
|
||||||
"mix_test_watch": {:hex, :mix_test_watch, "1.4.0", "d88bcc4fbe3198871266e9d2f00cd8ae350938efbb11d3fa1da091586345adbb", [:mix], [{:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "2b4693e17c8ead2ef56d4f48a0329891e8c2d0d73752c0f09272a2b17dc38d1b"},
|
"mix_test_watch": {:hex, :mix_test_watch, "1.4.0", "d88bcc4fbe3198871266e9d2f00cd8ae350938efbb11d3fa1da091586345adbb", [:mix], [{:file_system, "~> 0.2 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}], "hexpm", "2b4693e17c8ead2ef56d4f48a0329891e8c2d0d73752c0f09272a2b17dc38d1b"},
|
||||||
"mox": {:hex, :mox, "1.2.0", "a2cd96b4b80a3883e3100a221e8adc1b98e4c3a332a8fc434c39526babafd5b3", [:mix], [{:nimble_ownership, "~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}], "hexpm", "c7b92b3cc69ee24a7eeeaf944cd7be22013c52fcb580c1f33f50845ec821089a"},
|
"mox": {:hex, :mox, "1.2.0", "a2cd96b4b80a3883e3100a221e8adc1b98e4c3a332a8fc434c39526babafd5b3", [:mix], [{:nimble_ownership, "~> 1.0", [hex: :nimble_ownership, repo: "hexpm", optional: false]}], "hexpm", "c7b92b3cc69ee24a7eeeaf944cd7be22013c52fcb580c1f33f50845ec821089a"},
|
||||||
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
|
"nimble_options": {:hex, :nimble_options, "1.1.1", "e3a492d54d85fc3fd7c5baf411d9d2852922f66e69476317787a7b2bb000a61b", [:mix], [], "hexpm", "821b2470ca9442c4b6984882fe9bb0389371b8ddec4d45a9504f00a66f650b44"},
|
||||||
|
|
@ -46,19 +46,19 @@
|
||||||
"phoenix_html": {:hex, :phoenix_html, "4.3.0", "d3577a5df4b6954cd7890c84d955c470b5310bb49647f0a114a6eeecc850f7ad", [:mix], [], "hexpm", "3eaa290a78bab0f075f791a46a981bbe769d94bc776869f4f3063a14f30497ad"},
|
"phoenix_html": {:hex, :phoenix_html, "4.3.0", "d3577a5df4b6954cd7890c84d955c470b5310bb49647f0a114a6eeecc850f7ad", [:mix], [], "hexpm", "3eaa290a78bab0f075f791a46a981bbe769d94bc776869f4f3063a14f30497ad"},
|
||||||
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.7", "405880012cb4b706f26dd1c6349125bfc903fb9e44d1ea668adaf4e04d4884b7", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "3a8625cab39ec261d48a13b7468dc619c0ede099601b084e343968309bd4d7d7"},
|
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.8.7", "405880012cb4b706f26dd1c6349125bfc903fb9e44d1ea668adaf4e04d4884b7", [:mix], [{:ecto, "~> 3.6.2 or ~> 3.7", [hex: :ecto, repo: "hexpm", optional: true]}, {:ecto_mysql_extras, "~> 0.5", [hex: :ecto_mysql_extras, repo: "hexpm", optional: true]}, {:ecto_psql_extras, "~> 0.7", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:ecto_sqlite3_extras, "~> 1.1.7 or ~> 1.2.0", [hex: :ecto_sqlite3_extras, repo: "hexpm", optional: true]}, {:mime, "~> 1.6 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.19 or ~> 1.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "3a8625cab39ec261d48a13b7468dc619c0ede099601b084e343968309bd4d7d7"},
|
||||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.6.2", "b18b0773a1ba77f28c52decbb0f10fd1ac4d3ae5b8632399bbf6986e3b665f62", [:mix], [{:file_system, "~> 0.2.10 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "d1f89c18114c50d394721365ffb428cce24f1c13de0467ffa773e2ff4a30d5b9"},
|
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.6.2", "b18b0773a1ba77f28c52decbb0f10fd1ac4d3ae5b8632399bbf6986e3b665f62", [:mix], [{:file_system, "~> 0.2.10 or ~> 1.0", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "d1f89c18114c50d394721365ffb428cce24f1c13de0467ffa773e2ff4a30d5b9"},
|
||||||
"phoenix_live_view": {:hex, :phoenix_live_view, "1.1.32", "4977ad4cfab7868f3d2ba390a2cd6c62412614d48f798e85785602281a0a3827", [:mix], [{:igniter, ">= 0.6.16 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:lazy_html, "~> 0.1.0", [hex: :lazy_html, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0-rc", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3c9d8e76373414259ec5699a809991d1324808bee1d297730599e273282cee34"},
|
"phoenix_live_view": {:hex, :phoenix_live_view, "1.2.7", "d0f20871681216598e78baccd4f66d8686fdb8007821989bab508d293a3ed9ad", [:mix], [{:igniter, ">= 0.6.16 and < 1.0.0-0", [hex: :igniter, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:lazy_html, "~> 0.1.0", [hex: :lazy_html, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.6.15 or ~> 1.7.0 or ~> 1.8.0", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 3.3 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_template, "~> 1.0", [hex: :phoenix_template, repo: "hexpm", optional: false]}, {:phoenix_view, "~> 2.0", [hex: :phoenix_view, repo: "hexpm", optional: true]}, {:plug, "~> 1.15", [hex: :plug, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "61e97938a4fcca6d6f2c836925623abf2f52a572cc8c6085e4074f3f6337e0eb"},
|
||||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.2.0", "ff3a5616e1bed6804de7773b92cbccfc0b0f473faf1f63d7daf1206c7aeaaa6f", [:mix], [], "hexpm", "adc313a5bf7136039f63cfd9668fde73bba0765e0614cba80c06ac9460ff3e96"},
|
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.2.0", "ff3a5616e1bed6804de7773b92cbccfc0b0f473faf1f63d7daf1206c7aeaaa6f", [:mix], [], "hexpm", "adc313a5bf7136039f63cfd9668fde73bba0765e0614cba80c06ac9460ff3e96"},
|
||||||
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
|
"phoenix_template": {:hex, :phoenix_template, "1.0.4", "e2092c132f3b5e5b2d49c96695342eb36d0ed514c5b252a77048d5969330d639", [:mix], [{:phoenix_html, "~> 2.14.2 or ~> 3.0 or ~> 4.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}], "hexpm", "2c0c81f0e5c6753faf5cca2f229c9709919aba34fab866d3bc05060c9c444206"},
|
||||||
"plug": {:hex, :plug, "1.20.2", "adbee2441232412e37fbb357fd5e4cd533fdd253b29f2e1992262b0f1fb01462", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "b16baf55877d60891002ffc1ce0b3ff7d6f30a38a23e02e4d4293c4ac266f136"},
|
"plug": {:hex, :plug, "1.20.3", "56c480c633ec2ce10140e236e15233bf576e1d323887d7c96711bd02ab5160db", [:mix], [{:mime, "~> 1.0 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2 or ~> 2.0", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.3 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "be266aee1b8536ef6409d58cf39a3121319f0ec47cfa1b24024485aa0e76ad76"},
|
||||||
"plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"},
|
"plug_crypto": {:hex, :plug_crypto, "2.1.1", "19bda8184399cb24afa10be734f84a16ea0a2bc65054e23a62bb10f06bc89491", [:mix], [], "hexpm", "6470bce6ffe41c8bd497612ffde1a7e4af67f36a15eea5f921af71cf3e11247c"},
|
||||||
"postgrex": {:hex, :postgrex, "0.22.2", "4aec14df2a72722aee92492566edbeeb44e233ecb86b1915d03136297ef1385d", [:mix], [{:db_connection, "~> 2.9", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "8946382ddb06294f56026ac4278b3cc212bac8a2c82ed68b4087819ed1abc53b"},
|
"postgrex": {:hex, :postgrex, "0.22.3", "bf65941737ee7a9adbe4a64c91080310d11703da343e8ac9188aacb9eb9f6f02", [:mix], [{:db_connection, "~> 2.9", [hex: :db_connection, repo: "hexpm", optional: false]}, {:decimal, "~> 1.5 or ~> 2.0 or ~> 3.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:table, "~> 0.1.0", [hex: :table, repo: "hexpm", optional: true]}], "hexpm", "f018c13752b2b46e8d35d7e2d84c3276557cbfd880769109021a1d0ee36c1cfe"},
|
||||||
"prom_ex": {:hex, :prom_ex, "1.12.0", "a82cbd5b49964e4d4295ab72a18e007aadd5f4a91630b7c49fad42cc7e49c880", [:mix], [{:absinthe, ">= 1.8.0", [hex: :absinthe, repo: "hexpm", optional: true]}, {:broadway, ">= 1.1.0", [hex: :broadway, repo: "hexpm", optional: true]}, {:ecto, ">= 3.14.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:finch, "~> 0.18", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, ">= 2.10.0", [hex: :oban, repo: "hexpm", optional: true]}, {:octo_fetch, "~> 0.4", [hex: :octo_fetch, repo: "hexpm", optional: false]}, {:peep, "~> 3.0 or ~> 4.0", [hex: :peep, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, ">= 0.20.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, ">= 1.16.0", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 2.6.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, ">= 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.2", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.1", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "6357484941489ba2fee64bb1e9f2a1e86309545304f9e90144e3c10e553c958b"},
|
"prom_ex": {:hex, :prom_ex, "1.12.0", "a82cbd5b49964e4d4295ab72a18e007aadd5f4a91630b7c49fad42cc7e49c880", [:mix], [{:absinthe, ">= 1.8.0", [hex: :absinthe, repo: "hexpm", optional: true]}, {:broadway, ">= 1.1.0", [hex: :broadway, repo: "hexpm", optional: true]}, {:ecto, ">= 3.14.0", [hex: :ecto, repo: "hexpm", optional: true]}, {:finch, "~> 0.18", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:oban, ">= 2.10.0", [hex: :oban, repo: "hexpm", optional: true]}, {:octo_fetch, "~> 0.4", [hex: :octo_fetch, repo: "hexpm", optional: false]}, {:peep, "~> 3.0 or ~> 4.0", [hex: :peep, repo: "hexpm", optional: false]}, {:phoenix, ">= 1.7.0", [hex: :phoenix, repo: "hexpm", optional: true]}, {:phoenix_live_view, ">= 0.20.0", [hex: :phoenix_live_view, repo: "hexpm", optional: true]}, {:plug, ">= 1.16.0", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 2.6.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:telemetry, ">= 1.0.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}, {:telemetry_metrics_prometheus_core, "~> 1.2", [hex: :telemetry_metrics_prometheus_core, repo: "hexpm", optional: false]}, {:telemetry_poller, "~> 1.1", [hex: :telemetry_poller, repo: "hexpm", optional: false]}], "hexpm", "6357484941489ba2fee64bb1e9f2a1e86309545304f9e90144e3c10e553c958b"},
|
||||||
"req": {:hex, :req, "0.6.2", "b9b2024f35bcf60a92cc8cad2eaaf9d4e7aace463ff74be1afe5986830184413", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.21", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "cc9cd30a2ddd04989929b887178e1610c940456d962c6c3a52df6146d2eef9bf"},
|
"req": {:hex, :req, "0.6.3", "7fe5e68792ff0546e45d5919104fa1764a13694cfe3e48c8a0f32ad051ae77e4", [:mix], [{:brotli, "~> 0.3.1", [hex: :brotli, repo: "hexpm", optional: true]}, {:ezstd, "~> 1.0", [hex: :ezstd, repo: "hexpm", optional: true]}, {:finch, "~> 0.21", [hex: :finch, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mime, "~> 2.0.6 or ~> 2.1", [hex: :mime, repo: "hexpm", optional: false]}, {:nimble_csv, "~> 1.0", [hex: :nimble_csv, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: true]}], "hexpm", "e85b5c6c990e6c3f52bbba68e6f099118f2b8252825f96c7c3636b97a3de307d"},
|
||||||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
|
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.7", "354c321cf377240c7b8716899e182ce4890c5938111a1296add3ec74cf1715df", [:make, :mix, :rebar3], [], "hexpm", "fe4c190e8f37401d30167c8c405eda19469f34577987c76dde613e838bbc67f8"},
|
||||||
"stream_data": {:hex, :stream_data, "1.3.0", "bde37905530aff386dea1ddd86ecbf00e6642dc074ceffc10b7d4e41dfd6aac9", [:mix], [], "hexpm", "3cc552e286e817dca43c98044c706eec9318083a1480c52ae2688b08e2936e3c"},
|
"stream_data": {:hex, :stream_data, "1.4.0", "026f929db613aabea6208012ae9b8970d3fd5f88b3bdf26831bc536f98c42036", [:mix], [], "hexpm", "2b0ee3a340dcce1c8cf6302a763ee757d1e01c54d6e16d9069062509d68b1dc9"},
|
||||||
"styler": {:hex, :styler, "1.11.0", "35010d970689a23c2bcc8e97bd8bf7d20e3561d60c49be84654df5c37d051a9c", [:mix], [], "hexpm", "70f36165d0cf238a32b7a456fdef6a9c72e77e657d7ac4a0ace33aeba3f2b8c0"},
|
"styler": {:hex, :styler, "1.11.0", "35010d970689a23c2bcc8e97bd8bf7d20e3561d60c49be84654df5c37d051a9c", [:mix], [], "hexpm", "70f36165d0cf238a32b7a456fdef6a9c72e77e657d7ac4a0ace33aeba3f2b8c0"},
|
||||||
"swoosh": {:hex, :swoosh, "1.26.3", "9d8b60077305ce259298d9a1102e5be67cd3c41d1ea930c29e9288af195ca017", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, ">= 1.9.0 and < 5.0.0", [hex: :hackney, repo: "hexpm", optional: true]}, {:idna, ">= 6.0.0 and < 8.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c7683d070fe8f8aa9d174e61b01f2d527be73cd8ac40037b7109184941eb569f"},
|
"swoosh": {:hex, :swoosh, "1.26.3", "9d8b60077305ce259298d9a1102e5be67cd3c41d1ea930c29e9288af195ca017", [:mix], [{:bandit, ">= 1.0.0", [hex: :bandit, repo: "hexpm", optional: true]}, {:cowboy, "~> 1.1 or ~> 2.4", [hex: :cowboy, repo: "hexpm", optional: true]}, {:ex_aws, "~> 2.1", [hex: :ex_aws, repo: "hexpm", optional: true]}, {:finch, "~> 0.6", [hex: :finch, repo: "hexpm", optional: true]}, {:gen_smtp, "~> 0.13 or ~> 1.0", [hex: :gen_smtp, repo: "hexpm", optional: true]}, {:hackney, ">= 1.9.0 and < 5.0.0", [hex: :hackney, repo: "hexpm", optional: true]}, {:idna, ">= 6.0.0 and < 8.0.0", [hex: :idna, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}, {:mail, "~> 0.2", [hex: :mail, repo: "hexpm", optional: true]}, {:mime, "~> 1.1 or ~> 2.0", [hex: :mime, repo: "hexpm", optional: false]}, {:mua, "~> 0.2.3", [hex: :mua, repo: "hexpm", optional: true]}, {:multipart, "~> 0.4", [hex: :multipart, repo: "hexpm", optional: true]}, {:plug, "~> 1.9", [hex: :plug, repo: "hexpm", optional: true]}, {:plug_cowboy, ">= 1.0.0", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:req, "~> 0.5.10 or ~> 0.6 or ~> 1.0", [hex: :req, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.2 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "c7683d070fe8f8aa9d174e61b01f2d527be73cd8ac40037b7109184941eb569f"},
|
||||||
"tailwind": {:hex, :tailwind, "0.4.1", "e7bcc222fe96a1e55f948e76d13dd84a1a7653fb051d2a167135db3b4b08d3e9", [:mix], [], "hexpm", "6249d4f9819052911120dbdbe9e532e6bd64ea23476056adb7f730aa25c220d1"},
|
"tailwind": {:hex, :tailwind, "0.5.1", "35435b13158c90d37da11e1cfc808755fca1d7b6c5ab87b1b19c5de87e2f0a10", [:mix], [], "hexpm", "c4e26302a59fec72abc5610ecb6ad2116d9aa31f31aab2d4b8eb6e95d25a689c"},
|
||||||
"telemetry": {:hex, :telemetry, "1.4.2", "a0cb522801dffb1c49fe6e30561badffc7b6d0e180db1300df759faa22062855", [:rebar3], [], "hexpm", "928f6495066506077862c0d1646609eed891a4326bee3126ba54b60af61febb1"},
|
"telemetry": {:hex, :telemetry, "1.4.2", "a0cb522801dffb1c49fe6e30561badffc7b6d0e180db1300df759faa22062855", [:rebar3], [], "hexpm", "928f6495066506077862c0d1646609eed891a4326bee3126ba54b60af61febb1"},
|
||||||
"telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"},
|
"telemetry_metrics": {:hex, :telemetry_metrics, "1.1.0", "5bd5f3b5637e0abea0426b947e3ce5dd304f8b3bc6617039e2b5a008adc02f8f", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "e7b79e8ddfde70adb6db8a6623d1778ec66401f366e9a8f5dd0955c56bc8ce67"},
|
||||||
"telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.2.1", "c9755987d7b959b557084e6990990cb96a50d6482c683fb9622a63837f3cd3d8", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "5e2c599da4983c4f88a33e9571f1458bf98b0cf6ba930f1dc3a6e8cf45d5afb6"},
|
"telemetry_metrics_prometheus_core": {:hex, :telemetry_metrics_prometheus_core, "1.2.1", "c9755987d7b959b557084e6990990cb96a50d6482c683fb9622a63837f3cd3d8", [:mix], [{:telemetry, "~> 0.4 or ~> 1.0", [hex: :telemetry, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.6 or ~> 1.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "5e2c599da4983c4f88a33e9571f1458bf98b0cf6ba930f1dc3a6e8cf45d5afb6"},
|
||||||
|
|
|
||||||
304
nix/shell.nix
Normal file
304
nix/shell.nix
Normal file
|
|
@ -0,0 +1,304 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
stdenv,
|
||||||
|
mkShell,
|
||||||
|
writeShellScriptBin,
|
||||||
|
# Elixir/Erlang
|
||||||
|
elixir,
|
||||||
|
# Databases
|
||||||
|
postgresql_17,
|
||||||
|
# Build tools for NIF deps (bcrypt_elixir via elixir_make)
|
||||||
|
gcc,
|
||||||
|
gnumake,
|
||||||
|
pkg-config,
|
||||||
|
# Development tools
|
||||||
|
inotify-tools,
|
||||||
|
# LSPs and formatters
|
||||||
|
elixir-ls,
|
||||||
|
nixfmt,
|
||||||
|
shellcheck,
|
||||||
|
# Pre-commit hooks
|
||||||
|
pre-commit-hooks,
|
||||||
|
}:
|
||||||
|
|
||||||
|
let
|
||||||
|
# PostgreSQL with PostGIS extension
|
||||||
|
pg = postgresql_17.withPackages (ps: [
|
||||||
|
ps.postgis
|
||||||
|
]);
|
||||||
|
|
||||||
|
# PostgreSQL data directory (local to project)
|
||||||
|
pgDataDir = ".nix-postgres";
|
||||||
|
pgPort = "5432";
|
||||||
|
pgHost = "localhost";
|
||||||
|
|
||||||
|
# Service management flag
|
||||||
|
servicesFlag = ".nix-services-started";
|
||||||
|
|
||||||
|
# Version file to detect when PG config changes (extensions added/removed, version bump)
|
||||||
|
pgVersionFile = ".nix-postgres-version";
|
||||||
|
|
||||||
|
# Script to start PostgreSQL
|
||||||
|
startServices = writeShellScriptBin "start-services" ''
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🚀 Starting development services..."
|
||||||
|
|
||||||
|
# Check if PG version/extensions changed and reinit if needed.
|
||||||
|
# Must run BEFORE the servicesFlag guard so already-running clusters
|
||||||
|
# get reinitialized when extensions or versions change.
|
||||||
|
pg_needs_reinit=false
|
||||||
|
if [ -d "${pgDataDir}" ] && [ -f "${pgVersionFile}" ]; then
|
||||||
|
if [ "$(cat ${pgVersionFile})" != "${pg}" ]; then
|
||||||
|
echo "⚠️ PostgreSQL configuration changed (extensions or version updated)"
|
||||||
|
pg_needs_reinit=true
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ -d "${pgDataDir}" ] && [ ! -f "${pgVersionFile}" ]; then
|
||||||
|
pg_needs_reinit=true
|
||||||
|
fi
|
||||||
|
|
||||||
|
if $pg_needs_reinit; then
|
||||||
|
echo "🗑️ Stopping old PostgreSQL and removing cluster..."
|
||||||
|
${pg}/bin/pg_ctl -D ${pgDataDir} stop -m fast 2>/dev/null || true
|
||||||
|
rm -rf ${pgDataDir}
|
||||||
|
rm -f ${servicesFlag}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if already started (with correct version)
|
||||||
|
if [ -f "${servicesFlag}" ]; then
|
||||||
|
echo "✓ Services already running (remove ${servicesFlag} to force restart)"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Initialize PostgreSQL if needed
|
||||||
|
if [ ! -d "${pgDataDir}" ]; then
|
||||||
|
echo "📦 Initializing PostgreSQL database..."
|
||||||
|
${pg}/bin/initdb -D ${pgDataDir} -U $USER --encoding=UTF8 --locale=en_US.UTF-8
|
||||||
|
|
||||||
|
# Configure PostgreSQL
|
||||||
|
cat >> ${pgDataDir}/postgresql.conf << EOF
|
||||||
|
# Development configuration
|
||||||
|
# max_connections sized for the test pool (schedulers_online * 16)
|
||||||
|
max_connections = 300
|
||||||
|
shared_buffers = 128MB
|
||||||
|
fsync = off # Faster for development (DO NOT use in production)
|
||||||
|
synchronous_commit = off
|
||||||
|
full_page_writes = off
|
||||||
|
EOF
|
||||||
|
|
||||||
|
# Record current PG version for future change detection
|
||||||
|
echo -n "${pg}" > ${pgVersionFile}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Check if PostgreSQL is already running on this port
|
||||||
|
if ${pg}/bin/pg_isready -h ${pgHost} -p ${pgPort} > /dev/null 2>&1; then
|
||||||
|
echo "✓ PostgreSQL already running on port ${pgPort}"
|
||||||
|
else
|
||||||
|
# Start PostgreSQL
|
||||||
|
echo "🐘 Starting PostgreSQL on port ${pgPort}..."
|
||||||
|
${pg}/bin/pg_ctl -D ${pgDataDir} -l ${pgDataDir}/logfile -o "-p ${pgPort}" start
|
||||||
|
|
||||||
|
# Wait for PostgreSQL to be ready
|
||||||
|
for i in {1..30}; do
|
||||||
|
if ${pg}/bin/pg_isready -h ${pgHost} -p ${pgPort} > /dev/null 2>&1; then
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
if [ $i -eq 30 ]; then
|
||||||
|
echo "❌ PostgreSQL failed to start within 30 seconds"
|
||||||
|
echo " Check ${pgDataDir}/logfile for details"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
sleep 1
|
||||||
|
done
|
||||||
|
echo "✓ PostgreSQL started successfully"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Create postgres role if it doesn't exist (dev.exs/test.exs connect as postgres)
|
||||||
|
${pg}/bin/psql -h ${pgHost} -p ${pgPort} -U $USER -d postgres -tc \
|
||||||
|
"SELECT 1 FROM pg_roles WHERE rolname='postgres'" | grep -q 1 || \
|
||||||
|
${pg}/bin/psql -h ${pgHost} -p ${pgPort} -U $USER -d postgres -c \
|
||||||
|
"CREATE ROLE postgres WITH SUPERUSER LOGIN PASSWORD 'postgres';"
|
||||||
|
|
||||||
|
# Create development and test databases
|
||||||
|
for db in aprsme_dev aprsme_test; do
|
||||||
|
${pg}/bin/psql -h ${pgHost} -p ${pgPort} -U $USER -d postgres -tc \
|
||||||
|
"SELECT 1 FROM pg_database WHERE datname='$db'" | grep -q 1 || \
|
||||||
|
${pg}/bin/createdb -h ${pgHost} -p ${pgPort} -U $USER $db
|
||||||
|
done
|
||||||
|
|
||||||
|
# Enable PostGIS extension for dev and test databases
|
||||||
|
for db in aprsme_dev aprsme_test; do
|
||||||
|
${pg}/bin/psql -h ${pgHost} -p ${pgPort} -U $USER -d $db -c \
|
||||||
|
"CREATE EXTENSION IF NOT EXISTS postgis CASCADE;" 2>/dev/null || \
|
||||||
|
echo "⚠️ PostGIS not available for $db (optional)"
|
||||||
|
done
|
||||||
|
|
||||||
|
echo "✓ PostgreSQL started successfully"
|
||||||
|
|
||||||
|
# Mark services as started
|
||||||
|
touch ${servicesFlag}
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "✨ Development environment ready!"
|
||||||
|
echo ""
|
||||||
|
echo "PostgreSQL: ${pgHost}:${pgPort} (databases: aprsme_dev, aprsme_test)"
|
||||||
|
echo ""
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Script to stop PostgreSQL
|
||||||
|
stopServices = writeShellScriptBin "stop-services" ''
|
||||||
|
set -e
|
||||||
|
|
||||||
|
echo "🛑 Stopping development services..."
|
||||||
|
|
||||||
|
# Stop PostgreSQL
|
||||||
|
if [ -d "${pgDataDir}" ]; then
|
||||||
|
${pg}/bin/pg_ctl -D ${pgDataDir} stop -m fast 2>/dev/null || true
|
||||||
|
echo "✓ PostgreSQL stopped"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove services flag
|
||||||
|
rm -f ${servicesFlag}
|
||||||
|
|
||||||
|
echo "✓ Services stopped successfully"
|
||||||
|
'';
|
||||||
|
|
||||||
|
# Pre-commit hooks configuration
|
||||||
|
pre-commit-check = pre-commit-hooks.run {
|
||||||
|
src = ../.;
|
||||||
|
hooks = {
|
||||||
|
# Elixir formatting
|
||||||
|
mix-format = {
|
||||||
|
enable = true;
|
||||||
|
name = "mix format";
|
||||||
|
entry = "mix format --check-formatted";
|
||||||
|
files = "\\.(ex|exs)$";
|
||||||
|
pass_filenames = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Credo linting
|
||||||
|
credo = {
|
||||||
|
enable = true;
|
||||||
|
name = "credo";
|
||||||
|
entry = "mix credo --strict";
|
||||||
|
files = "\\.(ex|exs)$";
|
||||||
|
pass_filenames = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Nix formatting
|
||||||
|
nixfmt = {
|
||||||
|
enable = true;
|
||||||
|
entry = "${nixfmt}/bin/nixfmt";
|
||||||
|
};
|
||||||
|
|
||||||
|
# Shellcheck for shell scripts
|
||||||
|
shellcheck.enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
in
|
||||||
|
mkShell {
|
||||||
|
name = "aprsme-dev";
|
||||||
|
|
||||||
|
# Development tools
|
||||||
|
buildInputs = [
|
||||||
|
# Elixir/Erlang
|
||||||
|
elixir
|
||||||
|
|
||||||
|
# Databases (PostgreSQL with PostGIS)
|
||||||
|
pg
|
||||||
|
|
||||||
|
# NIF build tools (bcrypt_elixir)
|
||||||
|
gcc
|
||||||
|
gnumake
|
||||||
|
pkg-config
|
||||||
|
|
||||||
|
# LSPs and formatters
|
||||||
|
elixir-ls
|
||||||
|
nixfmt
|
||||||
|
shellcheck
|
||||||
|
|
||||||
|
# Service management scripts
|
||||||
|
startServices
|
||||||
|
stopServices
|
||||||
|
]
|
||||||
|
++ lib.optionals stdenv.isLinux [
|
||||||
|
# Linux-only tools
|
||||||
|
inotify-tools # For Mix file watching
|
||||||
|
];
|
||||||
|
|
||||||
|
# Environment variables
|
||||||
|
shellHook = ''
|
||||||
|
# Color codes
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
BLUE='\033[0;34m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
# Set Mix and Hex home to local directories (avoid polluting $HOME)
|
||||||
|
export MIX_HOME="$PWD/.nix-mix"
|
||||||
|
export HEX_HOME="$PWD/.nix-hex"
|
||||||
|
mkdir -p "$MIX_HOME" "$HEX_HOME"
|
||||||
|
|
||||||
|
# PostgreSQL connection (dev.exs/test.exs connect as postgres:postgres)
|
||||||
|
export PGHOST="${pgHost}"
|
||||||
|
export PGPORT="${pgPort}"
|
||||||
|
export PGUSER="$USER"
|
||||||
|
export DATABASE_URL="ecto://postgres:postgres@${pgHost}:${pgPort}/aprsme_dev"
|
||||||
|
|
||||||
|
# Development environment
|
||||||
|
export MIX_ENV=dev
|
||||||
|
export PHX_HOST=localhost
|
||||||
|
export PORT=4000
|
||||||
|
|
||||||
|
# Erlang shell history
|
||||||
|
export ERL_AFLAGS="-kernel shell_history enabled"
|
||||||
|
|
||||||
|
# Skip heavy setup when running inside direnv (DIRENV_DIR is set).
|
||||||
|
# direnv evaluates the shellHook to load env vars only; running mix,
|
||||||
|
# starting services, or installing pre-commit hooks would block the
|
||||||
|
# prompt and cause nix profile cleanup hangs on macOS.
|
||||||
|
if [ -z "$DIRENV_DIR" ]; then
|
||||||
|
# Running in nix develop (interactive shell)
|
||||||
|
|
||||||
|
# Install Hex and Rebar3 if not already installed
|
||||||
|
mix local.hex --force --if-missing > /dev/null 2>&1
|
||||||
|
mix local.rebar --force --if-missing > /dev/null 2>&1
|
||||||
|
|
||||||
|
# Pre-compile test dependencies so mix test works immediately.
|
||||||
|
# The _build/test tree is ephemeral (cleared when nix devShell changes).
|
||||||
|
MIX_ENV=test mix deps.compile 2>/dev/null || true
|
||||||
|
|
||||||
|
# Auto-start services on first shell entry.
|
||||||
|
# Run in a detached subshell to prevent nix develop from waiting
|
||||||
|
# on daemonized PostgreSQL child processes.
|
||||||
|
if [ ! -f "${servicesFlag}" ]; then
|
||||||
|
( ${startServices}/bin/start-services </dev/null & )
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Install pre-commit hooks
|
||||||
|
${pre-commit-check.shellHook}
|
||||||
|
|
||||||
|
# Welcome message
|
||||||
|
echo ""
|
||||||
|
echo -e "''${BLUE}╔═══════════════════════════════════════════════════════════╗''${NC}"
|
||||||
|
echo -e "''${BLUE}║ ║''${NC}"
|
||||||
|
echo -e "''${BLUE}║''${NC} ''${GREEN}aprs.me Development Environment''${NC} ''${BLUE}║''${NC}"
|
||||||
|
echo -e "''${BLUE}║ ║''${NC}"
|
||||||
|
echo -e "''${BLUE}╚═══════════════════════════════════════════════════════════╝''${NC}"
|
||||||
|
echo ""
|
||||||
|
echo -e "''${GREEN}Available commands:''${NC}"
|
||||||
|
echo " mix phx.server - Start Phoenix development server"
|
||||||
|
echo " mix test - Run test suite"
|
||||||
|
echo " mix format - Format Elixir code"
|
||||||
|
echo " mix credo --strict - Run static analysis"
|
||||||
|
echo " start-services - Start PostgreSQL"
|
||||||
|
echo " stop-services - Stop PostgreSQL"
|
||||||
|
echo " mix ecto.reset - Reset database (drop, create, migrate, seed)"
|
||||||
|
echo ""
|
||||||
|
echo -e "''${GREEN}Services:''${NC}"
|
||||||
|
echo " PostgreSQL: ${pgHost}:${pgPort}"
|
||||||
|
echo ""
|
||||||
|
fi
|
||||||
|
'';
|
||||||
|
}
|
||||||
7
shell.nix
Normal file
7
shell.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
# Compatibility shim for developers using `nix-shell` instead of `nix develop`
|
||||||
|
# This file uses flake-compat to provide the development shell from flake.nix
|
||||||
|
|
||||||
|
(import (fetchTarball {
|
||||||
|
url = "https://github.com/edolstra/flake-compat/archive/35bb57c0c8d8b62bbfd284272c928ceb64ddbde9.tar.gz";
|
||||||
|
sha256 = "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=";
|
||||||
|
}) { src = ./.; }).shellNix.default
|
||||||
|
|
@ -881,7 +881,7 @@ defmodule Aprsme.IsTest do
|
||||||
|
|
||||||
capture_log(fn ->
|
capture_log(fn ->
|
||||||
assert {:noreply, same_state} = Aprsme.Is.handle_info(:reconnect, state)
|
assert {:noreply, same_state} = Aprsme.Is.handle_info(:reconnect, state)
|
||||||
refute is_nil(same_state.failure_started_at)
|
assert same_state.failure_started_at
|
||||||
end)
|
end)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue