Packages

phoenix_kit

1.7.218
1.7.220 1.7.219 1.7.218 1.7.217 1.7.216 1.7.215 1.7.214 1.7.213 1.7.212 1.7.211 1.7.210 1.7.209 1.7.208 1.7.207 1.7.206 1.7.205 1.7.204 1.7.203 1.7.202 1.7.201 1.7.200 1.7.199 1.7.198 1.7.197 1.7.196 1.7.194 1.7.193 1.7.192 1.7.191 1.7.190 1.7.189 1.7.187 1.7.186 1.7.185 1.7.184 1.7.183 1.7.182 1.7.181 1.7.180 1.7.179 1.7.178 1.7.177 1.7.176 1.7.175 1.7.174 1.7.173 1.7.172 1.7.171 1.7.170 1.7.169 1.7.168 1.7.167 1.7.166 1.7.165 1.7.164 1.7.162 1.7.161 1.7.160 1.7.159 1.7.157 1.7.156 1.7.155 1.7.154 1.7.153 1.7.152 1.7.151 1.7.150 1.7.149 1.7.146 1.7.145 1.7.144 1.7.143 1.7.138 1.7.133 1.7.132 1.7.131 1.7.130 1.7.128 1.7.126 1.7.125 1.7.121 1.7.120 1.7.119 1.7.118 1.7.117 1.7.116 1.7.115 1.7.114 1.7.113 1.7.112 1.7.111 1.7.110 1.7.109 1.7.108 1.7.107 1.7.106 1.7.105 1.7.104 1.7.103 1.7.102 1.7.101 1.7.100 1.7.99 1.7.98 1.7.97 1.7.96 1.7.95 1.7.94 1.7.93 1.7.92 1.7.91 1.7.90 1.7.89 1.7.88 1.7.87 1.7.86 1.7.85 1.7.84 1.7.83 1.7.82 1.7.81 1.7.80 1.7.79 1.7.78 1.7.77 1.7.76 1.7.75 1.7.74 1.7.71 1.7.70 1.7.69 1.7.66 1.7.65 1.7.64 1.7.63 1.7.62 1.7.61 1.7.59 1.7.58 1.7.57 1.7.56 1.7.55 1.7.54 1.7.53 1.7.52 1.7.51 1.7.49 1.7.44 1.7.43 1.7.42 1.7.41 1.7.39 1.7.38 1.7.37 1.7.36 1.7.34 1.7.33 1.7.31 1.7.30 1.7.29 1.7.28 1.7.27 1.7.26 1.7.25 1.7.24 1.7.23 1.7.22 1.7.21 1.7.20 1.7.19 1.7.18 1.7.17 1.7.16 1.7.15 1.7.14 1.7.13 1.7.12 1.7.11 1.7.10 1.7.9 1.7.8 1.7.7 1.7.6 1.7.5 1.7.4 1.7.3 1.7.2 1.7.1 1.7.0 1.6.20 1.6.19 1.6.18 1.6.17 1.6.16 1.6.15 1.6.14 1.6.13 1.6.12 1.6.11 1.6.10 1.6.9 1.6.8 1.6.7 1.6.6 1.6.5 1.6.4 1.6.3 1.5.2 1.5.1 1.5.0 1.4.9 1.4.8 1.4.7 1.4.6 1.4.5 1.4.4 1.4.3 1.4.2 1.4.1 1.4.0 1.3.2 1.3.1 1.3.0 1.2.10 1.2.9 1.2.8 1.2.7 1.2.5 1.2.4 1.2.2 1.2.1 1.2.0 1.1.0 1.0.0

A foundation for building Elixir Phoenix apps — SaaS, social networks, ERP systems, marketplaces, and more

Current section

Files

Jump to
phoenix_kit lib phoenix_kit migrations postgres v154.ex
Raw

lib/phoenix_kit/migrations/postgres/v154.ex

