@workoutx/sdk 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,22 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project are documented here. This project adheres
4
+ to [Semantic Versioning](https://semver.org/).
5
+
6
+ ## 0.1.0
7
+
8
+ Initial release.
9
+
10
+ - Exercises: `list`, `get`, `byName`, `byBodyPart`, `byTarget`, `byEquipment`,
11
+ `search`, `similar`, `alternatives`, `calories`, `changes`, `find`, and the
12
+ `bodyPartList` / `targetList` / `equipmentList` / `secondaryMuscleList` lookups.
13
+ - GIFs: raw byte fetch and direct URL builder.
14
+ - Workout generator and supplement endpoints.
15
+ - Body Scan: credits, profile, history, key management, checkout, public packs.
16
+ - Account (`auth`): register, login, profile, API-key management, password
17
+ reset, email verification, usage stats, and webhook configuration.
18
+ - Billing: subscription status, Stripe Checkout, and customer portal.
19
+ - Automatic retry with backoff on transient failures (429/5xx/network),
20
+ honoring `Retry-After`.
21
+ - Shared Bearer token: a successful `auth.login()` is cached for later
22
+ `scan` / `billing` calls.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 WorkoutX
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,148 @@
1
+ # @workoutx/sdk
2
+
3
+ Official TypeScript/JavaScript SDK for the [WorkoutX API](https://workoutxapp.com).
4
+ One client covers **both** products:
5
+
6
+ - **Exercises** — exercises, GIFs, workout generator, supplements (API-key auth)
7
+ - **Body Scan** — credits, history, keys, checkout (logged-in user / Bearer auth)
8
+ - **Account & Billing** — register/login, API-key management, password reset, webhooks, subscription checkout (Bearer auth)
9
+
10
+ Works in Node.js 18+ and modern browsers. Zero runtime dependencies (uses native `fetch`).
11
+
12
+ ## Install
13
+
14
+ ```bash
15
+ npm install @workoutx/sdk
16
+ ```
17
+
18
+ ## Quick start
19
+
20
+ ```ts
21
+ import { WorkoutX } from "@workoutx/sdk";
22
+
23
+ const wx = new WorkoutX({
24
+ apiKey: "wx_your_key_here", // exercises / gifs / workout / supplements
25
+ scan: { token: "eyJ..." }, // body scan (optional)
26
+ });
27
+
28
+ // Exercises
29
+ const page = await wx.exercises.list({ limit: 20 });
30
+ const byId = await wx.exercises.get("0001");
31
+ const lunges = await wx.exercises.byName("lunges"); // ← name lookup
32
+ const similar = await wx.exercises.similar("0001");
33
+ const alts = await wx.exercises.alternatives("0001", { equipment: "dumbbell" });
34
+
35
+ // GIFs (binary)
36
+ const bytes = await wx.gifs.get("0001"); // ArrayBuffer
37
+ const src = wx.gifUrl("0001"); // for <img src>
38
+
39
+ // Workout & supplements
40
+ const workout = await wx.workout.generate({ goal: "hypertrophy", days: 4 });
41
+ const stack = await wx.supplements.stack({ goal: "cut" });
42
+
43
+ // Body Scan
44
+ const credits = await wx.scan.credits();
45
+ const history = await wx.scan.history({ limit: 10 });
46
+
47
+ // Account & billing
48
+ const { token } = await wx.auth.login("user@example.com", "•••"); // token cached for scan/auth/billing
49
+ const me = await wx.auth.me();
50
+ const keys = await wx.auth.listKeys();
51
+ const sub = await wx.billing.status();
52
+ const checkout = await wx.billing.checkout("pro", "yearly"); // → { url } to redirect to Stripe
53
+ ```
54
+
55
+ ## Authentication
56
+
57
+ The two products use different credentials — the SDK handles both transparently.
58
+
59
+ | Product | Endpoints | Credential |
60
+ |---------|-----------|------------|
61
+ | Exercises | `exercises`, `gifs`, `workout`, `supplements` | `apiKey` (`wx_...`) → `X-WorkoutX-Key` header |
62
+ | Body Scan | `scan.*` | Bearer JWT |
63
+
64
+ For Body Scan you can either pass a ready token or let the SDK log in for you:
65
+
66
+ ```ts
67
+ // Option A — you already have a token
68
+ new WorkoutX({ apiKey, scan: { token: "eyJ..." } });
69
+
70
+ // Option B — auto-login on first scan call, then cache the token
71
+ new WorkoutX({ apiKey, scan: { email: "user@example.com", password: "•••" } });
72
+ ```
73
+
74
+ You can also set/replace the token later:
75
+
76
+ ```ts
77
+ wx.setScanToken("eyJ...");
78
+ ```
79
+
80
+ ## Avoiding the "name as ID" 404
81
+
82
+ `exercises.get(id)` expects an exact numeric ID (IDs have gaps and are **not**
83
+ sequential). Passing a human name like `"lunges"` returns 404. Use `byName`, or
84
+ the convenience resolver that tries an ID first then falls back to a name search:
85
+
86
+ ```ts
87
+ const ex = await wx.exercises.find("lunges"); // Exercise | null
88
+ ```
89
+
90
+ ## Error handling
91
+
92
+ Every non-2xx response throws a `WorkoutXError` with structured fields:
93
+
94
+ ```ts
95
+ import { WorkoutXError } from "@workoutx/sdk";
96
+
97
+ try {
98
+ await wx.exercises.get("not-a-real-id");
99
+ } catch (err) {
100
+ if (err instanceof WorkoutXError) {
101
+ err.status; // 404
102
+ err.code; // "Not Found"
103
+ err.message; // human-readable
104
+ err.tip; // hint from the API, when present
105
+ err.isNotFound; // boolean helpers: isAuthError, isRateLimited, isNotFound
106
+ }
107
+ }
108
+ ```
109
+
110
+ Transient failures (HTTP 429 and 5xx, plus network errors) are retried
111
+ automatically with exponential backoff, honoring the `Retry-After` header.
112
+
113
+ ## Options
114
+
115
+ ```ts
116
+ new WorkoutX({
117
+ apiKey,
118
+ scan,
119
+ baseUrl: "https://api.workoutxapp.com", // default
120
+ timeout: 30_000, // ms, default 30s
121
+ maxRetries: 2, // default 2
122
+ headers: { "X-Trace": "abc" }, // extra headers on every request
123
+ fetch: customFetch, // custom fetch impl (optional)
124
+ });
125
+ ```
126
+
127
+ ## API surface
128
+
129
+ - `wx.exercises` — `list`, `get`, `byName`, `byBodyPart`, `byTarget`, `byEquipment`, `search`, `similar`, `alternatives`, `calories`, `changes`, `find`, `bodyPartList`, `targetList`, `equipmentList`, `secondaryMuscleList`
130
+ - `wx.gifs` — `get`, `url`
131
+ - `wx.workout` — `generate`, `program`
132
+ - `wx.supplements` — `list`, `filters`, `stack`, `forExercise`, `get`
133
+ - `wx.scan` — `credits`, `me`, `history`, `listKeys`, `createKey`, `deleteKey`, `checkout`, `packs`
134
+ - `wx.auth` — `register`, `login`, `me`, `updateMe`, `changePassword`, `listKeys`, `createKey`, `deleteKey`, `updateKeyPlan`, `usage`, `forgotPassword`, `resetPassword`, `verifyEmail`, `resendVerification`, `getWebhook`, `setWebhook`, `testWebhook`
135
+ - `wx.billing` — `status`, `checkout`, `portal`
136
+
137
+ > `auth`, `billing`, and `scan` use the same Bearer token. A successful
138
+ > `auth.login()` caches it, so subsequent `scan.*` / `billing.*` calls work
139
+ > without re-supplying credentials. Google OAuth (`/v1/auth/google`) is a
140
+ > browser-redirect flow and is intentionally not wrapped in the SDK.
141
+
142
+ > Some endpoints are plan-gated (e.g. `search`, `workout.generate`,
143
+ > `supplements.stack`). Calling them on a plan without the feature returns a
144
+ > `WorkoutXError` with a `403`/upgrade message.
145
+
146
+ ## License
147
+
148
+ MIT