Skip to content

Commit 0351f52

Browse files
committed
improvement: prompt for minimum pg version
improvement: adjust mix task aliases to be used with `ash_postgres` closes #391
1 parent 6219e8b commit 0351f52

File tree

7 files changed

+152
-34
lines changed

7 files changed

+152
-34
lines changed

lib/igniter.ex

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,14 @@ defmodule AshPostgres.Igniter do
22
@moduledoc "Codemods and utilities for working with AshPostgres & Igniter"
33

44
@doc false
5-
def default_repo_contents(otp_app) do
5+
def default_repo_contents(otp_app, name, opts \\ []) do
6+
min_pg_version = get_min_pg_version(name, opts)
7+
68
"""
79
use AshPostgres.Repo, otp_app: #{inspect(otp_app)}
810
911
def min_pg_version do
10-
# Adjust this according to your postgres version
11-
%Version{major: 16, minor: 0, patch: 0}
12+
%Version{major: #{min_pg_version.major}, minor: #{min_pg_version.minor || 0}, patch: #{min_pg_version.patch || 0}}
1213
end
1314
1415
def installed_extensions do
@@ -80,7 +81,12 @@ defmodule AshPostgres.Igniter do
8081
otp_app = Igniter.Project.Application.app_name(igniter)
8182

8283
igniter =
83-
Igniter.Code.Module.create_module(igniter, repo, default_repo_contents(otp_app))
84+
Igniter.Code.Module.create_module(
85+
igniter,
86+
repo,
87+
default_repo_contents(otp_app, repo),
88+
opts
89+
)
8490

8591
{igniter, repo}
8692
else
@@ -110,4 +116,50 @@ defmodule AshPostgres.Igniter do
110116
)
111117
end)
112118
end
119+
120+
@doc false
121+
def get_min_pg_version(name, opts) do
122+
if opts[:yes] do
123+
%Version{major: 16, minor: 0, patch: 0}
124+
else
125+
lead_in = """
126+
Generating #{inspect(name)}
127+
128+
What is the minimum postgres version you will be using?
129+
130+
AshPostgres uses this information when generating queries and migrations
131+
to choose the best available features for your version of postgres.
132+
"""
133+
134+
format_request =
135+
"""
136+
Please enter the version in the format major.minor.patch (e.g. 13.4.0)
137+
138+
Default: 16.0.0
139+
140+
141+
"""
142+
143+
prompt =
144+
if opts[:invalid_loop?] do
145+
format_request
146+
else
147+
"#{lead_in}\n\n#{format_request}"
148+
end
149+
150+
prompt
151+
|> String.trim_trailing()
152+
|> Mix.shell().prompt()
153+
|> String.trim()
154+
|> case do
155+
"" -> "16.0.0"
156+
input -> input
157+
end
158+
|> Version.parse()
159+
|> case do
160+
{:ok, version} -> version
161+
:error -> get_min_pg_version(name, Keyword.put(opts, :invalid_loop?, true))
162+
end
163+
end
164+
end
113165
end

lib/mix/helpers.ex

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
defmodule AshPostgres.Mix.Helpers do
22
@moduledoc false
3-
def domains!(opts, args, error_on_no_domains? \\ true) do
3+
def domains!(opts, args) do
44
apps =
55
if apps_paths = Mix.Project.apps_paths() do
66
apps_paths |> Map.keys() |> Enum.sort()
@@ -30,11 +30,7 @@ defmodule AshPostgres.Mix.Helpers do
3030
|> Enum.map(&ensure_compiled(&1, args))
3131
|> case do
3232
[] ->
33-
if error_on_no_domains? do
34-
raise "must supply the --domains argument, or set `config :my_app, ash_domains: [...]` in config"
35-
else
36-
[]
37-
end
33+
[]
3834

3935
domains ->
4036
domains

lib/mix/tasks/ash_postgres.generate_migrations.ex

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ defmodule Mix.Tasks.AshPostgres.GenerateMigrations do
100100
]
101101
)
102102

103-
domains = AshPostgres.Mix.Helpers.domains!(opts, args, false)
103+
domains = AshPostgres.Mix.Helpers.domains!(opts, args)
104104

105105
if Enum.empty?(domains) && !opts[:snapshots_only] do
106106
IO.warn("""

lib/mix/tasks/ash_postgres.install.ex

Lines changed: 90 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,29 @@ defmodule Mix.Tasks.AshPostgres.Install do
55
require Igniter.Code.Function
66
use Igniter.Mix.Task
77

8-
def igniter(igniter, _argv) do
8+
@impl true
9+
def info(_argv, _source) do
10+
%Igniter.Mix.Task.Info{
11+
schema: [
12+
yes: :boolean
13+
],
14+
aliases: [
15+
y: :yes
16+
]
17+
}
18+
end
19+
20+
@impl true
21+
def igniter(igniter, argv) do
922
repo = Igniter.Code.Module.module_name(igniter, "Repo")
1023
otp_app = Igniter.Project.Application.app_name(igniter)
1124

25+
opts = options!(argv)
26+
1227
igniter
1328
|> Igniter.Project.Formatter.import_dep(:ash_postgres)
14-
|> setup_repo_module(otp_app, repo)
29+
|> setup_aliases()
30+
|> setup_repo_module(otp_app, repo, opts)
1531
|> configure_config(otp_app, repo)
1632
|> configure_dev(otp_app, repo)
1733
|> configure_runtime(otp_app, repo)
@@ -29,6 +45,47 @@ defmodule Mix.Tasks.AshPostgres.Install do
2945
|> Ash.Igniter.codegen("initialize")
3046
end
3147

48+
defp setup_aliases(igniter) do
49+
is_ecto_setup = &Igniter.Code.Common.nodes_equal?(&1, "ecto.setup")
50+
51+
is_ecto_create_or_migrate =
52+
fn zipper ->
53+
Igniter.Code.Common.nodes_equal?(zipper, "ecto.create --quiet") or
54+
Igniter.Code.Common.nodes_equal?(zipper, "ecto.create") or
55+
Igniter.Code.Common.nodes_equal?(zipper, "ecto.migrate --quiet") or
56+
Igniter.Code.Common.nodes_equal?(zipper, "ecto.migrate")
57+
end
58+
59+
igniter
60+
|> Igniter.Project.TaskAliases.modify_existing_alias(
61+
"test",
62+
&Igniter.Code.List.remove_from_list(&1, is_ecto_create_or_migrate)
63+
)
64+
|> Igniter.Project.TaskAliases.modify_existing_alias(
65+
"test",
66+
&Igniter.Code.List.replace_in_list(
67+
&1,
68+
is_ecto_setup,
69+
"ash.setup"
70+
)
71+
)
72+
|> Igniter.Project.TaskAliases.add_alias("test", ["ash.setup --quiet", "test"],
73+
if_exists: {:prepend, "ash.setup --quiet"}
74+
)
75+
|> run_seeds_on_setup()
76+
end
77+
78+
defp run_seeds_on_setup(igniter) do
79+
if Igniter.exists?(igniter, "priv/repo/seeds.exs") do
80+
Igniter.Project.TaskAliases.add_alias(igniter, "ash.setup", [
81+
"ash.setup",
82+
"run priv/repo/seeds.exs"
83+
])
84+
else
85+
igniter
86+
end
87+
end
88+
3289
defp configure_config(igniter, otp_app, repo) do
3390
Igniter.Project.Config.configure(
3491
igniter,
@@ -256,26 +313,38 @@ defmodule Mix.Tasks.AshPostgres.Install do
256313
)
257314
end
258315