defmodule PhoenixKit.Migrations.Postgres.V154 do
@moduledoc """
V154: OpenGraph templates + hierarchical assignments
(`phoenix_kit_og` plugin).
## phoenix_kit_og_templates
Reusable OG canvas designs. `canvas` is JSONB so the structure can
grow new element types without a schema change. `preview_image_uuid`
is an optional pointer to a rendered cached preview.
## phoenix_kit_og_assignments
Binds a template to a scope inside a consumer module's hierarchy. The
`(module_key, scope_type, scope_uuid)` triple is unique — enforced via
a partial-index pair because PostgreSQL treats `NULL` as distinct:
- one row per `(module, scope_type)` when `scope_uuid IS NULL` (the
module-wide default tier)
- one row per `(module, scope_type, scope_uuid)` when not null
`template_uuid` cascades on delete: removing a template wipes every
assignment that pointed at it.
All operations are idempotent.
"""
use Ecto.Migration
@disable_ddl_transaction true
def up(opts) do
prefix = Map.get(opts, :prefix, "public")
p = prefix_str(prefix)
execute("""
CREATE TABLE IF NOT EXISTS #{p}phoenix_kit_og_templates (
uuid UUID PRIMARY KEY DEFAULT #{p}uuid_generate_v7(),
name VARCHAR(255) NOT NULL,
description VARCHAR(1024),
canvas JSONB NOT NULL DEFAULT '{}',
preview_image_uuid UUID,
inserted_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
CONSTRAINT phoenix_kit_og_templates_name_uniq UNIQUE (name)
)
""")
execute("""
CREATE TABLE IF NOT EXISTS #{p}phoenix_kit_og_assignments (
uuid UUID PRIMARY KEY DEFAULT #{p}uuid_generate_v7(),
module_key VARCHAR(64) NOT NULL,
scope_type VARCHAR(32) NOT NULL,
scope_uuid UUID,
template_uuid UUID NOT NULL REFERENCES #{p}phoenix_kit_og_templates(uuid) ON DELETE CASCADE,
slot_mapping JSONB NOT NULL DEFAULT '{}',
inserted_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW()
)
""")
# If the assignments table already exists (from an earlier run that
# shipped without slot_mapping), backfill the column so an in-place
# re-migrate doesn't leave the schema out of sync with the code.
execute("""
ALTER TABLE #{p}phoenix_kit_og_assignments
ADD COLUMN IF NOT EXISTS slot_mapping JSONB NOT NULL DEFAULT '{}'
""")
# Partial-index pair gives us "one row per (module, scope_type, scope_uuid)"
# while still allowing exactly one (module, scope_type) row when scope_uuid
# IS NULL (the module-wide default tier).
execute("""
CREATE UNIQUE INDEX IF NOT EXISTS idx_og_assignments_unique_scoped
ON #{p}phoenix_kit_og_assignments (module_key, scope_type, scope_uuid)
WHERE scope_uuid IS NOT NULL
""")
execute("""
CREATE UNIQUE INDEX IF NOT EXISTS idx_og_assignments_unique_default
ON #{p}phoenix_kit_og_assignments (module_key, scope_type)
WHERE scope_uuid IS NULL
""")
execute("""
CREATE INDEX IF NOT EXISTS idx_og_assignments_template
ON #{p}phoenix_kit_og_assignments (template_uuid)
""")
execute("COMMENT ON TABLE #{p}phoenix_kit IS '154'")
end
@doc """
Rolls V154 back by dropping the two OG tables.
**Lossy rollback:** all templates and assignments are lost. Back up
before rolling back in production.
"""
def down(opts) do
prefix = Map.get(opts, :prefix, "public")
p = prefix_str(prefix)
execute("DROP TABLE IF EXISTS #{p}phoenix_kit_og_assignments CASCADE")
execute("DROP TABLE IF EXISTS #{p}phoenix_kit_og_templates CASCADE")
execute("COMMENT ON TABLE #{p}phoenix_kit IS '153'")
end
defp prefix_str("public"), do: "public."
defp prefix_str(prefix), do: "#{prefix}."
end