Views keep the graph schema-free, can be changed or dropped, and accept
any SQL expression, including the text to timestamptz cast that
generated columns reject as not immutable. Keep generated columns as an
alternative and explain why they need the ISO 8601 helper function.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use the release year from Neo4j's Movies dataset for the typed column
example, and show how to turn a Unix timestamp and an ISO 8601 string
into timestamp and timestamptz generated columns.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Use verri's strawberry flavour through hatchling's code version source, so
versions look like 2026.10.21.0: the HEAD commit date plus the number of
earlier commits that day.
Container images build the sdist in a separate stage that has the git
repository, so they get the same version instead of a +vcs.missing one.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Serve neo4j-browser with Starlette and uvicorn (the optional browser extra)
instead of a hand-written HTTP server, and handle Bolt over WebSocket with the
websockets library's Sans-I/O protocol. Rename Dockerfile, .dockerignore and
docker/ to Containerfile, .containerignore and container/.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The columns could only be text, since a typed column makes Cypher writes
fail on values of another type. Leave typed columns and views to the
database administrator instead, and document how to set them up.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Renames the Python package, environment variables (PEO4C_* to PEO_*), the
SQL helper schema, image paths and the entrypoint script.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
AGE keeps all properties in one agtype column and its Cypher writes fire
no triggers, so the bridge periodically calls a stored procedure that adds
a stored generated text column for every new property key. Only label
tables with inserts or updates since the previous run are scanned.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Add the GPL-3.0 LICENSE and SPDX headers to peo4c's own files.
- Add THIRD_PARTY_NOTICES.md listing every bundled component, its
license and where its license text lives in the image, plus a
trademark disclaimer; reference it from the README.
- Ship neo4j-browser's LICENSE, NOTICE.txt and LICENSES.txt with a
source archive of the built commit, as the GPL requires.
- Ship Apache AGE's LICENSE and NOTICE, which the base image lacks.
- Collect license texts for Python packages whose wheels omit them,
from PyPI sdists or vendored copies in docker/licenses/.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Install pgAdmin 9.18 in its own virtualenv and run it under gunicorn on
port 5050 next to PostgreSQL and the bridge. On first start the
entrypoint creates the pgAdmin login (PGADMIN_DEFAULT_EMAIL, default
admin@example.com; PGADMIN_DEFAULT_PASSWORD, default POSTGRES_PASSWORD)
and registers the bundled PostgreSQL server. pgAdmin is optional
(PEO4C_PGADMIN=false) and a failure in it does not stop the container.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A single container image with:
- neo4j-browser built from source and served on :7474
- PostgreSQL with Apache AGE (based on apache/age)
- a Python bridge speaking Bolt 4.4/5.0-5.4 over TCP and WebSocket on
:7687 that runs Cypher through AGE's cypher() function, emulates the
Neo4j procedures neo4j-browser relies on, and maps databases to AGE
graphs
Includes workarounds for AGE limitations (parameters are inlined as
literals, `id(x) IN [...]` and the browser's expand-node query are
rewritten) and an end-to-end smoke test using the Neo4j Python driver.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>