feat: Upgrade framework
This commit is contained in:
commit
42984b8c29
49 changed files with 27425 additions and 11583 deletions
4
.gitignore
vendored
4
.gitignore
vendored
|
@ -34,8 +34,8 @@ node_modules
|
|||
/priv/static/
|
||||
|
||||
# Mnesia DBs
|
||||
/apps/*/priv/mnesia/
|
||||
/priv/mnesia/
|
||||
/apps/*/priv/mnesia*
|
||||
/priv/mnesia*
|
||||
|
||||
# Lock file for Brew, since the versions aren't really stable & isolated anyway
|
||||
Brewfile.lock.json
|
||||
|
|
|
@ -18,6 +18,7 @@ variables:
|
|||
.test_template: &test_template
|
||||
stage: test
|
||||
cache:
|
||||
key: $CI_JOB_NAME
|
||||
paths:
|
||||
- _build/
|
||||
- deps/
|
||||
|
@ -42,10 +43,6 @@ build_image_for_commit:
|
|||
image: "docker:20.10"
|
||||
only:
|
||||
- master
|
||||
cache:
|
||||
paths:
|
||||
- _build/
|
||||
- deps/
|
||||
services:
|
||||
- name: docker:20.10-dind
|
||||
before_script:
|
||||
|
@ -58,13 +55,14 @@ build_image_for_commit:
|
|||
deploy_to_tags:
|
||||
stage: deploy_tags
|
||||
needs: ['test', 'build_image_for_commit']
|
||||
image: "node:15.0"
|
||||
image: "node:16"
|
||||
only:
|
||||
- master
|
||||
cache:
|
||||
key:
|
||||
files:
|
||||
- package-lock.json
|
||||
- package.json
|
||||
paths:
|
||||
- node_modules/
|
||||
script:
|
||||
|
@ -72,7 +70,10 @@ deploy_to_tags:
|
|||
- export GIT_AUTHOR_EMAIL=$GITLAB_USER_EMAIL
|
||||
- export GIT_COMMITTER_NAME=$GITLAB_USER_NAME
|
||||
- export GIT_COMMITTER_EMAIL=$GITLAB_USER_EMAIL
|
||||
- npm install
|
||||
- export GIT_BRANCH=$CI_COMMIT_REF_NAME
|
||||
- git config user.email $GITLAB_USER_EMAIL
|
||||
- git config user.name $GITLAB_USER_NAME
|
||||
- npm install --no-save
|
||||
- npx semantic-release --repository-url=$CI_REPOSITORY_URL
|
||||
- script/generate-build-version
|
||||
artifacts:
|
||||
|
@ -107,3 +108,83 @@ deploy_commit_image_to_tag:
|
|||
- docker tag $CI_REGISTRY_IMAGE:$CI_COMMIT_SHA$IMAGE_TYPE $CI_REGISTRY_IMAGE:latest$IMAGE_TYPE
|
||||
- docker push $CI_REGISTRY_IMAGE:$BUILD_VERSION$IMAGE_TYPE
|
||||
- docker push $CI_REGISTRY_IMAGE:latest$IMAGE_TYPE
|
||||
|
||||
.dependabot_gitlab: &dependabot_gitlab
|
||||
image:
|
||||
name: docker.io/andrcuns/dependabot-gitlab:0.4.3
|
||||
entrypoint: [""]
|
||||
variables:
|
||||
GIT_STRATEGY: none
|
||||
RAILS_ENV: production
|
||||
SETTINGS__STANDALONE: "true"
|
||||
SETTINGS__GITLAB_URL: $CI_SERVER_URL
|
||||
SETTINGS__GITLAB_ACCESS_TOKEN: $GITLAB_TOKEN
|
||||
before_script:
|
||||
- cd /home/dependabot/app
|
||||
script:
|
||||
- bundle exec rake "dependabot:update[$CI_PROJECT_PATH,$PACKAGE_MANAGER,$DIRECTORY]"
|
||||
only:
|
||||
- schedules
|
||||
|
||||
npm-release-tools:
|
||||
extends: .dependabot_gitlab
|
||||
variables:
|
||||
DIRECTORY: "/"
|
||||
PACKAGE_MANAGER: npm
|
||||
only:
|
||||
variables:
|
||||
- $PACKAGE_MANAGER_SET =~ /(\bnpm|yarn\b)/
|
||||
|
||||
npm-assets:
|
||||
extends: .dependabot_gitlab
|
||||
variables:
|
||||
DIRECTORY: "/apps/app/assets"
|
||||
PACKAGE_MANAGER: npm
|
||||
only:
|
||||
variables:
|
||||
- $PACKAGE_MANAGER_SET =~ /(\bnpm|yarn\b)/
|
||||
|
||||
mix-admin:
|
||||
extends: .dependabot_gitlab
|
||||
variables:
|
||||
DIRECTORY: "/apps/admin"
|
||||
PACKAGE_MANAGER: mix
|
||||
only:
|
||||
variables:
|
||||
- $PACKAGE_MANAGER_SET =~ /\bmix\b/
|
||||
|
||||
mix-app:
|
||||
extends: .dependabot_gitlab
|
||||
variables:
|
||||
DIRECTORY: "/apps/app"
|
||||
PACKAGE_MANAGER: mix
|
||||
only:
|
||||
variables:
|
||||
- $PACKAGE_MANAGER_SET =~ /\bmix\b/
|
||||
|
||||
mix-core:
|
||||
extends: .dependabot_gitlab
|
||||
variables:
|
||||
DIRECTORY: "/apps/core"
|
||||
PACKAGE_MANAGER: mix
|
||||
only:
|
||||
variables:
|
||||
- $PACKAGE_MANAGER_SET =~ /\bmix\b/
|
||||
|
||||
mix-content:
|
||||
extends: .dependabot_gitlab
|
||||
variables:
|
||||
DIRECTORY: "/apps/content"
|
||||
PACKAGE_MANAGER: mix
|
||||
only:
|
||||
variables:
|
||||
- $PACKAGE_MANAGER_SET =~ /\bmix\b/
|
||||
|
||||
docker:
|
||||
extends: .dependabot_gitlab
|
||||
variables:
|
||||
DIRECTORY: "/"
|
||||
PACKAGE_MANAGER: docker
|
||||
only:
|
||||
variables:
|
||||
- $PACKAGE_MANAGER_SET =~ /\bdocker\b/
|
||||
|
|
30
.gitlab/dependabot.yml
Normal file
30
.gitlab/dependabot.yml
Normal file
|
@ -0,0 +1,30 @@
|
|||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: docker
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: mix
|
||||
directory: "/apps/admin"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: mix
|
||||
directory: "/apps/app"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: mix
|
||||
directory: "/apps/content"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: mix
|
||||
directory: "/apps/core"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: npm
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
- package-ecosystem: npm
|
||||
directory: "/apps/app/assets"
|
||||
schedule:
|
||||
interval: "daily"
|
|
@ -1,3 +1,3 @@
|
|||
erlang 23.0.2
|
||||
elixir 1.10.3-otp-23
|
||||
elixir 1.12.1
|
||||
nodejs 14.5.0
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
FROM elixir:1.10.4-alpine AS elixir-builder
|
||||
FROM elixir:1.12.1-alpine AS elixir-builder
|
||||
|
||||
RUN mix local.hex --force \
|
||||
&& mix local.rebar --force
|
||||
|
@ -27,7 +27,7 @@ RUN mix deps.get
|
|||
|
||||
# Leave off here so that we can built assets and compile the elixir app in parallel
|
||||
|
||||
FROM node:15.0 AS asset-builder
|
||||
FROM node:16.3.0 AS asset-builder
|
||||
|
||||
# Build assets in a node container
|
||||
ADD ./apps/app/assets/ /root/app/apps/app/assets/
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
defmodule Legendary.Admin.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
@version "2.10.0"
|
||||
@version "2.11.2"
|
||||
|
||||
def project do
|
||||
[
|
||||
|
@ -50,7 +50,7 @@ defmodule Legendary.Admin.MixProject do
|
|||
{:phoenix_ecto, "~> 4.0"},
|
||||
{:phoenix_html, "~> 2.11"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
{:phoenix_live_dashboard, "~> 0.2.0"},
|
||||
{:phoenix_live_dashboard, "~> 0.4.0"},
|
||||
{:postgrex, ">= 0.0.0"},
|
||||
{:telemetry_metrics, "~> 0.4"},
|
||||
{:telemetry_poller, "~> 0.4"},
|
||||
|
|
|
@ -14,6 +14,7 @@ import "../css/app.css"
|
|||
//
|
||||
import "phoenix_html"
|
||||
import "alpinejs"
|
||||
import "./live"
|
||||
import { ready } from "./utils"
|
||||
|
||||
function togglePasswordFieldVisibility()
|
||||
|
@ -38,7 +39,7 @@ const toggleSidebar = (event) => {
|
|||
}
|
||||
|
||||
ready(() => {
|
||||
document.getElementById('nav-toggle').onclick = function(){
|
||||
(document.getElementById('nav-toggle') ||{}).onclick = function(){
|
||||
document.getElementById("nav-content").classList.toggle("hidden");
|
||||
}
|
||||
|
||||
|
|
23
apps/app/assets/js/live.js
Normal file
23
apps/app/assets/js/live.js
Normal file
|
@ -0,0 +1,23 @@
|
|||
import {Socket} from "phoenix"
|
||||
import LiveSocket from "phoenix_live_view"
|
||||
import topbar from "topbar"
|
||||
|
||||
let csrfToken = document.querySelector("meta[name='csrf-token']").getAttribute("content")
|
||||
|
||||
let liveSocket = new LiveSocket("/live", Socket, {params: {_csrf_token: csrfToken}})
|
||||
|
||||
// Show progress bar on live navigation and form submits
|
||||
topbar.config({barColors: {0: "#3B82F6"}, shadowColor: "rgba(0, 0, 0, .3)"})
|
||||
window.addEventListener("phx:page-loading-start", info => topbar.show())
|
||||
window.addEventListener("phx:page-loading-stop", info => topbar.hide())
|
||||
|
||||
// Connect if there are any LiveViews on the page
|
||||
liveSocket.connect()
|
||||
|
||||
// Expose liveSocket on window for web console debug logs and latency simulation:
|
||||
// >> liveSocket.enableDebug()
|
||||
// >> liveSocket.enableLatencySim(1000)
|
||||
// The latency simulator is enabled for the duration of the browser session.
|
||||
// Call disableLatencySim() to disable:
|
||||
// >> liveSocket.disableLatencySim()
|
||||
window.liveSocket = liveSocket
|
23988
apps/app/assets/package-lock.json
generated
23988
apps/app/assets/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -13,38 +13,38 @@
|
|||
"autoprefixer": "^9.8.6",
|
||||
"csswring": "^7.0.0",
|
||||
"glob": "^7.1.6",
|
||||
"gulp": "^4.0.2",
|
||||
"phoenix": "file:/../../../deps/phoenix",
|
||||
"phoenix_html": "file:/../../../deps/phoenix_html",
|
||||
"phoenix_live_view": "file:../../../deps/phoenix_live_view",
|
||||
"postcss-color-function": "^4.1.0",
|
||||
"simplemde": "^1.11.2",
|
||||
"stylelint": "^13.6.1",
|
||||
"tailwindcss": "^1.7.3"
|
||||
"tailwindcss": "^1.7.3",
|
||||
"topbar": "^1.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.0.0",
|
||||
"@babel/preset-env": "^7.0.0",
|
||||
"babel-loader": "^8.0.0",
|
||||
"copy-webpack-plugin": "^5.1.1",
|
||||
"copy-webpack-plugin": "^9.0.1",
|
||||
"css-loader": "^3.4.2",
|
||||
"extract-text-webpack-plugin": "^3.0.2",
|
||||
"css-minimizer-webpack-plugin": "^3.0.2",
|
||||
"file-loader": "^6.0.0",
|
||||
"image-webpack-loader": "^6.0.0",
|
||||
"less": "^3.11.3",
|
||||
"less-loader": "^6.2.0",
|
||||
"mini-css-extract-plugin": "^0.9.0",
|
||||
"node-sass": "^4.13.1",
|
||||
"optimize-css-assets-webpack-plugin": "^5.0.1",
|
||||
"mini-css-extract-plugin": "^1.6.2",
|
||||
"postcss-css-variables": "^0.17.0",
|
||||
"postcss-import": "^12.0.1",
|
||||
"postcss-loader": "^3.0.0",
|
||||
"postcss-loader": "^6.1.0",
|
||||
"sass": "^1.35.1",
|
||||
"sass-loader": "^8.0.2",
|
||||
"style-loader": "^1.2.1",
|
||||
"stylelint-config-standard": "^20.0.0",
|
||||
"stylelint": "^13.13.1",
|
||||
"stylelint-config-standard": "^22.0.0",
|
||||
"stylelint-order": "^4.1.0",
|
||||
"terser-webpack-plugin": "^2.3.2",
|
||||
"webpack": "4.41.5",
|
||||
"webpack-cli": "^3.3.2"
|
||||
"webpack": "^5.1.0",
|
||||
"webpack-cli": "^4.7.2"
|
||||
},
|
||||
"resolutions": {
|
||||
"graceful-fs": "4.2.3"
|
||||
|
|
|
@ -1,8 +1,19 @@
|
|||
module.exports = {
|
||||
future: {
|
||||
removeDeprecatedGapUtilities: true,
|
||||
purgeLayersByDefault: true,
|
||||
},
|
||||
purge: {
|
||||
enabled: true,
|
||||
layers: ['base', 'components', 'utilities'],
|
||||
content: [
|
||||
'../../../**/views/*.ex',
|
||||
'../../../**/*.html.eex',
|
||||
'../../../**/*.html.leex',
|
||||
'../../../**/*.html.heex',
|
||||
'./js/**/*.js'
|
||||
]
|
||||
},
|
||||
purge: [],
|
||||
theme: {
|
||||
extend: {},
|
||||
},
|
||||
|
|
|
@ -2,7 +2,7 @@ const path = require('path');
|
|||
const glob = require('glob');
|
||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
||||
const TerserPlugin = require('terser-webpack-plugin');
|
||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
||||
const CssMinimizerPlugin = require('css-minimizer-webpack-plugin');
|
||||
const CopyWebpackPlugin = require('copy-webpack-plugin');
|
||||
|
||||
const nodeModulesPath = path.resolve(__dirname, 'node_modules')
|
||||
|
@ -14,7 +14,7 @@ module.exports = (env, options) => {
|
|||
optimization: {
|
||||
minimizer: [
|
||||
new TerserPlugin({ cache: true, parallel: true, sourceMap: devMode }),
|
||||
new OptimizeCSSAssetsPlugin({})
|
||||
new CssMinimizerPlugin(),
|
||||
]
|
||||
},
|
||||
mode: options.mode,
|
||||
|
@ -63,7 +63,7 @@ module.exports = (env, options) => {
|
|||
{
|
||||
test: /\.css$/,
|
||||
use: [
|
||||
{loader: MiniCssExtractPlugin.loader, options: {sourceMap: true}},
|
||||
{loader: MiniCssExtractPlugin.loader},
|
||||
{loader: 'css-loader', options: {sourceMap: true}},
|
||||
{loader: 'postcss-loader', options: {sourceMap: true}},
|
||||
],
|
||||
|
@ -75,12 +75,12 @@ module.exports = (env, options) => {
|
|||
filename: 'css/[name].css',
|
||||
chunkFilename: '[id].css',
|
||||
}),
|
||||
new CopyWebpackPlugin([
|
||||
new CopyWebpackPlugin({patterns: [
|
||||
{
|
||||
from: path.resolve(__dirname, 'static'),
|
||||
to: path.resolve(__dirname, '../priv/static'),
|
||||
},
|
||||
]),
|
||||
]}),
|
||||
],
|
||||
resolve: {
|
||||
alias: {
|
||||
|
|
|
@ -27,6 +27,27 @@ defmodule AppWeb do
|
|||
end
|
||||
end
|
||||
|
||||
def live_view do
|
||||
quote do
|
||||
use Phoenix.LiveView,
|
||||
layout: {AppWeb.LayoutView, "live.html"}
|
||||
|
||||
import AppWeb.LiveHelpers
|
||||
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
def live_component do
|
||||
quote do
|
||||
use Phoenix.LiveComponent
|
||||
|
||||
import AppWeb.LiveHelpers
|
||||
|
||||
unquote(view_helpers())
|
||||
end
|
||||
end
|
||||
|
||||
def view do
|
||||
quote do
|
||||
use Phoenix.View,
|
||||
|
@ -48,6 +69,7 @@ defmodule AppWeb do
|
|||
|
||||
import Plug.Conn
|
||||
import Phoenix.Controller
|
||||
import Phoenix.LiveView.Router
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -66,9 +88,10 @@ defmodule AppWeb do
|
|||
# Import basic rendering functionality (render, render_layout, etc)
|
||||
import Phoenix.View
|
||||
|
||||
import Legendary.CoreWeb.Helpers
|
||||
import AppWeb.ErrorHelpers
|
||||
import AppWeb.Gettext
|
||||
import Legendary.CoreWeb.Helpers
|
||||
import Phoenix.LiveView.Helpers
|
||||
alias AppWeb.Router.Helpers, as: Routes
|
||||
end
|
||||
end
|
||||
|
|
0
apps/app/lib/app_web/live/.keep
Normal file
0
apps/app/lib/app_web/live/.keep
Normal file
41
apps/app/lib/app_web/live_helpers.ex
Normal file
41
apps/app/lib/app_web/live_helpers.ex
Normal file
|
@ -0,0 +1,41 @@
|
|||
defmodule AppWeb.LiveHelpers do
|
||||
@moduledoc """
|
||||
Commonly functions for LiveViews.
|
||||
"""
|
||||
import Phoenix.LiveView
|
||||
|
||||
alias Legendary.Auth.User
|
||||
alias Pow.Store.CredentialsCache
|
||||
alias AppWeb.Pow.Routes
|
||||
|
||||
def assign_defaults(socket, session) do
|
||||
assign_new(socket, :current_user, fn -> get_user(socket, session) end)
|
||||
end
|
||||
|
||||
def require_auth(socket) do
|
||||
if socket.assigns.current_user do
|
||||
socket
|
||||
else
|
||||
redirect(socket, to: Routes.after_sign_out_path(%Plug.Conn{}))
|
||||
end
|
||||
end
|
||||
|
||||
defp get_user(socket, session, config \\ [otp_app: :core])
|
||||
|
||||
defp get_user(socket, %{"core_auth" => signed_token}, config) do
|
||||
{otp_app, _config} = Keyword.pop(config, :otp_app, :core)
|
||||
{store, store_config} = Pow.Plug.Base.store(Application.get_env(otp_app, :pow))
|
||||
|
||||
conn = struct!(Plug.Conn, secret_key_base: socket.endpoint.config(:secret_key_base))
|
||||
salt = Atom.to_string(Pow.Plug.Session)
|
||||
|
||||
with {:ok, token} <- Pow.Plug.verify_token(conn, salt, signed_token, config),
|
||||
{user, _metadata} <- store.get(store_config, token) do
|
||||
user
|
||||
else
|
||||
_any -> nil
|
||||
end
|
||||
end
|
||||
|
||||
defp get_user(_, _, _), do: nil
|
||||
end
|
|
@ -9,10 +9,11 @@ defmodule AppWeb.Router do
|
|||
pipeline :browser do
|
||||
plug :accepts, ["html"]
|
||||
plug :fetch_session
|
||||
plug :fetch_flash
|
||||
plug :fetch_live_flash
|
||||
plug :protect_from_forgery
|
||||
plug :put_secure_browser_headers
|
||||
plug :put_layout, {AppWeb.LayoutView, :app}
|
||||
plug :put_root_layout, {AppWeb.LayoutView, :root}
|
||||
end
|
||||
|
||||
pipeline :api do
|
||||
|
@ -57,6 +58,7 @@ defmodule AppWeb.Router do
|
|||
pow_extension_routes()
|
||||
end
|
||||
|
||||
use Legendary.Core.Routes
|
||||
use Legendary.Admin.Routes
|
||||
use Legendary.Content.Routes
|
||||
end
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
<div class="fixed w-full px-4 z-50 mt-20">
|
||||
<%= [info: "green", error: "red"] |> Enum.map(fn {level, color} -> %>
|
||||
<%= if live_flash(@flash, level) do %>
|
||||
<div
|
||||
class="relative bg-<%= color %>-100 lg:w-1/2 w-full p-5 object-right rounded shadow-xl m-auto mb-5 js-flash"
|
||||
phx-click="lv:clear-flash"
|
||||
phx-value-key="<%= level %>"
|
||||
>
|
||||
<div class="flex justify-between text-<%= color %>-700">
|
||||
<div class="flex space-x-3">
|
||||
<div class="flex-1 leading-tight text-sm font-medium">
|
||||
<%= live_flash(@flash, level) %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex-none">
|
||||
×
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
<% end) %>
|
||||
</div>
|
|
@ -1,3 +1,5 @@
|
|||
<% conn_or_socket = if assigns[:conn], do: assigns[:conn], else: @socket %>
|
||||
|
||||
<nav class="flex items-center justify-between flex-wrap bg-grey-dark p-6 w-full z-10 bg-gray-800">
|
||||
<div class="flex items-center flex-no-shrink text-white mr-6">
|
||||
<a class="text-white no-underline hover:text-white hover:no-underline" href="/">
|
||||
|
@ -35,14 +37,14 @@
|
|||
class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4"
|
||||
%>
|
||||
</li>
|
||||
<%= if has_role?(@conn, :admin) do %>
|
||||
<%= if has_role?(conn_or_socket, :admin) do %>
|
||||
<li class="mr-3">
|
||||
<a class="inline-block py-2 px-4 text-white no-underline" href="/admin">Admin</a>
|
||||
</li>
|
||||
<% end %>
|
||||
<%= if Pow.Plug.current_user(@conn) do %>
|
||||
<%= if current_user(conn_or_socket) do %>
|
||||
<li class="mr-3">
|
||||
<%= link "Sign Out", to: Routes.pow_session_path(@conn, :delete), method: :delete, class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" %>
|
||||
<%= link "Sign Out", to: Routes.pow_session_path(conn_or_socket, :delete), method: :delete, class: "inline-block text-white no-underline hover:text-white hover:text-underline py-2 px-4" %>
|
||||
</li>
|
||||
<% else %>
|
||||
<% end %>
|
||||
|
|
|
@ -1,24 +1,5 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title><%= title(@view_module, @view_template, assigns) %></title>
|
||||
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<%= feed_tag(@conn, @view_module, @view_template, assigns) %>
|
||||
<script defer type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
</head>
|
||||
<body class="text-gray-800 antialiased">
|
||||
<main role="main">
|
||||
<!-- Page Contents -->
|
||||
<div class="bg-gray-100 min-h-screen">
|
||||
<%= render "_menu.html", assigns %>
|
||||
<%= render "_menu.html", assigns %>
|
||||
|
||||
<%= flash_block(@conn) %>
|
||||
<%= flash_block(@conn) %>
|
||||
|
||||
<%= @inner_content %>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
<%= @inner_content %>
|
||||
|
|
6
apps/app/lib/app_web/templates/layout/live.html.leex
Normal file
6
apps/app/lib/app_web/templates/layout/live.html.leex
Normal file
|
@ -0,0 +1,6 @@
|
|||
|
||||
<%= render "_menu.html", assigns %>
|
||||
|
||||
<%= render "_live_flash_block.html", flash: @flash %>
|
||||
|
||||
<%= @inner_content %>
|
20
apps/app/lib/app_web/templates/layout/root.html.leex
Normal file
20
apps/app/lib/app_web/templates/layout/root.html.leex
Normal file
|
@ -0,0 +1,20 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<%= csrf_meta_tag() %>
|
||||
<%= live_title_tag title(@view_module, @view_template, assigns) %>
|
||||
<link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<script defer phx-track-static type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
</head>
|
||||
<body class="text-gray-800 antialiased">
|
||||
<main role="main">
|
||||
<!-- Page Contents -->
|
||||
<div class="bg-gray-100 min-h-screen">
|
||||
<%= @inner_content %>
|
||||
</div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
|
@ -44,12 +44,14 @@ defmodule App.MixProject do
|
|||
{:core, in_umbrella: true},
|
||||
{:ecto_sql, "~> 3.4"},
|
||||
{:excoveralls, "~> 0.10", only: [:dev, :test]},
|
||||
{:floki, ">= 0.30.0"},
|
||||
{:oban, "~> 2.1"},
|
||||
{:phoenix, "~> 1.5.8"},
|
||||
{:phoenix_ecto, "~> 4.0"},
|
||||
{:phoenix_html, "~> 2.11"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
{:phoenix_live_dashboard, "~> 0.2.0"},
|
||||
{:phoenix_live_dashboard, "~> 0.4.0"},
|
||||
{:phoenix_live_view, "~> 0.15.7", override: true},
|
||||
{:postgrex, ">= 0.0.0"},
|
||||
{:telemetry_metrics, "~> 0.4"},
|
||||
{:telemetry_poller, "~> 0.4"},
|
||||
|
|
|
@ -42,7 +42,7 @@ defmodule Legendary.Content do
|
|||
|
||||
def process_content(text) do
|
||||
text
|
||||
|> Earmark.as_html!(encode: false)
|
||||
|> Earmark.as_html!()
|
||||
end
|
||||
|
||||
# Include shared imports and aliases for views
|
||||
|
|
|
@ -3,8 +3,6 @@ defmodule Legendary.Content.FeedsController do
|
|||
|
||||
alias Legendary.Content.{Posts}
|
||||
|
||||
plug :put_layout, false when action in [:preview]
|
||||
|
||||
def index(conn, params) do
|
||||
category = params |> Map.get("category")
|
||||
posts = Posts.list_posts(params)
|
||||
|
|
|
@ -5,9 +5,9 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
|
||||
<title><%= title(@view_module, @view_template, assigns) %></title>
|
||||
<link rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<link phx-track-static rel="stylesheet" href="<%= Routes.static_path(@conn, "/css/app.css") %>"/>
|
||||
<%= feed_tag(@conn, @view_module, @view_template, assigns) %>
|
||||
<script defer type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
<script phx-track-static defer type="text/javascript" src="<%= Routes.static_path(@conn, "/js/app.js") %>"></script>
|
||||
</head>
|
||||
<body class="text-gray-800 antialiased">
|
||||
<main role="main">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
defmodule Legendary.Content.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
@version "2.10.0"
|
||||
@version "2.11.2"
|
||||
|
||||
def project do
|
||||
[
|
||||
|
@ -42,9 +42,9 @@ defmodule Legendary.Content.MixProject do
|
|||
defp deps do
|
||||
[
|
||||
{:core, in_umbrella: true},
|
||||
{:earmark, "1.4.3"},
|
||||
{:earmark, "1.4.15"},
|
||||
{:excoveralls, "~> 0.10", only: [:dev, :test]},
|
||||
{:floki, "~> 0.25.0"},
|
||||
{:floki, ">= 0.30.0"},
|
||||
{:gettext, "~> 0.11"},
|
||||
{:jason, "~> 1.0"},
|
||||
{:mock, "~> 0.3.0", only: :test},
|
||||
|
@ -54,10 +54,10 @@ defmodule Legendary.Content.MixProject do
|
|||
{:phoenix, "~> 1.5.8"},
|
||||
{:phoenix_ecto, "~> 4.0"},
|
||||
{:phoenix_html, "~> 2.11"},
|
||||
{:phoenix_html_sanitizer, "~> 1.0.0"},
|
||||
{:phoenix_html_sanitizer, "~> 1.1.0"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
{:phoenix_live_dashboard, "~> 0.2.0"},
|
||||
{:php_serializer, "~> 0.9.0"},
|
||||
{:phoenix_live_dashboard, "~> 0.4.0"},
|
||||
{:php_serializer, "~> 2.0.0"},
|
||||
{:plug_cowboy, "~> 2.0"},
|
||||
{:sitemap, "~> 1.1"},
|
||||
{:slugger, "~> 0.3"},
|
||||
|
|
32
apps/core/guides/features/feature-flags.md
Normal file
32
apps/core/guides/features/feature-flags.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
# Feature Flags
|
||||
|
||||
Legendary comes with [Fun with Flags](https://github.com/tompave/fun_with_flags)
|
||||
preconfigured for managing [feature flags](https://en.wikipedia.org/wiki/Feature_toggle).
|
||||
This allows you to have more granular control over which users see which features
|
||||
and when. For example, you can hide a feature which is not complete, or show it
|
||||
to only a select group of testers.
|
||||
|
||||
|
||||
Fun With Flags supports a variety of different feature gate types. From
|
||||
the Fun With Flags docs:
|
||||
|
||||
* **Boolean**: globally on and off.
|
||||
* **Actors**: on or off for specific structs or data. The `FunWithFlags.Actor` protocol can be implemented for types and structs that should have specific rules. For example, in web applications it's common to use a `%User{}` struct or equivalent as an actor, or perhaps the current country of the request.
|
||||
* **Groups**: on or off for structs or data that belong to a category or satisfy a condition. The `FunWithFlags.Group` protocol can be implemented for types and structs that belong to groups for which a feature flag can be enabled or disabled. For example, one could implement the protocol for a `%User{}` struct to identify administrators.
|
||||
* **%-of-Time**: globally on for a percentage of the time. It ignores actors and groups. Mutually exclusive with the %-of-actors gate.
|
||||
* **%-of-Actors**: globally on for a percentage of the actors. It only applies when the flag is checked with a specific actor and is ignored when the flag is checked without actor arguments. Mutually exclusive with the %-of-time gate.
|
||||
|
||||
Since feature flags may be checked often (sometimes multiple times per request),
|
||||
Fun With Flags uses a two-layer approach. Flags are cached in [ETS](https://erlang.org/doc/man/ets.html)
|
||||
and also persisted to longer-term storage so that they are not lost when the app
|
||||
restarts.
|
||||
|
||||
By default, Legendary caches the flags for five minutes. We use Ecto for
|
||||
persistence. We also use Phoenix PubSub to inform application nodes when a flag
|
||||
has been updated. This configuration is a sensible default that we would not
|
||||
expect you to need to change in most cases.
|
||||
|
||||
## UI
|
||||
|
||||
We integrate the Fun With Flags UI for managing flags. You can reach it through
|
||||
a link in the admin.
|
|
@ -3,6 +3,12 @@ defmodule Legendary.Auth.UserAdmin do
|
|||
alias Legendary.Auth.User
|
||||
alias Legendary.Core.Repo
|
||||
|
||||
def custom_links(_schema) do
|
||||
[
|
||||
%{name: "Feature Flags", url: "/admin/feature-flags", order: 2, location: :top, icon: "flag"},
|
||||
]
|
||||
end
|
||||
|
||||
def create_changeset(schema, attrs) do
|
||||
Legendary.Auth.User.admin_changeset(schema, attrs)
|
||||
end
|
||||
|
|
45
apps/core/lib/auth_web/controller_callbacks.ex
Normal file
45
apps/core/lib/auth_web/controller_callbacks.ex
Normal file
|
@ -0,0 +1,45 @@
|
|||
defmodule AuthWeb.Pow.ControllerCallbacks do
|
||||
@moduledoc """
|
||||
Hook into Pow Controllers to provide additional framework feature. In particular,
|
||||
we disconnect any active live views when a user logs out. This will cause the
|
||||
live view to re-connect with the new session environment.
|
||||
"""
|
||||
alias Pow.Extension.Phoenix.ControllerCallbacks
|
||||
alias Plug.Conn
|
||||
|
||||
def before_respond(Pow.Phoenix.SessionController, :create, {:ok, conn}, config) do
|
||||
user = conn.assigns.current_user
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> Conn.put_session(:current_user_id, user.id)
|
||||
|> Conn.put_session(:live_socket_id, "users_sockets:#{user.id}")
|
||||
|
||||
ControllerCallbacks.before_respond(
|
||||
Pow.Phoenix.SessionController,
|
||||
:create,
|
||||
{:ok, conn},
|
||||
config
|
||||
)
|
||||
end
|
||||
|
||||
def before_respond(Pow.Phoenix.SessionController, :delete, {:ok, conn}, config) do
|
||||
live_socket_id = Conn.get_session(conn, :live_socket_id)
|
||||
AppWeb.Endpoint.broadcast(live_socket_id, "disconnect", %{})
|
||||
|
||||
conn =
|
||||
conn
|
||||
|> Conn.delete_session(:live_socket_id)
|
||||
|
||||
ControllerCallbacks.before_respond(
|
||||
Pow.Phoenix.SessionController,
|
||||
:delete,
|
||||
{:ok, conn},
|
||||
config
|
||||
)
|
||||
end
|
||||
|
||||
defdelegate before_respond(controller, action, results, config), to: ControllerCallbacks
|
||||
|
||||
defdelegate before_process(controller, action, results, config), to: ControllerCallbacks
|
||||
end
|
|
@ -1,7 +1,12 @@
|
|||
defmodule Legendary.AuthWeb.Helpers do
|
||||
def has_role?(conn = %Plug.Conn{}, role) do
|
||||
conn
|
||||
|> Pow.Plug.current_user()
|
||||
def current_user(socket = %Phoenix.LiveView.Socket{assigns: %{current_user: user}}), do: user
|
||||
def current_user(socket = %Phoenix.LiveView.Socket{assigns: %{__assigns__: %{current_user: user}}}), do: user
|
||||
def current_user(%Phoenix.LiveView.Socket{}), do: nil
|
||||
def current_user(conn), do: Pow.Plug.current_user(conn)
|
||||
|
||||
def has_role?(conn_or_socket, role) do
|
||||
conn_or_socket
|
||||
|> current_user()
|
||||
|> Legendary.Auth.Roles.has_role?(role)
|
||||
end
|
||||
end
|
||||
|
|
11
apps/core/lib/core_web/routes.ex
Normal file
11
apps/core/lib/core_web/routes.ex
Normal file
|
@ -0,0 +1,11 @@
|
|||
defmodule Legendary.Core.Routes do
|
||||
defmacro __using__(_opts \\ []) do
|
||||
quote do
|
||||
scope path: "/admin/feature-flags" do
|
||||
pipe_through :require_admin
|
||||
|
||||
forward "/", FunWithFlags.UI.Router, namespace: "admin/feature-flags"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,11 +7,8 @@ defmodule Legendary.CoreWeb.Helpers do
|
|||
import Phoenix.Controller, only: [get_flash: 2]
|
||||
import Legendary.CoreWeb.ErrorHelpers
|
||||
|
||||
def has_role?(conn = %Plug.Conn{}, role) do
|
||||
conn
|
||||
|> Pow.Plug.current_user()
|
||||
|> Legendary.Auth.Roles.has_role?(role)
|
||||
end
|
||||
defdelegate current_user(a), to: Legendary.AuthWeb.Helpers
|
||||
defdelegate has_role?(a, b), to: Legendary.AuthWeb.Helpers
|
||||
|
||||
def changeset_error_block(changeset) do
|
||||
~E"""
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
defmodule Legendary.Core.MixProject do
|
||||
use Mix.Project
|
||||
|
||||
@version "2.10.0"
|
||||
@version "2.11.2"
|
||||
|
||||
def project do
|
||||
[
|
||||
|
@ -58,6 +58,7 @@ defmodule Legendary.Core.MixProject do
|
|||
"guides/features/content-management.md",
|
||||
"guides/features/devops-templates.md",
|
||||
"guides/features/email.md",
|
||||
"guides/features/feature-flags.md",
|
||||
"guides/features/i18n.md",
|
||||
"guides/features/tasks-and-scripts.md",
|
||||
]
|
||||
|
@ -139,15 +140,17 @@ defmodule Legendary.Core.MixProject do
|
|||
{:ex_cldr, "~> 2.13.0"},
|
||||
{:ex_doc, "~> 0.24", only: :dev, runtime: false},
|
||||
{:excoveralls, "~> 0.10", only: [:dev, :test]},
|
||||
{:fun_with_flags, "~> 1.6.0"},
|
||||
{:fun_with_flags_ui, "~> 0.7.2"},
|
||||
{:phoenix, "~> 1.5.8"},
|
||||
{:phoenix_ecto, "~> 4.1"},
|
||||
{:ecto_sql, "~> 3.4"},
|
||||
{:ex_prompt, "~> 0.1.5"},
|
||||
{:ex_prompt, "~> 0.2.0"},
|
||||
{:linguist, "0.3.1"},
|
||||
{:postgrex, ">= 0.0.0"},
|
||||
{:phoenix_html, "~> 2.11"},
|
||||
{:phoenix_live_reload, "~> 1.2", only: :dev},
|
||||
{:phoenix_live_dashboard, "~> 0.2.0"},
|
||||
{:phoenix_live_dashboard, "~> 0.4.0"},
|
||||
{:phoenix_pubsub, "~> 2.0"},
|
||||
{:pow, "~> 1.0.20"},
|
||||
{:telemetry_metrics, "~> 0.4"},
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
defmodule Legendary.Core.Repo.Migrations.AddFeatureFlagTable do
|
||||
use Ecto.Migration
|
||||
|
||||
def up do
|
||||
create table(:fun_with_flags_toggles, primary_key: false) do
|
||||
add :id, :bigserial, primary_key: true
|
||||
add :flag_name, :string, null: false
|
||||
add :gate_type, :string, null: false
|
||||
add :target, :string, null: false
|
||||
add :enabled, :boolean, null: false
|
||||
end
|
||||
|
||||
create index(
|
||||
:fun_with_flags_toggles,
|
||||
[:flag_name, :gate_type, :target],
|
||||
[unique: true, name: "fwf_flag_name_gate_target_idx"]
|
||||
)
|
||||
end
|
||||
|
||||
def down do
|
||||
drop table(:fun_with_flags_toggles)
|
||||
end
|
||||
end
|
|
@ -40,7 +40,7 @@ config :core, :pow,
|
|||
user: Legendary.Auth.User,
|
||||
repo: Legendary.Core.Repo,
|
||||
extensions: [PowEmailConfirmation, PowPersistentSession, PowResetPassword],
|
||||
controller_callbacks: Pow.Extension.Phoenix.ControllerCallbacks,
|
||||
controller_callbacks: AuthWeb.Pow.ControllerCallbacks,
|
||||
mailer_backend: Legendary.AuthWeb.Pow.Mailer,
|
||||
web_mailer_module: Legendary.AuthWeb,
|
||||
web_module: Legendary.AuthWeb,
|
||||
|
@ -74,7 +74,25 @@ config :app,
|
|||
crontab: [
|
||||
]
|
||||
|
||||
config :mnesia, dir: to_charlist(Path.expand("./priv/mnesia"))
|
||||
config :mnesia, dir: to_charlist(Path.expand("./priv/mnesia@#{Kernel.node}"))
|
||||
|
||||
# Feature flags
|
||||
|
||||
config :fun_with_flags, :cache,
|
||||
enabled: true,
|
||||
ttl: 300 # seconds
|
||||
|
||||
config :fun_with_flags, :persistence,
|
||||
adapter: FunWithFlags.Store.Persistent.Ecto,
|
||||
repo: Legendary.Core.Repo
|
||||
|
||||
config :fun_with_flags, :cache_bust_notifications,
|
||||
enabled: true,
|
||||
adapter: FunWithFlags.Notifications.PhoenixPubSub,
|
||||
client: App.PubSub
|
||||
|
||||
# Notifications can also be disabled, which will also remove the Redis/Redix dependency
|
||||
config :fun_with_flags, :cache_bust_notifications, [enabled: false]
|
||||
|
||||
import_config "email_styles.exs"
|
||||
import_config "admin.exs"
|
||||
|
|
|
@ -15,7 +15,7 @@ use Mix.Config
|
|||
]
|
||||
|> Enum.map(fn {otp_app, module} ->
|
||||
config otp_app, Module.concat(module, "Endpoint"),
|
||||
http: [port: 4000],
|
||||
http: [port: String.to_integer(System.get_env("PORT") || "4000")],
|
||||
debug_errors: true,
|
||||
code_reloader: true,
|
||||
check_origin: false,
|
||||
|
@ -24,18 +24,19 @@ use Mix.Config
|
|||
"node_modules/webpack/bin/webpack.js",
|
||||
"--mode",
|
||||
"development",
|
||||
"--watch-stdin",
|
||||
"--watch",
|
||||
"--watch-options-stdin",
|
||||
cd: Path.expand("../apps/#{otp_app}/assets", __DIR__)
|
||||
]
|
||||
]
|
||||
|
||||
config otp_app, Module.concat(module, "Endpoint"),
|
||||
config otp_app, AppWeb.Endpoint,
|
||||
live_reload: [
|
||||
patterns: [
|
||||
~r"priv/static/.*(js|css|png|jpeg|jpg|gif|svg)$",
|
||||
~r"priv/gettext/.*(po)$",
|
||||
~r"lib/app/(live|views)/.*(ex)$",
|
||||
~r"lib/app/templates/.*(eex)$"
|
||||
~r"(live|views)/.*(ex)$",
|
||||
~r"templates/.*(eex)$"
|
||||
]
|
||||
]
|
||||
end)
|
||||
|
@ -61,7 +62,7 @@ config :core, Legendary.CoreMailer, adapter: Bamboo.LocalAdapter
|
|||
config :libcluster,
|
||||
topologies: [
|
||||
erlang_hosts: [
|
||||
strategy: Elixir.Cluster.Strategy.ErlangHosts,
|
||||
strategy: Elixir.Cluster.Strategy.Gossip,
|
||||
]
|
||||
]
|
||||
|
||||
|
|
|
@ -73,7 +73,7 @@ config :core, Legendary.CoreMailer,
|
|||
username: {:system, "SMTP_USERNAME"},
|
||||
password: {:system, "SMTP_PASSWORD"},
|
||||
tls: :if_available,
|
||||
allowed_tls_versions: [:"tlsv1", :"tlsv1.1", :"tlsv1.2"],
|
||||
allowed_tls_versions: [:tlsv1, :"tlsv1.1", :"tlsv1.2"],
|
||||
ssl: false,
|
||||
retries: 1,
|
||||
no_mx_lookups: false,
|
||||
|
|
2
mix.exs
2
mix.exs
|
@ -1,7 +1,7 @@
|
|||
defmodule Legendary.Mixfile do
|
||||
use Mix.Project
|
||||
|
||||
@version "2.10.0"
|
||||
@version "2.11.2"
|
||||
|
||||
def project do
|
||||
[
|
||||
|
|
22
mix.lock
22
mix.lock
|
@ -16,25 +16,25 @@
|
|||
"db_connection": {:hex, :db_connection, "2.2.2", "3bbca41b199e1598245b716248964926303b5d4609ff065125ce98bcd368939e", [:mix], [{:connection, "~> 1.0.2", [hex: :connection, repo: "hexpm", optional: false]}], "hexpm", "642af240d8a8affb93b4ba5a6fcd2bbcbdc327e1a524b825d383711536f8070c"},
|
||||
"decimal": {:hex, :decimal, "1.9.0", "83e8daf59631d632b171faabafb4a9f4242c514b0a06ba3df493951c08f64d07", [:mix], [], "hexpm", "b1f2343568eed6928f3e751cf2dffde95bfaa19dd95d09e8a9ea92ccfd6f7d85"},
|
||||
"dialyxir": {:hex, :dialyxir, "1.0.0", "6a1fa629f7881a9f5aaf3a78f094b2a51a0357c843871b8bc98824e7342d00a5", [:mix], [{:erlex, ">= 0.2.6", [hex: :erlex, repo: "hexpm", optional: false]}], "hexpm", "aeb06588145fac14ca08d8061a142d52753dbc2cf7f0d00fc1013f53f8654654"},
|
||||
"earmark": {:hex, :earmark, "1.4.3", "364ca2e9710f6bff494117dbbd53880d84bebb692dafc3a78eb50aa3183f2bfd", [:mix], [], "hexpm", "8cf8a291ebf1c7b9539e3cddb19e9cef066c2441b1640f13c34c1d3cfc825fec"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.12", "b245e875ec0a311a342320da0551da407d9d2b65d98f7a9597ae078615af3449", [:mix], [], "hexpm", "711e2cc4d64abb7d566d43f54b78f7dc129308a63bc103fbd88550d2174b3160"},
|
||||
"earmark": {:hex, :earmark, "1.4.15", "2c7f924bf495ec1f65bd144b355d0949a05a254d0ec561740308a54946a67888", [:mix], [{:earmark_parser, ">= 1.4.13", [hex: :earmark_parser, repo: "hexpm", optional: false]}], "hexpm", "3b1209b85bc9f3586f370f7c363f6533788fb4e51db23aa79565875e7f9999ee"},
|
||||
"earmark_parser": {:hex, :earmark_parser, "1.4.13", "0c98163e7d04a15feb62000e1a891489feb29f3d10cb57d4f845c405852bbef8", [:mix], [], "hexpm", "d602c26af3a0af43d2f2645613f65841657ad6efc9f0e361c3b6c06b578214ba"},
|
||||
"ecto": {:hex, :ecto, "3.4.6", "08f7afad3257d6eb8613309af31037e16c36808dfda5a3cd0cb4e9738db030e4", [:mix], [{:decimal, "~> 1.6 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "6f13a9e2a62e75c2dcfc7207bfc65645ab387af8360db4c89fee8b5a4bf3f70b"},
|
||||
"ecto_sql": {:hex, :ecto_sql, "3.4.4", "d28bac2d420f708993baed522054870086fd45016a9d09bb2cd521b9c48d32ea", [:mix], [{:db_connection, "~> 2.2", [hex: :db_connection, repo: "hexpm", optional: false]}, {:ecto, "~> 3.4.3", [hex: :ecto, repo: "hexpm", optional: false]}, {:myxql, "~> 0.3.0 or ~> 0.4.0", [hex: :myxql, repo: "hexpm", optional: true]}, {:postgrex, "~> 0.15.0", [hex: :postgrex, repo: "hexpm", optional: true]}, {:tds, "~> 2.1.0", [hex: :tds, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "edb49af715dd72f213b66adfd0f668a43c17ed510b5d9ac7528569b23af57fe8"},
|
||||
"elixir_make": {:hex, :elixir_make, "0.6.0", "38349f3e29aff4864352084fc736fa7fa0f2995a819a737554f7ebd28b85aaab", [:mix], [], "hexpm", "d522695b93b7f0b4c0fcb2dfe73a6b905b1c301226a5a55cb42e5b14d509e050"},
|
||||
"erlex": {:hex, :erlex, "0.2.6", "c7987d15e899c7a2f34f5420d2a2ea0d659682c06ac607572df55a43753aa12e", [:mix], [], "hexpm", "2ed2e25711feb44d52b17d2780eabf998452f6efda104877a3881c2f8c0c0c75"},
|
||||
"ex_cldr": {:hex, :ex_cldr, "2.13.0", "742f14a4afcfea61a190d603d8e555d2c91d71e4e8fc2520d5dc35616969e225", [:mix], [{:cldr_utils, "~> 2.3", [hex: :cldr_utils, repo: "hexpm", optional: false]}, {:decimal, "~> 1.6", [hex: :decimal, repo: "hexpm", optional: false]}, {:gettext, "~> 0.13", [hex: :gettext, repo: "hexpm", optional: true]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:plug, "~> 1.4", [hex: :plug, repo: "hexpm", optional: true]}, {:telemetry, "~> 0.4.0", [hex: :telemetry, repo: "hexpm", optional: true]}], "hexpm", "5e4cf3e945ee60156a3342e2a762f69036ffbe1f80520cc88592d68f12c5db55"},
|
||||
"ex_doc": {:hex, :ex_doc, "0.24.0", "2df14354835afaabdf87cb2971ea9485d8a36ff590e4b6c250b4f60c8fdf9143", [:mix], [{:earmark_parser, "~> 1.4.0", [hex: :earmark_parser, repo: "hexpm", optional: false]}, {:makeup_elixir, "~> 0.14", [hex: :makeup_elixir, repo: "hexpm", optional: false]}, {:makeup_erlang, "~> 0.1", [hex: :makeup_erlang, repo: "hexpm", optional: false]}], "hexpm", "a0f4bcff21ceebea48414e49885d2a3e542200f76a2facf3f8faa54935eeb721"},
|
||||
"ex_prompt": {:hex, :ex_prompt, "0.1.5", "b136642d0962f8ea37b3c9fa185ad1f42c71c3b9c6c3950f0358d7f3d2db2970", [:mix], [], "hexpm", "ad19a404708c9c7b05d36090b2d074ceafbed248a8de1a22d45a05ebe6994b83"},
|
||||
"ex_prompt": {:hex, :ex_prompt, "0.2.0", "4030424e9a7710e1939d81eea4a82af2e0a1826065adb28d59bc01e919af4a60", [:mix], [], "hexpm", "220ac023d87d529457b87c9db4b40ce542bff93ae2de16c582808c6822dfe3e8"},
|
||||
"excoveralls": {:hex, :excoveralls, "0.13.0", "4e1b7cc4e0351d8d16e9be21b0345a7e165798ee5319c7800b9138ce17e0b38e", [:mix], [{:hackney, "~> 1.16", [hex: :hackney, repo: "hexpm", optional: false]}, {:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: false]}], "hexpm", "fe2a56c8909564e2e6764765878d7d5e141f2af3bc8ff3b018a68ee2a218fced"},
|
||||
"file_system": {:hex, :file_system, "0.2.8", "f632bd287927a1eed2b718f22af727c5aeaccc9a98d8c2bd7bff709e851dc986", [:mix], [], "hexpm", "97a3b6f8d63ef53bd0113070102db2ce05352ecf0d25390eb8d747c2bde98bca"},
|
||||
"floki": {:hex, :floki, "0.25.0", "b1c9ddf5f32a3a90b43b76f3386ca054325dc2478af020e87b5111c19f2284ac", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "631f4e627c46d5ecd347df5a2accdaf0621c77c3693c5b75a8ad58e84c61f242"},
|
||||
"floki": {:hex, :floki, "0.31.0", "f05ee8a8e6a3ced4e62beeb2c79a63bc8e12ab98fbaaf6e6a3d9b76b1278e23f", [:mix], [{:html_entities, "~> 0.5.0", [hex: :html_entities, repo: "hexpm", optional: false]}], "hexpm", "b05afa372f5c345a5bf240ac25ea1f0f3d5fcfd7490ac0beeb4a203f9444891e"},
|
||||
"gen_smtp": {:hex, :gen_smtp, "1.1.1", "bf9303c31735100631b1d708d629e4c65944319d1143b5c9952054f4a1311d85", [:rebar3], [{:hut, "1.3.0", [hex: :hut, repo: "hexpm", optional: false]}, {:ranch, ">= 1.7.0", [hex: :ranch, repo: "hexpm", optional: false]}], "hexpm", "51bc50cc017efd4a4248cbc39ea30fb60efa7d4a49688986fafad84434ff9ab7"},
|
||||
"gen_stage": {:hex, :gen_stage, "1.0.0", "51c8ae56ff54f9a2a604ca583798c210ad245f415115453b773b621c49776df5", [:mix], [], "hexpm", "1d9fc978db5305ac54e6f5fec7adf80cd893b1000cf78271564c516aa2af7706"},
|
||||
"gen_state_machine": {:hex, :gen_state_machine, "2.1.0", "a38b0e53fad812d29ec149f0d354da5d1bc0d7222c3711f3a0bd5aa608b42992", [:mix], [], "hexpm", "ae367038808db25cee2f2c4b8d0531522ea587c4995eb6f96ee73410a60fa06b"},
|
||||
"gettext": {:hex, :gettext, "0.18.2", "7df3ea191bb56c0309c00a783334b288d08a879f53a7014341284635850a6e55", [:mix], [], "hexpm", "f9f537b13d4fdd30f3039d33cb80144c3aa1f8d9698e47d7bcbcc8df93b1f5c5"},
|
||||
"hackney": {:hex, :hackney, "1.17.4", "99da4674592504d3fb0cfef0db84c3ba02b4508bae2dff8c0108baa0d6e0977c", [:rebar3], [{:certifi, "~>2.6.1", [hex: :certifi, repo: "hexpm", optional: false]}, {:idna, "~>6.1.0", [hex: :idna, repo: "hexpm", optional: false]}, {:metrics, "~>1.0.0", [hex: :metrics, repo: "hexpm", optional: false]}, {:mimerl, "~>1.1", [hex: :mimerl, repo: "hexpm", optional: false]}, {:parse_trans, "3.3.1", [hex: :parse_trans, repo: "hexpm", optional: false]}, {:ssl_verify_fun, "~>1.1.0", [hex: :ssl_verify_fun, repo: "hexpm", optional: false]}, {:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "de16ff4996556c8548d512f4dbe22dd58a587bf3332e7fd362430a7ef3986b16"},
|
||||
"html_entities": {:hex, :html_entities, "0.5.1", "1c9715058b42c35a2ab65edc5b36d0ea66dd083767bef6e3edb57870ef556549", [:mix], [], "hexpm", "30efab070904eb897ff05cd52fa61c1025d7f8ef3a9ca250bc4e6513d16c32de"},
|
||||
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.0.1", "2572e7122c78ab7e57b613e7c7f5e42bf9b3c25e430e32f23f1413d86db8a0af", [:mix], [{:mochiweb, "~> 2.12.2", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm", "c334e2835e094fb9c04658bd4cfc7533fa51a8f56f11343c57ab9cb2a01d8613"},
|
||||
"html_entities": {:hex, :html_entities, "0.5.2", "9e47e70598da7de2a9ff6af8758399251db6dbb7eebe2b013f2bbd2515895c3c", [:mix], [], "hexpm", "c53ba390403485615623b9531e97696f076ed415e8d8058b1dbaa28181f4fdcc"},
|
||||
"html_sanitize_ex": {:hex, :html_sanitize_ex, "1.4.1", "e8a67da405fe9f0d1be121a40a60f70811192033a5b8d00a95dddd807f5e053e", [:mix], [{:mochiweb, "~> 2.15", [hex: :mochiweb, repo: "hexpm", optional: false]}], "hexpm", "68d92656f47cd73598c45ad2394561f025c8c65d146001b955fd7b517858962a"},
|
||||
"hut": {:hex, :hut, "1.3.0", "71f2f054e657c03f959cf1acc43f436ea87580696528ca2a55c8afb1b06c85e7", [:"erlang.mk", :rebar, :rebar3], [], "hexpm", "7e15d28555d8a1f2b5a3a931ec120af0753e4853a4c66053db354f35bf9ab563"},
|
||||
"idna": {:hex, :idna, "6.1.1", "8a63070e9f7d0c62eb9d9fcb360a7de382448200fbbd1b106cc96d3d8099df8d", [:rebar3], [{:unicode_util_compat, "~>0.7.0", [hex: :unicode_util_compat, repo: "hexpm", optional: false]}], "hexpm", "92376eb7894412ed19ac475e4a86f7b413c1b9fbb5bd16dccd57934157944cea"},
|
||||
"jason": {:hex, :jason, "1.2.2", "ba43e3f2709fd1aa1dce90aaabfd039d000469c05c56f0b8e31978e03fa39052", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "18a228f5f0058ee183f29f9eae0805c6e59d61c3b006760668d8d18ff0d12179"},
|
||||
|
@ -49,7 +49,7 @@
|
|||
"metrics": {:hex, :metrics, "1.0.1", "25f094dea2cda98213cecc3aeff09e940299d950904393b2a29d191c346a8486", [:rebar3], [], "hexpm", "69b09adddc4f74a40716ae54d140f93beb0fb8978d8636eaded0c31b6f099f16"},
|
||||
"mime": {:hex, :mime, "1.6.0", "dabde576a497cef4bbdd60aceee8160e02a6c89250d6c0b29e56c0dfb00db3d2", [:mix], [], "hexpm", "31a1a8613f8321143dde1dafc36006a17d28d02bdfecb9e95a880fa7aabd19a7"},
|
||||
"mimerl": {:hex, :mimerl, "1.2.0", "67e2d3f571088d5cfd3e550c383094b47159f3eee8ffa08e64106cdf5e981be3", [:rebar3], [], "hexpm", "f278585650aa581986264638ebf698f8bb19df297f66ad91b18910dfc6e19323"},
|
||||
"mochiweb": {:hex, :mochiweb, "2.12.2", "80804ad342afa3d7f3524040d4eed66ce74b17a555de454ac85b07c479928e46", [:make, :rebar], [], "hexpm", "d3e681d4054b74a96cf2efcd09e94157ab83a5f55ddc4ce69f90b8144673bd7a"},
|
||||
"mochiweb": {:hex, :mochiweb, "2.20.1", "e4dbd0ed716f076366ecf62ada5755a844e1d95c781e8c77df1d4114be868cdf", [:rebar3], [], "hexpm", "d1aeee7870470d2fa9eae0b3d5ab6c33801aa2d82b10e9dade885c5c921b36aa"},
|
||||
"mock": {:hex, :mock, "0.3.5", "feb81f52b8dcf0a0d65001d2fec459f6b6a8c22562d94a965862f6cc066b5431", [:mix], [{:meck, "~> 0.8.13", [hex: :meck, repo: "hexpm", optional: false]}], "hexpm", "6fae404799408300f863550392635d8f7e3da6b71abdd5c393faf41b131c8728"},
|
||||
"neotomex": {:hex, :neotomex, "0.1.7", "64f76513653aa87ea7abdde0fd600e56955d838020a13d88f2bf334c88ac3e7a", [:mix], [], "hexpm", "4b87b8f614d1cd89dc8ba80ba0e559bedb3ebf6f6d74cd774fcfdd215e861445"},
|
||||
"nimble_parsec": {:hex, :nimble_parsec, "1.1.0", "3a6fca1550363552e54c216debb6a9e95bd8d32348938e13de5eda962c0d7f89", [:mix], [], "hexpm", "08eb32d66b706e913ff748f11694b17981c0b04a33ef470e33e11b3d3ac8f54b"},
|
||||
|
@ -58,10 +58,10 @@
|
|||
"phoenix": {:hex, :phoenix, "1.5.9", "a6368d36cfd59d917b37c44386e01315bc89f7609a10a45a22f47c007edf2597", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.13 or ~> 3.0", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:phoenix_pubsub, "~> 2.0", [hex: :phoenix_pubsub, repo: "hexpm", optional: false]}, {:plug, "~> 1.10", [hex: :plug, repo: "hexpm", optional: false]}, {:plug_cowboy, "~> 1.0 or ~> 2.2", [hex: :plug_cowboy, repo: "hexpm", optional: true]}, {:plug_crypto, "~> 1.1.2 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "7e4bce20a67c012f1fbb0af90e5da49fa7bf0d34e3a067795703b74aef75427d"},
|
||||
"phoenix_ecto": {:hex, :phoenix_ecto, "4.1.0", "a044d0756d0464c5a541b4a0bf4bcaf89bffcaf92468862408290682c73ae50d", [:mix], [{:ecto, "~> 3.0", [hex: :ecto, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.9", [hex: :phoenix_html, repo: "hexpm", optional: true]}, {:plug, "~> 1.0", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "c5e666a341ff104d0399d8f0e4ff094559b2fde13a5985d4cb5023b2c2ac558b"},
|
||||
"phoenix_html": {:hex, :phoenix_html, "2.14.3", "51f720d0d543e4e157ff06b65de38e13303d5778a7919bcc696599e5934271b8", [:mix], [{:plug, "~> 1.5", [hex: :plug, repo: "hexpm", optional: false]}], "hexpm", "efd697a7fff35a13eeeb6b43db884705cba353a1a41d127d118fda5f90c8e80f"},
|
||||
"phoenix_html_sanitizer": {:hex, :phoenix_html_sanitizer, "1.0.2", "e2c8cfbc83660e362753de127cc957bec3442a8aecdf271fb65a684a906fccf5", [:mix], [{:html_sanitize_ex, "~> 1.0.0", [hex: :html_sanitize_ex, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "47aebb08fa954b7ad95f295fb701df9800ee3a489212119c9c6074a65e1e5a10"},
|
||||
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.2.6", "1b4e1b7d797386b7f9d70d2af931dc9843a5f2f2423609d22cef1eec4e4dba7d", [:mix], [{:phoenix_html, "~> 2.14.1 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.13.1", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.4.0 or ~> 0.5.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "b20dcad98c4ca63d38a7f5e7a40936e1e8e9da983d3d722b88ae33afb866c9ca"},
|
||||
"phoenix_html_sanitizer": {:hex, :phoenix_html_sanitizer, "1.1.0", "ea9e1162217621208ba6b2951a24abe2c06b39347f65c22c31312f9f5ac0fa75", [:mix], [{:html_sanitize_ex, "~> 1.1", [hex: :html_sanitize_ex, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.0", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "089f28f0592d58f7cf1f032b89c13e873dc73c77a2ccf3386aee976c6ff077c9"},
|
||||
"phoenix_live_dashboard": {:hex, :phoenix_live_dashboard, "0.4.0", "87990e68b60213d7487e65814046f9a2bed4a67886c943270125913499b3e5c3", [:mix], [{:ecto_psql_extras, "~> 0.4.1 or ~> 0.5", [hex: :ecto_psql_extras, repo: "hexpm", optional: true]}, {:phoenix_html, "~> 2.14.1 or ~> 2.15", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:phoenix_live_view, "~> 0.15.0", [hex: :phoenix_live_view, repo: "hexpm", optional: false]}, {:telemetry_metrics, "~> 0.4.0 or ~> 0.5.0 or ~> 0.6.0", [hex: :telemetry_metrics, repo: "hexpm", optional: false]}], "hexpm", "8d52149e58188e9e4497cc0d8900ab94d9b66f96998ec38c47c7a4f8f4f50e57"},
|
||||
"phoenix_live_reload": {:hex, :phoenix_live_reload, "1.2.4", "940c0344b1d66a2e46eef02af3a70e0c5bb45a4db0bf47917add271b76cd3914", [:mix], [{:file_system, "~> 0.2.1 or ~> 0.3", [hex: :file_system, repo: "hexpm", optional: false]}, {:phoenix, "~> 1.4", [hex: :phoenix, repo: "hexpm", optional: false]}], "hexpm", "38f9308357dea4cc77f247e216da99fcb0224e05ada1469167520bed4cb8cccd"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "0.13.3", "2186c55cc7c54ca45b97c6f28cfd267d1c61b5f205f3c83533704cd991bdfdec", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.4.17 or ~> 1.5.2", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}], "hexpm", "c6309a7da2e779cb9cdf2fb603d75f38f49ef324bedc7a81825998bd1744ff8a"},
|
||||
"phoenix_live_view": {:hex, :phoenix_live_view, "0.15.7", "09720b8e5151b3ca8ef739cd7626d4feb987c69ba0b509c9bbdb861d5a365881", [:mix], [{:jason, "~> 1.0", [hex: :jason, repo: "hexpm", optional: true]}, {:phoenix, "~> 1.5.7", [hex: :phoenix, repo: "hexpm", optional: false]}, {:phoenix_html, "~> 2.14", [hex: :phoenix_html, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4.2 or ~> 0.5", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "3a756cf662420272d0f1b3b908cce5222163b5a95aa9bab404f9d29aff53276e"},
|
||||
"phoenix_pubsub": {:hex, :phoenix_pubsub, "2.0.0", "a1ae76717bb168cdeb10ec9d92d1480fec99e3080f011402c0a2d68d47395ffb", [:mix], [], "hexpm", "c52d948c4f261577b9c6fa804be91884b381a7f8f18450c5045975435350f771"},
|
||||
"php_serializer": {:hex, :php_serializer, "0.9.2", "59c5fd6bd3096671fd89358fb8229341ac7423b50ad8d45a15213b02ea2edab2", [:mix], [], "hexpm", "34eb835a460944f7fc216773b363c02e7dcf8ac0390c9e9ccdbd92b31a7ca59a"},
|
||||
"plug": {:hex, :plug, "1.11.1", "f2992bac66fdae679453c9e86134a4201f6f43a687d8ff1cd1b2862d53c80259", [:mix], [{:mime, "~> 1.0", [hex: :mime, repo: "hexpm", optional: false]}, {:plug_crypto, "~> 1.1.1 or ~> 1.2", [hex: :plug_crypto, repo: "hexpm", optional: false]}, {:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "23524e4fefbb587c11f0833b3910bfb414bf2e2534d61928e920f54e3a1b881f"},
|
||||
|
@ -76,7 +76,7 @@
|
|||
"ssl_verify_fun": {:hex, :ssl_verify_fun, "1.1.6", "cf344f5692c82d2cd7554f5ec8fd961548d4fd09e7d22f5b62482e5aeaebd4b0", [:make, :mix, :rebar3], [], "hexpm", "bdb0d2471f453c88ff3908e7686f86f9be327d065cc1ec16fa4540197ea04680"},
|
||||
"swarm": {:hex, :swarm, "3.4.0", "64f8b30055d74640d2186c66354b33b999438692a91be275bb89cdc7e401f448", [:mix], [{:gen_state_machine, "~> 2.0", [hex: :gen_state_machine, repo: "hexpm", optional: false]}, {:libring, "~> 1.0", [hex: :libring, repo: "hexpm", optional: false]}], "hexpm", "94884f84783fc1ba027aba8fe8a7dae4aad78c98e9f9c76667ec3471585c08c6"},
|
||||
"telemetry": {:hex, :telemetry, "0.4.3", "a06428a514bdbc63293cd9a6263aad00ddeb66f608163bdec7c8995784080818", [:rebar3], [], "hexpm", "eb72b8365ffda5bed68a620d1da88525e326cb82a75ee61354fc24b844768041"},
|
||||
"telemetry_metrics": {:hex, :telemetry_metrics, "0.5.0", "1b796e74add83abf844e808564275dfb342bcc930b04c7577ab780e262b0d998", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "31225e6ce7a37a421a0a96ec55244386aec1c190b22578bd245188a4a33298fd"},
|
||||
"telemetry_metrics": {:hex, :telemetry_metrics, "0.6.0", "da9d49ee7e6bb1c259d36ce6539cd45ae14d81247a2b0c90edf55e2b50507f7b", [:mix], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "5cfe67ad464b243835512aa44321cee91faed6ea868d7fb761d7016e02915c3d"},
|
||||
"telemetry_poller": {:hex, :telemetry_poller, "0.5.1", "21071cc2e536810bac5628b935521ff3e28f0303e770951158c73eaaa01e962a", [:rebar3], [{:telemetry, "~> 0.4", [hex: :telemetry, repo: "hexpm", optional: false]}], "hexpm", "4cab72069210bc6e7a080cec9afffad1b33370149ed5d379b81c7c5f0c663fd4"},
|
||||
"timex": {:hex, :timex, "3.6.2", "845cdeb6119e2fef10751c0b247b6c59d86d78554c83f78db612e3290f819bc2", [:mix], [{:combine, "~> 0.10", [hex: :combine, repo: "hexpm", optional: false]}, {:gettext, "~> 0.10", [hex: :gettext, repo: "hexpm", optional: false]}, {:tzdata, "~> 0.1.8 or ~> 0.5 or ~> 1.0.0", [hex: :tzdata, repo: "hexpm", optional: false]}], "hexpm", "26030b46199d02a590be61c2394b37ea25a3664c02fafbeca0b24c972025d47a"},
|
||||
"tzdata": {:hex, :tzdata, "1.0.3", "73470ad29dde46e350c60a66e6b360d3b99d2d18b74c4c349dbebbc27a09a3eb", [:mix], [{:hackney, "~> 1.0", [hex: :hackney, repo: "hexpm", optional: false]}], "hexpm", "a6e1ee7003c4d04ecbd21dd3ec690d4c6662db5d3bbdd7262d53cdf5e7c746c1"},
|
||||
|
|
14332
package-lock.json
generated
14332
package-lock.json
generated
File diff suppressed because it is too large
Load diff
12
package.json
12
package.json
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "@mythic-insight/legendary",
|
||||
"version": "2.10.0",
|
||||
"version": "2.11.2",
|
||||
"private": true,
|
||||
"description": "The Legendary Phoenix Boilerplate.",
|
||||
"main": "index.js",
|
||||
|
@ -19,14 +19,16 @@
|
|||
"homepage": "https://gitlab.com/mythic-insight/legendary#readme",
|
||||
"devDependencies": {
|
||||
"@google/semantic-release-replace-plugin": "^1.0.2",
|
||||
"@semantic-release/commit-analyzer": "^6.1.0",
|
||||
"@semantic-release/commit-analyzer": "^8.0.1",
|
||||
"@semantic-release/exec": "^5.0.0",
|
||||
"@semantic-release/git": "^7.0.8",
|
||||
"@semantic-release/npm": "^7.0.9",
|
||||
"@semantic-release/git": "^9.0.0",
|
||||
"@semantic-release/npm": "^7.1.3",
|
||||
"dot": "^1.1.3",
|
||||
"semantic-release": "^15.14.0"
|
||||
"http-proxy": "^1.18.1",
|
||||
"semantic-release": "^17.4.4"
|
||||
},
|
||||
"release": {
|
||||
"branch": "master",
|
||||
"plugins": [
|
||||
"@semantic-release/commit-analyzer"
|
||||
],
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
@ -6,10 +6,10 @@ set -e
|
|||
if ! brew -v &> /dev/null
|
||||
then
|
||||
echo "WARNING: Cannot find brew. Skipping brewfile installation."
|
||||
export KERL_CONFIGURE_OPTIONS="--disable-hipe"
|
||||
export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --disable-hipe"
|
||||
else
|
||||
brew bundle
|
||||
export KERL_CONFIGURE_OPTIONS="--disable-hipe --with-ssl=$(brew --prefix openssl)"
|
||||
export KERL_CONFIGURE_OPTIONS="$KERL_CONFIGURE_OPTIONS --disable-hipe --with-ssl=$(brew --prefix openssl)"
|
||||
fi
|
||||
|
||||
if ! which asdf &> /dev/null
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
|
5
script/env-ci
Executable file
5
script/env-ci
Executable file
|
@ -0,0 +1,5 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
const envCi = require('env-ci');
|
||||
|
||||
console.log(envCi());
|
34
script/proxy
Executable file
34
script/proxy
Executable file
|
@ -0,0 +1,34 @@
|
|||
#!/usr/bin/env node
|
||||
|
||||
var http = require('http'),
|
||||
httpProxy = require('http-proxy');
|
||||
|
||||
//
|
||||
// Create a proxy server with custom application logic
|
||||
//
|
||||
var proxy = new httpProxy.createProxyServer({});
|
||||
|
||||
var proxyServer = http.createServer(function (req, res) {
|
||||
proxy.web(req, res, {
|
||||
target: {
|
||||
host: 'localhost',
|
||||
port: 4001
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
//
|
||||
// Listen to the `upgrade` event and proxy the
|
||||
// WebSocket requests as well.
|
||||
//
|
||||
proxyServer.on('upgrade', function (req, socket, head) {
|
||||
proxy.ws(req, socket, head, {
|
||||
target: {
|
||||
host: 'localhost',
|
||||
port: 4001
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log("listening on port 4000")
|
||||
proxyServer.listen(4000);
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
|
33
script/server-clustered
Executable file
33
script/server-clustered
Executable file
|
@ -0,0 +1,33 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
||||
DIR_PATH=$(dirname $0)
|
||||
|
||||
$DIR_PATH/update
|
||||
|
||||
trap_with_arg() { # from https://stackoverflow.com/a/2183063/804678
|
||||
local func="$1"; shift
|
||||
for sig in "$@"; do
|
||||
trap "$func $sig" "$sig"
|
||||
done
|
||||
}
|
||||
|
||||
stop() {
|
||||
trap - SIGINT EXIT
|
||||
printf '\n%s\n' "received $1, killing child processes"
|
||||
kill -s SIGINT 0
|
||||
}
|
||||
|
||||
trap_with_arg 'stop' EXIT SIGINT SIGTERM SIGHUP
|
||||
|
||||
CLUSTER_COOKIE=`openssl rand -hex 8`
|
||||
|
||||
PORT=4002 elixir --sname two --cookie $CLUSTER_COOKIE -S mix phx.server 2>/dev/null &
|
||||
PORT=4003 elixir --sname three --cookie $CLUSTER_COOKIE -S mix phx.server 2>/dev/null &
|
||||
PORT=4004 elixir --sname four --cookie $CLUSTER_COOKIE -S mix phx.server 2>/dev/null &
|
||||
|
||||
$DIR_PATH/proxy &
|
||||
|
||||
PORT=4001 iex --sname one --cookie $CLUSTER_COOKIE -S mix phx.server
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
#!/bin/sh
|
||||
#!/bin/bash
|
||||
|
||||
set -x
|
||||
set -e
|
||||
|
|
Loading…
Reference in a new issue