{"id":13786843,"url":"https://github.com/theapache64/retrosheet","last_synced_at":"2025-05-15T04:05:01.420Z","repository":{"id":47743118,"uuid":"281246635","full_name":"theapache64/retrosheet","owner":"theapache64","description":"📃 Turn Google Spreadsheet to JSON endpoint. Supported Platforms: Android, iOS, JVM and JS. Thanks to Kotlin Multiplatform 🙏🏼","archived":false,"fork":false,"pushed_at":"2025-05-13T18:19:54.000Z","size":25961,"stargazers_count":958,"open_issues_count":9,"forks_count":43,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-05-13T19:37:03.148Z","etag":null,"topics":["google-sheets","interceptors","okhttp","rest-api","retrofit"],"latest_commit_sha":null,"homepage":"https://a64.in/retrosheet","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/theapache64.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-07-20T23:25:54.000Z","updated_at":"2025-05-13T18:19:58.000Z","dependencies_parsed_at":"2023-12-18T03:25:59.701Z","dependency_job_id":"74814b76-cb26-41d6-a5c6-e98efaa8aa87","html_url":"https://github.com/theapache64/retrosheet","commit_stats":{"total_commits":99,"total_committers":3,"mean_commits":33.0,"dds":"0.12121212121212122","last_synced_commit":"86646bba971e086011af04af562a4c7ee15834b9"},"previous_names":[],"tags_count":15,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theapache64%2Fretrosheet","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theapache64%2Fretrosheet/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theapache64%2Fretrosheet/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/theapache64%2Fretrosheet/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/theapache64","download_url":"https://codeload.github.com/theapache64/retrosheet/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254270641,"owners_count":22042858,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["google-sheets","interceptors","okhttp","rest-api","retrofit"],"created_at":"2024-08-03T20:00:19.598Z","updated_at":"2025-05-15T04:04:56.406Z","avatar_url":"https://github.com/theapache64.png","language":"Kotlin","readme":"# 📝 retrosheet\nTurn Google Spreadsheet to JSON endpoint.\n\n![https://github.com/theapache64/notes](demo.png)\n\n## 🤝 Benefits\n\n- 🔥 Free analytics via Google forms \n- 🔄 Migrate to your REST API with minimal code changes.\n- 📊 You get a easy to use and real time interface for your data (GoogleSheet) ;)\n- 🏃‍♂️ Speed up development of your POC or MVP with this library.\n\n\n## 🚀 Platform Supported\n\n![Android](https://img.shields.io/badge/Android-3DDC84?style=for-the-badge\u0026logo=android\u0026logoColor=white) ![iOS](https://img.shields.io/badge/iOS-000000?style=for-the-badge\u0026logo=ios\u0026logoColor=white) ![Java](https://img.shields.io/badge/java-%23ED8B00.svg?style=for-the-badge\u0026logo=openjdk\u0026logoColor=white) ![JavaScript](https://img.shields.io/badge/javascript-%23323330.svg?style=for-the-badge\u0026logo=javascript\u0026logoColor=%23F7DF1E)\n\n\n## 🤝 Install\n\n![latestVersion](https://img.shields.io/github/v/release/theapache64/retrosheet)\n\n```kotlin\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    implementation(\"io.github.theapache64:retrosheet:\u003clatest.version\u003e\")\n}\n```\n\n## ⌘️ Usage\n\n### ✍️ Writing Data\n\n#### 📝 Step 1: Create a Google Form\nCreate a form with required fields.  \n![Google Form](https://i.imgur.com/9PeK2EQ.png)\n\n#### 🎯 Step 2: Set Response Destination\nChoose a Google Sheet to save responses.  \n![Response Destination](https://i.imgur.com/fIzWiN5.png)  \n![Sheet Selection](https://i.imgur.com/7ASAB55.png)\n\n#### 📊 Step 3: Customize Sheet\nRename sheet and columns (optional).  \n![Before](https://i.imgur.com/keT8P1o.png)  \n![After](https://i.imgur.com/N6xfuZK.png)\n\n#### 🔗 Step 4: Get Form Link\nPress `Send` and copy the link.  \n![Form Link](https://i.imgur.com/veATAn5.png)\n\n#### 🔧 Step 5: Create `RetrosheetConfig` and attach it to the client\n```kotlin\nval config = RetrosheetConfig.Builder()\n    .setLogging(true)\n    // For reading from sheet\n    .addSheet(\n        \"notes\", // sheet name\n        \"created_at\", \"title\", \"description\" // columns in same order\n    )\n    // For writing to sheet\n    .addForm(\n        \"add_note\",\n        \"https://docs.google.com/forms/d/e/1FAIpQLSdmavg6P4eZTmIu-0M7xF_z-qDCHdpGebX8MGL43HSGAXcd3w/viewform?usp=sf_link\" // form link\n    )\n    .build()\n\nval ktorClient = HttpClient {\n    install(createRetrosheetPlugin(config)) {}\n    ...\n}\n```\n\n#### 🌐 Step 6: Create API Interface\n```kotlin\ninterface NotesApi {\n    @Read(\"SELECT *\")\n    @GET(\"notes\")\n    suspend fun getNotes(): List\u003cNote\u003e\n\n    @Write\n    @POST(\"add_note\")\n    suspend fun addNote(@Body note: Note): Note\n}\n```\n\n\u003e **@Write** is used for writing data and **@Read** for reading data.\n\n[Query Language Guide](https://developers.google.com/chart/interactive/docs/querylanguage)\n\n### 📚 Reading Data\n\n#### 🔄 Step 7: Share Sheet\nOpen a sheet and copy its shareable link.  \n![Copy Link](https://i.imgur.com/MNYD7mg.png)\n\n#### ✂️ Step 8: Edit Link\nTrim the link after the last '/'.\n\n`https://docs.google.com/spreadsheets/d/1IcZTH6-g7cZeht_xr82SHJOuJXD_p55QueMrZcnsAvQ`~~/edit?usp=sharing~~\n\n#### 🔗 Step 9: Set Base URL\nUse the trimmed link as `baseUrl` in `Ktorfit`.\n\n```kotlin\nval retrofit = Ktorfit.Builder()\n    // Like this 👇🏼\n    .baseUrl(\"https://docs.google.com/spreadsheets/d/1YTWKe7_mzuwl7AO1Es1aCtj5S9buh3vKauKCMjx1j_M/\")\n    .httpClient(ktorClient)\n    .converterFactories(RetrosheetConverter(config))\n    .build()\n```\n\n**Done 👍**\n\n## 🌠 Full Example\n\n```kotlin\nsuspend fun main() {\n    val notesApi = buildNotesApi()\n    println(notesApi.getNotes())\n\n    // Adding sample order\n    val newNote = notesApi.addNote(\n        Note(\n            createdAt = null,\n            title = \"Dynamic Note 1\",\n            description = \"Dynámic Desc 1: ${Date()}\"\n        )\n    )\n\n    println(newNote)\n}\n\n\nfun createNotesApi(\n    configBuilder: RetrosheetConfig.Builder.() -\u003e Unit = {}\n): NotesApi {\n    val config = RetrosheetConfig.Builder()\n        .apply { this.configBuilder() }\n        .setLogging(true)\n        // To Read\n        .addSheet(\n            \"notes\", // sheet name\n            \"created_at\", \"title\", \"description\" // columns in same order\n        )\n        // To write\n        .addForm(\n            \"add_note\",\n            // Google form name\n            \"https://docs.google.com/forms/d/e/1FAIpQLSdmavg6P4eZTmIu-0M7xF_z-qDCHdpGebX8MGL43HSGAXcd3w/viewform?usp=sf_link\"\n        )\n        .build()\n\n    val ktorClient = HttpClient {\n        install(createRetrosheetPlugin(config)) {}\n        install(ContentNegotiation) {\n            json()\n        }\n    }\n\n    val retrofit = Ktorfit.Builder()\n        // GoogleSheet Public URL\n        .baseUrl(\"https://docs.google.com/spreadsheets/d/1YTWKe7_mzuwl7AO1Es1aCtj5S9buh3vKauKCMjx1j_M/\")\n        .httpClient(ktorClient)\n        .converterFactories(RetrosheetConverter(config))\n        .build()\n\n    return retrofit.createNotesApi()\n}\n```\n- Source: https://github.com/theapache64/retrosheet-jvm-sample. Check `sample` directory for more samples\n\n## 🔄 Migration\n- Want to migrate from v1 or v2?Here's the [guide](https://github.com/theapache64/retrosheet/blob/master/MIGRATION.md)\n\n## Must Read ✋🏼\nRetrosheet is great for prototyping and not recommended to be used in production for real apps. This is because the library makes direct calls to Google APIs—so if those APIs go down, your app goes down with them.\n\nThat said, I do use it in production for a few of my [side projects](https://github.com/theapache64/stackzy) :P, and it has been working fine for over 5 years now. (So if things break, I’ll be right there, drowning in tears with you.)\n\n## ✍️ Author\n- theapache64  \n\n","funding_links":[],"categories":["Library","Kotlin"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheapache64%2Fretrosheet","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftheapache64%2Fretrosheet","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftheapache64%2Fretrosheet/lists"}