259-
defp setup_repo_module(igniter, otp_app, repo) do
260-
Igniter.Code.Module.find_and_update_or_create_module(
261-
igniter,
316+
defp setup_repo_module(igniter, otp_app, repo, opts) do
317+
{exists?, igniter} = Igniter.Project.Module.module_exists?(igniter, repo)
318+
319+
if exists? do
320+
Igniter.Project.Module.find_and_update_module!(
321+
igniter,
322+
repo,
323+
fn zipper ->
324+
{:ok,
325+
zipper
326+
|> set_otp_app(otp_app)
327+
|> Sourceror.Zipper.top()
328+
|> use_ash_postgres_instead_of_ecto()
329+
|> Sourceror.Zipper.top()
330+
|> remove_adapter_option()}
331+
end
332+
)
333+
else
334+
Igniter.Project.Module.create_module(
335+
igniter,
336+
repo,
337+
AshPostgres.Igniter.default_repo_contents(otp_app, repo, opts)
338+
)
339+
end
340+
|> Igniter.Project.Module.find_and_update_module!(
262341
repo,
263-
AshPostgres.Igniter.default_repo_contents(otp_app),
264-
fn zipper ->
265-
{:ok,
266-
zipper
267-
|> set_otp_app(otp_app)
268-
|> Sourceror.Zipper.top()
269-
|> use_ash_postgres_instead_of_ecto()
270-
|> Sourceror.Zipper.top()
271-
|> remove_adapter_option()}
272-
end
342+
&configure_installed_extensions_function/1
273343
)
274344
|> Igniter.Code.Module.find_and_update_module!(
275345
repo,
276-
&configure_installed_extensions_function/1
346+
&configure_min_pg_version_function(&1, repo, opts)
277347
)
278-
|> Igniter.Code.Module.find_and_update_module!(repo, &configure_min_pg_version_function/1)
279348
end
280349

281350
defp use_ash_postgres_instead_of_ecto(zipper) do
@@ -347,17 +416,18 @@ defmodule Mix.Tasks.AshPostgres.Install do
347416
end
348417
end
349418

350-
defp configure_min_pg_version_function(zipper) do
419+
defp configure_min_pg_version_function(zipper, repo, opts) do
351420
case Igniter.Code.Function.move_to_def(zipper, :min_pg_version, 0) do
352421
{:ok, zipper} ->
353422
{:ok, zipper}
354423

355424
_ ->
425+
min_pg_version = AshPostgres.Igniter.get_min_pg_version(repo, opts)
426+
356427
{:ok,
357428
Igniter.Code.Common.add_code(zipper, """
358429
def min_pg_version do
359-
# Adjust this according to your postgres version
360-
%Version{major: 16, minor: 0, patch: 0}
430+
%Version{major: #{min_pg_version.major}, minor: #{min_pg_version.minor || 0}, patch: #{min_pg_version.patch || 0}}
361431
end
362432
""")}
363433
end

mix.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ defmodule AshPostgres.MixProject do
166166
[
167167
{:ash, ash_version("~> 3.4 and >= 3.4.9")},
168168
{:ash_sql, ash_sql_version("~> 0.2 and >= 0.2.30")},
169-
{:igniter, "~> 0.3 and >= 0.3.36"},
169+
{:igniter, "~> 0.3 and >= 0.3.42"},
170170
{:ecto_sql, "~> 3.12"},
171171
{:ecto, "~> 3.12 and >= 3.12.1"},
172172
{:jason, "~> 1.0"},

mix.lock

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
"git_cli": {:hex, :git_cli, "0.3.0", "a5422f9b95c99483385b976f5d43f7e8233283a47cda13533d7c16131cb14df5", [:mix], [], "hexpm", "78cb952f4c86a41f4d3511f1d3ecb28edb268e3a7df278de2faa1bd4672eaf9b"},
2121
"git_ops": {:hex, :git_ops, "2.6.1", "cc7799a68c26cf814d6d1a5121415b4f5bf813de200908f930b27a2f1fe9dad5", [:mix], [{:git_cli, "~> 0.2", [hex: :git_cli, repo: "hexpm", optional: false]}, {:nimble_parsec, "~> 1.0", [hex: :nimble_parsec, repo: "hexpm", optional: false]}], "hexpm", "ce62d07e41fe993ec22c35d5edb11cf333a21ddaead6f5d9868fcb607d42039e"},
2222
"glob_ex": {:hex, :glob_ex, "0.1.8", "f7ef872877ca2ae7a792ab1f9ff73d9c16bf46ecb028603a8a3c5283016adc07", [:mix], [], "hexpm", "9e39d01729419a60a937c9260a43981440c43aa4cadd1fa6672fecd58241c464"},
23-
"igniter": {:hex, :igniter, "0.3.39", "e59b56836b9b22c6b76b1b9661c60a996eca7bbb3b0a22f7a888cd1c77d43419", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:rewrite, "~> 0.9", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "0e794a273b53442a6fb223a65cd9800648d6e2f8fdf8556bcf74d0af793f4bd4"},
23+
"igniter": {:hex, :igniter, "0.3.42", "29ab08de9ba4316a6eb0ac73cd4481b3d2c4e799a647b667faafe5c988487e1b", [:mix], [{:glob_ex, "~> 0.1.7", [hex: :glob_ex, repo: "hexpm", optional: false]}, {:jason, "~> 1.4", [hex: :jason, repo: "hexpm", optional: false]}, {:rewrite, "~> 0.9", [hex: :rewrite, repo: "hexpm", optional: false]}, {:sourceror, "~> 1.4", [hex: :sourceror, repo: "hexpm", optional: false]}, {:spitfire, ">= 0.1.3 and < 1.0.0-0", [hex: :spitfire, repo: "hexpm", optional: false]}], "hexpm", "d6bb222d7c6f29a9fb2461a93109da5787e4354928feea2b7a14827c27129115"},
2424
"inflex": {:hex, :inflex, "2.1.0", "a365cf0821a9dacb65067abd95008ca1b0bb7dcdd85ae59965deef2aa062924c", [:mix], [], "hexpm", "14c17d05db4ee9b6d319b0bff1bdf22aa389a25398d1952c7a0b5f3d93162dd8"},
2525
"iterex": {:hex, :iterex, "0.1.2", "58f9b9b9a22a55cbfc7b5234a9c9c63eaac26d276b3db80936c0e1c60355a5a6", [:mix], [], "hexpm", "2e103b8bcc81757a9af121f6dc0df312c9a17220f302b1193ef720460d03029d"},
2626
"jason": {:hex, :jason, "1.4.4", "b9226785a9aa77b6857ca22832cffa5d5011a667207eb2a0ad56adb5db443b8a", [:mix], [{:decimal, "~> 1.0 or ~> 2.0", [hex: :decimal, repo: "hexpm", optional: true]}], "hexpm", "c5eb0cab91f094599f94d55bc63409236a8ec69a21a67814529e8d5f6cc90b3b"},

test/mix/tasks/ash_postgres.install_test.exs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ defmodule Mix.Tasks.AshPostgres.InstallTest do
77
# any errors. We should add better tests here, though.
88
test "installation does not fail" do
99
test_project()
10-
|> Igniter.compose_task("ash_postgres.install")
10+
|> Igniter.compose_task("ash_postgres.install", ["--yes"])
1111
|> assert_creates("lib/test/repo.ex")
1212
end
1313
end

0 commit comments

Comments
 (0)