You've already forked tribes-plugin-template
template: make rename portable and add explicit otp_app dev flow
This commit is contained in:
11
README.md
11
README.md
@@ -27,15 +27,19 @@ mix test
|
||||
For local development alongside a Tribes checkout:
|
||||
|
||||
```bash
|
||||
# Build plugin code once (host loads BEAM from _build/dev/lib/<otp_app>/ebin)
|
||||
cd /path/to/your-plugin
|
||||
mix compile
|
||||
|
||||
# Symlink into the host plugins directory
|
||||
cd /path/to/tribes
|
||||
ln -s /path/to/your-plugin plugins/your_plugin
|
||||
|
||||
# Start Tribes dev server — your plugin loads automatically
|
||||
# Start Tribes dev server
|
||||
iex --sname dev -S mix phx.server
|
||||
```
|
||||
|
||||
Edit your plugin source. Phoenix code reloader picks up changes.
|
||||
When you change plugin Elixir code, re-run `mix compile` in the plugin repo.
|
||||
|
||||
## Project Structure
|
||||
|
||||
@@ -63,6 +67,9 @@ your_plugin/
|
||||
```json
|
||||
{
|
||||
"name": "your_plugin",
|
||||
"entry_module": "YourPlugin.Plugin",
|
||||
"host_api": "1",
|
||||
"otp_app": "your_plugin",
|
||||
"provides": ["some_capability@1"],
|
||||
"requires": ["ecto@1"],
|
||||
"enhances_with": ["inference@1"]
|
||||
|
||||
@@ -58,24 +58,44 @@ defmodule MyPlugin.Plugin do
|
||||
end
|
||||
|
||||
defp manifest_path do
|
||||
# In a release, manifest.json sits alongside ebin/ in the plugin directory.
|
||||
# In dev mode (path dep), it's at the project root.
|
||||
case :code.priv_dir(:my_plugin) do
|
||||
{:error, :bad_name} ->
|
||||
# Dev mode fallback: relative to project root
|
||||
Path.join(__DIR__, "../../../manifest.json") |> Path.expand()
|
||||
project_manifest = Path.join(__DIR__, "../../manifest.json") |> Path.expand()
|
||||
|
||||
priv_dir ->
|
||||
priv_dir |> to_string() |> Path.join("../manifest.json") |> Path.expand()
|
||||
end
|
||||
candidates =
|
||||
case :code.priv_dir(:my_plugin) do
|
||||
{:error, :bad_name} ->
|
||||
[project_manifest]
|
||||
|
||||
priv_dir ->
|
||||
priv_dir = to_string(priv_dir)
|
||||
|
||||
[
|
||||
Path.join(priv_dir, "../manifest.json") |> Path.expand(),
|
||||
project_manifest
|
||||
]
|
||||
end
|
||||
|
||||
first_existing_path(candidates) || project_manifest
|
||||
end
|
||||
|
||||
defp migrations_path(manifest) do
|
||||
if manifest["migrations"] do
|
||||
case :code.priv_dir(:my_plugin) do
|
||||
{:error, :bad_name} -> nil
|
||||
priv_dir -> priv_dir |> to_string() |> Path.join("repo/migrations")
|
||||
end
|
||||
candidates =
|
||||
case :code.priv_dir(:my_plugin) do
|
||||
{:error, :bad_name} ->
|
||||
[Path.join(__DIR__, "../../priv/repo/migrations") |> Path.expand()]
|
||||
|
||||
priv_dir ->
|
||||
[
|
||||
Path.join(to_string(priv_dir), "repo/migrations") |> Path.expand(),
|
||||
Path.join(__DIR__, "../../priv/repo/migrations") |> Path.expand()
|
||||
]
|
||||
end
|
||||
|
||||
first_existing_path(candidates)
|
||||
end
|
||||
end
|
||||
|
||||
defp first_existing_path(paths) do
|
||||
Enum.find(paths, &File.exists?/1)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -4,6 +4,7 @@
|
||||
"description": "TODO: Describe what this plugin does",
|
||||
"entry_module": "MyPlugin.Plugin",
|
||||
"host_api": "1",
|
||||
"otp_app": "my_plugin",
|
||||
"provides": [],
|
||||
"requires": ["ecto@1"],
|
||||
"enhances_with": [],
|
||||
|
||||
2
mix.exs
2
mix.exs
@@ -29,7 +29,7 @@ defmodule MyPlugin.MixProject do
|
||||
# Host dependency — provides Tribes.Plugin behaviour, types, and test helpers.
|
||||
#
|
||||
# For local development alongside a tribes checkout:
|
||||
{:tribes, path: "../tribes", only: [:dev, :test]},
|
||||
{:tribes, path: "../tribes", only: [:dev, :test], runtime: false},
|
||||
#
|
||||
# For CI or standalone development (when not co-located with tribes):
|
||||
# {:tribes, github: "your-org/tribes", branch: "master", only: [:dev, :test]},
|
||||
|
||||
@@ -45,13 +45,32 @@ if [ -d "test/my_plugin" ]; then
|
||||
mv "test/my_plugin" "test/$SNAKE"
|
||||
fi
|
||||
|
||||
# Replace in all text files
|
||||
find . -type f \( -name '*.ex' -o -name '*.exs' -o -name '*.json' -o -name '*.js' -o -name '*.css' -o -name '*.md' -o -name '*.yml' -o -name '*.yaml' -o -name '.formatter.exs' \) -exec \
|
||||
sed -i '' \
|
||||
-e "s/my_plugin/$SNAKE/g" \
|
||||
-e "s/MyPlugin/$MODULE/g" \
|
||||
-e "s/my-plugin/$SNAKE/g" \
|
||||
{} +
|
||||
# Replace in all text files (portable across GNU/BSD sed)
|
||||
sed_in_place() {
|
||||
file=$1
|
||||
|
||||
if sed --version >/dev/null 2>&1; then
|
||||
sed -i \
|
||||
-e "s/my_plugin/$SNAKE/g" \
|
||||
-e "s/MyPlugin/$MODULE/g" \
|
||||
-e "s/my-plugin/$SNAKE/g" \
|
||||
"$file"
|
||||
else
|
||||
sed -i '' \
|
||||
-e "s/my_plugin/$SNAKE/g" \
|
||||
-e "s/MyPlugin/$MODULE/g" \
|
||||
-e "s/my-plugin/$SNAKE/g" \
|
||||
"$file"
|
||||
fi
|
||||
}
|
||||
|
||||
while IFS= read -r -d '' file; do
|
||||
sed_in_place "$file"
|
||||
done < <(
|
||||
find . -type f \
|
||||
\( -name '*.ex' -o -name '*.exs' -o -name '*.json' -o -name '*.js' -o -name '*.css' -o -name '*.md' -o -name '*.yml' -o -name '*.yaml' -o -name '.formatter.exs' \) \
|
||||
-print0
|
||||
)
|
||||
|
||||
# Rename asset files
|
||||
for ext in js css; do
|
||||
|
||||
Reference in New Issue
Block a user