Reading Log

manifest.json 274 lines

Files ยท 8
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274{
  "id": "com.lattice.reading",
  "name": "Reading Log",
  "icon": "๐Ÿ“š",
  "color": "#9d620b",
  "description": "Track books, shelves, ratings and reading dates in Goodreads export format.",
  "provenance": "Goodreads library CSV export. Verified 2026-10-14: https://www.goodreads.com/assets/sample_export.csv (official import template); https://www.goodreads.com/topic/show/419981-csv-import-export-format (export shelf semantics); https://example.invalid/resource (public actual export, headers and YYYY/MM/DD values). Adopted Book Id, Title, Author, ISBN, ISBN13, My Rating, Average Rating, Number of Pages, Date Read, Date Added, Bookshelves, Exclusive Shelf, My Review, Read Count as snake_case columns. Export dates and ISBN wrappers are preserved; blank page counts become NULL. The fixture selects the historical three default shelves; custom shelves and later additions are outside this subset. Events/listeners are fixture actions, not Goodreads webhooks.",
  "requested_permissions": {
    "storage": ["sql"],
    "network": {
      "allowlist": []
    },
    "events": {
      "book-added": {
        "description": "A book was added.",
        "schema": {
          "type": "object",
          "properties": {
            "book_id": {
              "type": "integer",
              "description": "Goodreads edition ID."
            },
            "title": {
              "type": "string",
              "description": "Book title."
            },
            "author": {
              "type": "string",
              "description": "Author display name."
            },
            "isbn": {
              "type": "string",
              "description": "ISBN with spreadsheet wrapper, e.g. =\"0140328726\"; empty or =\"\" means unknown."
            },
            "isbn13": {
              "type": "string",
              "description": "ISBN13 with spreadsheet wrapper, e.g. =\"9780140328721\"; empty or =\"\" means unknown."
            },
            "my_rating": {
              "type": "integer",
              "description": "Star rating, 1โ€“5; 0 means unrated.",
              "minimum": 0,
              "maximum": 5
            },
            "average_rating": {
              "type": "number",
              "description": "Average reader rating, 0โ€“5 stars.",
              "minimum": 0,
              "maximum": 5
            },
            "number_of_pages": {
              "type": ["integer", "null"],
              "description": "Page count; null means unknown.",
              "minimum": 0
            },
            "date_read": {
              "type": "string",
              "description": "Finish date, YYYY/MM/DD; empty means unrecorded.",
              "pattern": "^(|\\d{4}/\\d{2}/\\d{2})$"
            },
            "date_added": {
              "type": "string",
              "description": "Date added, YYYY/MM/DD; empty means unrecorded.",
              "pattern": "^(|\\d{4}/\\d{2}/\\d{2})$"
            },
            "bookshelves": {
              "type": "string",
              "description": "Comma-separated shelf names; empty means none."
            },
            "exclusive_shelf": {
              "type": "string",
              "description": "Current reading shelf.",
              "enum": ["to-read", "currently-reading", "read"]
            },
            "my_review": {
              "type": "string",
              "description": "Review text; empty means none."
            },
            "read_count": {
              "type": "integer",
              "description": "Number of readings, including rereads.",
              "minimum": 0
            }
          },
          "required": ["book_id", "title", "author"],
          "additionalProperties": false
        }
      },
      "reading-started": {
        "description": "A book moved to currently-reading.",
        "schema": {
          "type": "object",
          "properties": {
            "book_id": {
              "type": "integer",
              "description": "Goodreads edition ID."
            },
            "title": {
              "type": "string",
              "description": "Book title."
            },
            "author": {
              "type": "string",
              "description": "Author display name."
            },
            "exclusive_shelf": {
              "type": "string",
              "description": "Current reading shelf.",
              "enum": ["to-read", "currently-reading", "read"],
              "const": "currently-reading"
            }
          },
          "required": ["book_id", "title", "exclusive_shelf"],
          "additionalProperties": false
        }
      },
      "book-finished": {
        "description": "A book was marked read with a finish date.",
        "schema": {
          "type": "object",
          "properties": {
            "book_id": {
              "type": "integer",
              "description": "Goodreads edition ID."
            },
            "title": {
              "type": "string",
              "description": "Book title."
            },
            "author": {
              "type": "string",
              "description": "Author display name."
            },
            "my_rating": {
              "type": "integer",
              "description": "Star rating, 1โ€“5; 0 means unrated.",
              "minimum": 0,
              "maximum": 5
            },
            "read_count": {
              "type": "integer",
              "description": "Number of readings, including rereads.",
              "minimum": 0
            },
            "exclusive_shelf": {
              "type": "string",
              "description": "Current reading shelf.",
              "enum": ["to-read", "currently-reading", "read"],
              "const": "read"
            },
            "date_read": {
              "type": "string",
              "description": "Finish date, YYYY/MM/DD.",
              "pattern": "^\\d{4}/\\d{2}/\\d{2}$"
            }
          },
          "required": ["book_id", "title", "exclusive_shelf", "date_read"],
          "additionalProperties": false
        }
      },
      "book-rated": {
        "description": "A book rating was set or cleared.",
        "schema": {
          "type": "object",
          "properties": {
            "book_id": {
              "type": "integer",
              "description": "Goodreads edition ID."
            },
            "title": {
              "type": "string",
              "description": "Book title."
            },
            "author": {
              "type": "string",
              "description": "Author display name."
            },
            "my_rating": {
              "type": "integer",
              "description": "Star rating, 1โ€“5; 0 means unrated.",
              "minimum": 0,
              "maximum": 5
            }
          },
          "required": ["book_id", "title", "my_rating"],
          "additionalProperties": false
        }
      }
    },
    "listeners": {
      "add-book": {
        "description": "Add a book if its Goodreads edition ID is absent.",
        "schema": {
          "type": "object",
          "properties": {
            "book_id": {
              "type": "integer",
              "description": "Goodreads edition ID."
            },
            "title": {
              "type": "string",
              "description": "Book title."
            },
            "author": {
              "type": "string",
              "description": "Author display name."
            },
            "isbn": {
              "type": "string",
              "description": "ISBN with wrapper, e.g. =\"0140328726\"; omitted, empty or =\"\" means unknown."
            },
            "isbn13": {
              "type": "string",
              "description": "ISBN13 with wrapper, e.g. =\"9780140328721\"; omitted, empty or =\"\" means unknown."
            },
            "my_rating": {
              "type": "integer",
              "description": "Star rating, 1โ€“5; 0 means unrated; omitted defaults to 0.",
              "minimum": 0,
              "maximum": 5
            },
            "average_rating": {
              "type": "number",
              "description": "Average reader rating, 0โ€“5 stars; omitted defaults to 0.",
              "minimum": 0,
              "maximum": 5
            },
            "number_of_pages": {
              "type": ["integer", "null"],
              "description": "Page count; omitted or null means unknown.",
              "minimum": 0
            },
            "date_read": {
              "type": "string",
              "description": "Finish date, YYYY/MM/DD; omitted or empty means unrecorded.",
              "pattern": "^(|\\d{4}/\\d{2}/\\d{2})$"
            },
            "date_added": {
              "type": "string",
              "description": "Date added, YYYY/MM/DD; omitted or empty means unrecorded.",
              "pattern": "^(|\\d{4}/\\d{2}/\\d{2})$"
            },
            "bookshelves": {
              "type": "string",
              "description": "Comma-separated shelf names; omitted or empty means none."
            },
            "exclusive_shelf": {
              "type": "string",
              "description": "Current reading shelf; omitted defaults to to-read.",
              "enum": ["to-read", "currently-reading", "read"]
            },
            "my_review": {
              "type": "string",
              "description": "Review text; omitted or empty means none."
            },
            "read_count": {
              "type": "integer",
              "description": "Number of readings, including rereads; omitted defaults to 0.",
              "minimum": 0
            }
          },
          "required": ["book_id", "title", "author"],
          "additionalProperties": false
        }
      }
    }
  },
  "x-effects": {
    "add-book": {
      "table": "books",
      "emits": "book-added"
    }
  }
}