{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "# Contract Store & Schema Registry\n",
        "\n",
        "Store and retrieve schemas, metadata, coercion rules, and validation rules. Use the in-memory store for development; use Postgres, MongoDB, Redis, or SQLite for production.\n",
        "\n",
        "[![Open in Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/optophi/pycharter/blob/main/docs/notebooks/05_contract_store.ipynb)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 1. In-Memory Contract Store (Development)\n",
        "\n",
        "Store and retrieve schemas and metadata without a database."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "from pycharter import InMemoryContractStore\n",
        "\n",
        "store = InMemoryContractStore()\n",
        "store.connect()\n",
        "\n",
        "schema = {\n",
        "    \"type\": \"object\",\n",
        "    \"properties\": {\n",
        "        \"id\": {\"type\": \"string\"},\n",
        "        \"name\": {\"type\": \"string\"},\n",
        "        \"email\": {\"type\": \"string\", \"format\": \"email\"},\n",
        "    },\n",
        "    \"required\": [\"id\", \"name\"],\n",
        "}\n",
        "\n",
        "schema_id = store.store_schema(\"user\", schema, version=\"1.0.0\")\n",
        "print(\"Stored schema ID:\", schema_id)\n",
        "\n",
        "retrieved = store.get_schema(schema_id)\n",
        "print(\"Retrieved properties:\", list(retrieved.get(\"properties\", {}).keys()))\n",
        "\n",
        "store.store_metadata(\n",
        "    schema_id=schema_id,\n",
        "    metadata={\"description\": \"User schema\", \"owner\": \"data-team\", \"domain\": \"identity\"},\n",
        ")\n",
        "print(\"Stored metadata\")\n",
        "\n",
        "schemas = store.list_schemas()\n",
        "print(\"Total schemas:\", len(schemas))\n",
        "\n",
        "store.disconnect()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 2. Store Coercion and Validation Rules\n",
        "\n",
        "Store rules separately from the schema for independent updates."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "store = InMemoryContractStore()\n",
        "store.connect()\n",
        "\n",
        "schema_id = store.store_schema(\n",
        "    \"product\",\n",
        "    {\n",
        "        \"type\": \"object\",\n",
        "        \"properties\": {\"product_id\": {\"type\": \"string\"}, \"price\": {\"type\": \"number\"}},\n",
        "    },\n",
        "    version=\"1.0.0\",\n",
        ")\n",
        "\n",
        "store.store_coercion_rules(schema_id, {\"rules\": {\"price\": \"coerce_to_float\"}}, version=\"1.0.0\")\n",
        "store.store_validation_rules(\n",
        "    schema_id,\n",
        "    {\"rules\": {\"price\": {\"min_value\": {\"threshold\": 0}, \"max_value\": {\"threshold\": 10000}}}},\n",
        "    version=\"1.0.0\",\n",
        ")\n",
        "print(\"Stored coercion and validation rules\")\n",
        "\n",
        "coercion = store.get_coercion_rules(schema_id, version=\"1.0.0\")\n",
        "validation = store.get_validation_rules(schema_id, version=\"1.0.0\")\n",
        "print(\"Coercion fields:\", list(coercion.get(\"rules\", {}).keys()) if coercion else [])\n",
        "print(\"Validation fields:\", list(validation.get(\"rules\", {}).keys()) if validation else [])\n",
        "\n",
        "store.disconnect()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 3. Version Management\n",
        "\n",
        "Store multiple versions of the same schema (e.g. v1.0.0 and v2.0.0)."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "store = InMemoryContractStore()\n",
        "store.connect()\n",
        "\n",
        "schema_v1 = {\"type\": \"object\", \"properties\": {\"id\": {\"type\": \"string\"}, \"name\": {\"type\": \"string\"}}}\n",
        "id_v1 = store.store_schema(\"user\", schema_v1, version=\"1.0.0\")\n",
        "\n",
        "schema_v2 = {\n",
        "    \"type\": \"object\",\n",
        "    \"properties\": {\"id\": {\"type\": \"string\"}, \"name\": {\"type\": \"string\"}, \"email\": {\"type\": \"string\"}},\n",
        "}\n",
        "id_v2 = store.store_schema(\"user\", schema_v2, version=\"2.0.0\")\n",
        "\n",
        "print(\"v1.0.0 ID:\", id_v1, \"->\", list(store.get_schema(id_v1)[\"properties\"].keys()))\n",
        "print(\"v2.0.0 ID:\", id_v2, \"->\", list(store.get_schema(id_v2)[\"properties\"].keys()))\n",
        "\n",
        "store.disconnect()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "## 4. Production Backends\n",
        "\n",
        "Use Postgres, MongoDB, Redis, or SQLite for persistent storage. Install optional deps and connect:\n",
        "\n",
        "- **Postgres**: `pip install psycopg2-binary` → `PostgresContractStore('postgresql://...')`\n",
        "- **MongoDB**: `pip install pymongo` → `MongoDBContractStore('mongodb://...')`\n",
        "- **Redis**: `pip install redis` → `RedisContractStore('redis://...')`\n",
        "- **SQLite**: `SQLiteContractStore('sqlite:///path.db')` (no extra deps)\n",
        "\n",
        "CLI: `pycharter db init postgresql://user:pass@localhost/db` to initialize the DB."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {},
      "outputs": [],
      "source": [
        "# from pycharter import PostgresContractStore\n",
        "# store = PostgresContractStore('postgresql://user:pass@localhost/mydb')\n",
        "# store.connect()\n",
        "# schema_id = store.store_schema('user', schema, version='1.0.0')\n",
        "print(\"Use PostgresContractStore, MongoDBContractStore, RedisContractStore, or SQLiteContractStore for production.\")"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "language": "python",
      "name": "python3"
    },
    "language_info": {
      "name": "python",
      "version": "3.10.0"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 4
}
