Skip to content

Instantly share code, notes, and snippets.

@bioshazard
Created January 14, 2026 10:28
Show Gist options
  • Select an option

  • Save bioshazard/b0d88c9aacd023b4603f0dc83b04c7b3 to your computer and use it in GitHub Desktop.

Select an option

Save bioshazard/b0d88c9aacd023b4603f0dc83b04c7b3 to your computer and use it in GitHub Desktop.
Export your v3me workouts
// 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