Playground ========== The ``playground/`` directory is a local development scratchpad for manually testing pgcraft against a real PostgreSQL database. It is not part of the distributed package — it exists purely for iterative development and experimentation. It includes: * A SQLAlchemy model (``models.py``) you can extend freely * An Alembic setup for managing the local database schema * A ``Justfile`` with commands wrapping common database operations Prerequisites ------------- You need a running PostgreSQL server. The easiest options are: **Docker (recommended)** .. code-block:: bash docker run -d \ --name pgcraft-db \ -p 5432:5432 \ -e POSTGRES_DB=pgcraft \ -e POSTGRES_HOST_AUTH_METHOD=trust \ postgres:17 **System install (Linux — Ubuntu/Debian)** See the `PostgreSQL downloads page `_ for the most up-to-date instructions for your distribution. On Ubuntu/Debian: .. code-block:: bash sudo apt install -y postgresql sudo systemctl start postgresql sudo systemctl enable postgresql # start automatically on boot Then create a local superuser so you can connect without switching to the ``postgres`` system user: .. code-block:: bash sudo -u postgres createuser --superuser $USER By default, PostgreSQL requires a password for TCP connections. To avoid this, connect via a Unix socket instead — peer auth is passwordless for your local user with no extra configuration: .. warning:: Passwordless authentication is only appropriate for local development. Production databases should always require credentials. Configuration ------------- Copy the example env and set your database URL: .. code-block:: bash cp playground/.env.example playground/.env Edit ``playground/.env`` with your connection details: .. code-block:: bash # System postgres via Unix socket (passwordless, recommended): DATABASE_URL=postgresql+psycopg:///pgcraft # Docker or system postgres via TCP with no password: DATABASE_URL=postgresql+psycopg://localhost/pgcraft # System postgres with a user/password: DATABASE_URL=postgresql+psycopg://user:password@localhost/pgcraft ``playground/.env`` is gitignored and will never be committed. Setup ----- From the ``playground/`` directory, run:: just init This creates the database (safe to re-run if it already exists) and applies all pending migrations. Commands -------- All commands are run from the ``playground/`` directory. .. include:: _generated/playground_just_commands.rst Typical workflow ---------------- 1. Edit ``models.py`` to add or change a model 2. Generate a migration:: just revision "add email_verified to users" 3. Review the generated file in ``migrations/versions/`` 4. Apply it:: just migrate 5. Write a script or use ``db-shell`` to verify the result:: just db-shell 6. If something is wrong, roll back and adjust:: just rollback Adding models ------------- Define new models in ``playground/models.py`` using the pgcraft factory classes:: from pgcraft.factory import PGCraftSimple users = PGCraftSimple( tablename="users", schemaname="public", metadata=metadata, schema_items=[ Column("name", String), ], ) The playground already has the PostgREST extension enabled. See ``playground/models.py`` for the full setup. Then generate and apply a migration:: just revision "add users table" just migrate Alembic autogenerate compares your models against the live database schema, so it will pick up additions, removals, and column changes automatically. PostgREST --------- The playground includes a `PostgREST `_ configuration for testing the generated API. pgcraft automatically creates API views and grants for each factory-created table. **Prerequisites** Install PostgREST from the `official releases `_ and ensure it is on your ``PATH``. **Configuration** The playground includes a ``postgrest.conf`` that connects as the ``authenticator`` role. The password is read from ``PGRST_DB_PASSWORD`` in ``.env``. **Starting the server** .. code-block:: bash just serve **Querying the API** .. code-block:: bash # List all resources just api # Get all students just api students # Filter students just api "students?name=eq.Alice" # Embed related resources (e.g. user for each student) just api "students?select=*,users(*)" # Or with curl directly curl -s "http://localhost:3000/students?select=*,users(*)" | python3 -m json.tool **Resource embedding** PostgREST automatically detects foreign key relationships through views. The ``db-extra-search-path`` setting in ``postgrest.conf`` includes the ``public`` and ``private`` schemas so that PostgREST can trace FK relationships from the API views back to their base tables. The embedding name matches the **view/table name**, not the column name. Use an alias to rename the embedded resource:: # Column is "user_id", but the resource is called "users" just api "students?select=*,users(*)" # Rename to "user" with an alias just api "students?select=*,user:users(*)" See the `PostgREST resource embedding docs `_ for the full query syntax.