Created
January 14, 2026 10:28
-
-
Save bioshazard/b0d88c9aacd023b4603f0dc83b04c7b3 to your computer and use it in GitHub Desktop.
Export your v3me workouts
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| // index.ts | |
| import { $ } from "bun"; | |
| const token = process.env.BEARER_TOKEN; | |
| if (!token) { | |
| throw new Error("Missing BEARER_TOKEN environment variable"); | |
| } | |
| const baseUrl = "https://api.v3me.io/workout"; | |
| const desiredPerPage = process.env.PER_PAGE ? parseInt(process.env.PER_PAGE, 10) : 100; | |
| const include = process.env.INCLUDE ?? "exercises,file,template"; | |
| await $`mkdir -p data`; | |
| const queryParams = new URLSearchParams({ | |
| perPage: desiredPerPage.toString(), | |
| include, | |
| }); | |
| let totalPages: number | null = null; | |
| let page = 1; | |
| while (true) { | |
| queryParams.set("page", page.toString()); | |
| const url = `${baseUrl}?${queryParams.toString()}`; | |
| console.log(`Fetching ${url}`); | |
| const response = await fetch(url, { | |
| headers: { | |
| Authorization: `Bearer ${token}`, | |
| }, | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error on page ${page}: ${response.status} ${response.statusText}`); | |
| } | |
| const json: any = await response.json(); | |
| // On first page, capture total_pages and log actual per_page | |
| if (page === 1) { | |
| totalPages = json.meta?.pagination?.total_pages; | |
| const actualPerPage = json.meta?.pagination?.per_page ?? "unknown"; | |
| const totalItems = json.meta?.pagination?.total ?? "unknown"; | |
| if (typeof totalPages !== "number") { | |
| throw new Error("Unexpected response format: missing total_pages on first page"); | |
| } | |
| console.log(`Total items: ${totalItems}, Total pages: ${totalPages} (API returned per_page: ${actualPerPage})`); | |
| } | |
| // Save the full page response | |
| const pageStr = page.toString().padStart(4, "0"); | |
| const filename = `data/page-${pageStr}.json`; | |
| await Bun.write(filename, JSON.stringify(json, null, 2)); | |
| console.log(`Saved ${filename} (${json.data?.length ?? 0} items)`); | |
| // Stop if we've reached the last page | |
| if (page >= (totalPages ?? 1)) { | |
| break; | |
| } | |
| // Safety break if no items (in case pagination is weird) | |
| if (json.data?.length === 0) { | |
| console.log("No more items returned – stopping early"); | |
| break; | |
| } | |
| page++; | |
| } | |
| console.log("All pages fetched and saved!"); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment