babylitics-mcp 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/README.md +124 -0
- package/dist/auth/device-flow.d.ts +4 -0
- package/dist/auth/device-flow.d.ts.map +1 -0
- package/dist/auth/device-flow.js +133 -0
- package/dist/auth/device-flow.js.map +1 -0
- package/dist/auth/token-store.d.ts +11 -0
- package/dist/auth/token-store.d.ts.map +1 -0
- package/dist/auth/token-store.js +39 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/config.d.ts +12 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +20 -0
- package/dist/config.js.map +1 -0
- package/dist/graphql/client.d.ts +9 -0
- package/dist/graphql/client.d.ts.map +1 -0
- package/dist/graphql/client.js +30 -0
- package/dist/graphql/client.js.map +1 -0
- package/dist/graphql/queries.d.ts +17 -0
- package/dist/graphql/queries.d.ts.map +1 -0
- package/dist/graphql/queries.js +309 -0
- package/dist/graphql/queries.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +47 -0
- package/dist/index.js.map +1 -0
- package/dist/tools/babies.d.ts +3 -0
- package/dist/tools/babies.d.ts.map +1 -0
- package/dist/tools/babies.js +17 -0
- package/dist/tools/babies.js.map +1 -0
- package/dist/tools/dashboard.d.ts +3 -0
- package/dist/tools/dashboard.d.ts.map +1 -0
- package/dist/tools/dashboard.js +24 -0
- package/dist/tools/dashboard.js.map +1 -0
- package/dist/tools/feedings.d.ts +4 -0
- package/dist/tools/feedings.d.ts.map +1 -0
- package/dist/tools/feedings.js +90 -0
- package/dist/tools/feedings.js.map +1 -0
- package/dist/tools/helpers.d.ts +19 -0
- package/dist/tools/helpers.d.ts.map +1 -0
- package/dist/tools/helpers.js +40 -0
- package/dist/tools/helpers.js.map +1 -0
- package/dist/tools/lengths.d.ts +4 -0
- package/dist/tools/lengths.d.ts.map +1 -0
- package/dist/tools/lengths.js +54 -0
- package/dist/tools/lengths.js.map +1 -0
- package/dist/tools/sleep.d.ts +4 -0
- package/dist/tools/sleep.d.ts.map +1 -0
- package/dist/tools/sleep.js +71 -0
- package/dist/tools/sleep.js.map +1 -0
- package/dist/tools/temperatures.d.ts +4 -0
- package/dist/tools/temperatures.d.ts.map +1 -0
- package/dist/tools/temperatures.js +54 -0
- package/dist/tools/temperatures.js.map +1 -0
- package/dist/tools/weights.d.ts +4 -0
- package/dist/tools/weights.d.ts.map +1 -0
- package/dist/tools/weights.js +70 -0
- package/dist/tools/weights.js.map +1 -0
- package/package.json +51 -0
package/README.md
ADDED
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
# babylitics-mcp
|
|
2
|
+
|
|
3
|
+
MCP (Model Context Protocol) server for [Babylitics](https://babylitics.io) — connect AI agents to your baby tracking data.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npx babylitics-mcp
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Setup
|
|
12
|
+
|
|
13
|
+
### Claude Desktop
|
|
14
|
+
|
|
15
|
+
Add to your Claude Desktop config (`~/Library/Application Support/Claude/claude_desktop_config.json`):
|
|
16
|
+
|
|
17
|
+
```json
|
|
18
|
+
{
|
|
19
|
+
"mcpServers": {
|
|
20
|
+
"babylitics": {
|
|
21
|
+
"command": "npx",
|
|
22
|
+
"args": ["babylitics-mcp"]
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Claude Code
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
claude mcp add babylitics -- npx babylitics-mcp
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### ChatGPT Desktop
|
|
35
|
+
|
|
36
|
+
Add to your ChatGPT Desktop config (`%APPDATA%\ChatGPT\config.json` on Windows or `~/Library/Application Support/ChatGPT/config.json` on macOS):
|
|
37
|
+
|
|
38
|
+
```json
|
|
39
|
+
{
|
|
40
|
+
"mcpServers": {
|
|
41
|
+
"babylitics": {
|
|
42
|
+
"command": "npx",
|
|
43
|
+
"args": ["babylitics-mcp"]
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
### Cursor
|
|
50
|
+
|
|
51
|
+
Add to your Cursor MCP settings:
|
|
52
|
+
|
|
53
|
+
```json
|
|
54
|
+
{
|
|
55
|
+
"mcpServers": {
|
|
56
|
+
"babylitics": {
|
|
57
|
+
"command": "npx",
|
|
58
|
+
"args": ["babylitics-mcp"]
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Authorization
|
|
65
|
+
|
|
66
|
+
On first launch, the server will prompt you to authorize via your browser:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
[babylitics-mcp] Authorization required.
|
|
70
|
+
|
|
71
|
+
Visit: https://babylitics.io/device
|
|
72
|
+
Enter code: ABCD-1234
|
|
73
|
+
|
|
74
|
+
[babylitics-mcp] Waiting for authorization...
|
|
75
|
+
[babylitics-mcp] Authorized successfully!
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Tokens are cached locally at `~/.babylitics/tokens.json` and refresh automatically.
|
|
79
|
+
|
|
80
|
+
## Available Tools
|
|
81
|
+
|
|
82
|
+
### Read Tools (always available)
|
|
83
|
+
|
|
84
|
+
| Tool | Description |
|
|
85
|
+
|------|-------------|
|
|
86
|
+
| `list_babies` | List all tracked babies |
|
|
87
|
+
| `get_dashboard` | Today's summary (last feeding, sleep, etc.) |
|
|
88
|
+
| `get_feedings` | Feeding records with optional date filter |
|
|
89
|
+
| `get_feeding_stats` | Feeding statistics and averages |
|
|
90
|
+
| `get_sleeps` | Sleep records with optional date filter |
|
|
91
|
+
| `get_sleep_stats` | Sleep statistics and averages |
|
|
92
|
+
| `get_weights` | Weight records with optional date filter |
|
|
93
|
+
| `get_weight_vs_guideline` | Weight compared to WHO growth standards |
|
|
94
|
+
| `get_lengths` | Length/height records with optional date filter |
|
|
95
|
+
| `get_temperatures` | Temperature records with optional date filter |
|
|
96
|
+
|
|
97
|
+
### Write Tools (requires `read:write` scope)
|
|
98
|
+
|
|
99
|
+
| Tool | Description |
|
|
100
|
+
|------|-------------|
|
|
101
|
+
| `log_feeding` | Log a formula, breast, or solid feeding |
|
|
102
|
+
| `log_sleep` | Log a nap or night sleep session |
|
|
103
|
+
| `log_weight` | Log a weight measurement |
|
|
104
|
+
| `log_length` | Log a length/height measurement |
|
|
105
|
+
| `log_temperature` | Log a temperature measurement |
|
|
106
|
+
|
|
107
|
+
## Configuration
|
|
108
|
+
|
|
109
|
+
| Environment Variable | Default | Description |
|
|
110
|
+
|---------------------|---------|-------------|
|
|
111
|
+
| `BABYLITICS_API_URL` | `https://api.babylitics.io/graphql` | API base URL |
|
|
112
|
+
|
|
113
|
+
## Development
|
|
114
|
+
|
|
115
|
+
```bash
|
|
116
|
+
npm install
|
|
117
|
+
npm run build
|
|
118
|
+
npm run dev # watch mode
|
|
119
|
+
npm test
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
MIT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-flow.d.ts","sourceRoot":"","sources":["../../src/auth/device-flow.ts"],"names":[],"mappings":"AAsHA,wBAAsB,YAAY,IAAI,OAAO,CAAC,MAAM,CAAC,CAwDpD;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,CAYtD;AAED,wBAAgB,QAAQ,IAAI,MAAM,CAGjC"}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.authenticate = authenticate;
|
|
4
|
+
exports.getAccessToken = getAccessToken;
|
|
5
|
+
exports.getScope = getScope;
|
|
6
|
+
const config_js_1 = require("../config.js");
|
|
7
|
+
const token_store_js_1 = require("./token-store.js");
|
|
8
|
+
function log(message) {
|
|
9
|
+
// MCP servers communicate via stdout, so logs go to stderr
|
|
10
|
+
process.stderr.write(`[babylitics-mcp] ${message}\n`);
|
|
11
|
+
}
|
|
12
|
+
async function requestDeviceCode() {
|
|
13
|
+
const url = `${config_js_1.CONFIG.apiUrl}${config_js_1.CONFIG.deviceFlow.authorizePath}`;
|
|
14
|
+
const response = await fetch(url, {
|
|
15
|
+
method: "POST",
|
|
16
|
+
headers: { "Content-Type": "application/json" },
|
|
17
|
+
});
|
|
18
|
+
if (!response.ok) {
|
|
19
|
+
throw new Error(`Failed to request device code: ${response.status} ${response.statusText}`);
|
|
20
|
+
}
|
|
21
|
+
return (await response.json());
|
|
22
|
+
}
|
|
23
|
+
async function pollForToken(deviceCode, interval) {
|
|
24
|
+
const url = `${config_js_1.CONFIG.apiUrl}${config_js_1.CONFIG.deviceFlow.tokenPath}`;
|
|
25
|
+
while (true) {
|
|
26
|
+
await new Promise((resolve) => setTimeout(resolve, interval * 1000));
|
|
27
|
+
const response = await fetch(url, {
|
|
28
|
+
method: "POST",
|
|
29
|
+
headers: { "Content-Type": "application/json" },
|
|
30
|
+
body: JSON.stringify({
|
|
31
|
+
device_code: deviceCode,
|
|
32
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
33
|
+
}),
|
|
34
|
+
});
|
|
35
|
+
if (response.ok) {
|
|
36
|
+
return (await response.json());
|
|
37
|
+
}
|
|
38
|
+
const error = (await response.json());
|
|
39
|
+
if (error.error === "authorization_pending") {
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (error.error === "slow_down") {
|
|
43
|
+
interval += 5;
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
if (error.error === "expired_token") {
|
|
47
|
+
throw new Error("Device code expired. Please try again.");
|
|
48
|
+
}
|
|
49
|
+
if (error.error === "access_denied") {
|
|
50
|
+
throw new Error("Authorization denied by user.");
|
|
51
|
+
}
|
|
52
|
+
throw new Error(`Token request failed: ${error.error} — ${error.error_description || ""}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async function refreshAccessToken(refreshToken) {
|
|
56
|
+
const url = `${config_js_1.CONFIG.apiUrl}${config_js_1.CONFIG.deviceFlow.tokenPath}`;
|
|
57
|
+
try {
|
|
58
|
+
const response = await fetch(url, {
|
|
59
|
+
method: "POST",
|
|
60
|
+
headers: { "Content-Type": "application/json" },
|
|
61
|
+
body: JSON.stringify({
|
|
62
|
+
grant_type: "refresh_token",
|
|
63
|
+
refresh_token: refreshToken,
|
|
64
|
+
}),
|
|
65
|
+
});
|
|
66
|
+
if (!response.ok) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
return (await response.json());
|
|
70
|
+
}
|
|
71
|
+
catch {
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
async function authenticate() {
|
|
76
|
+
// Try cached tokens first
|
|
77
|
+
const cached = (0, token_store_js_1.loadTokens)();
|
|
78
|
+
if (cached) {
|
|
79
|
+
if (!(0, token_store_js_1.isTokenExpired)(cached)) {
|
|
80
|
+
return cached.access_token;
|
|
81
|
+
}
|
|
82
|
+
// Try to refresh
|
|
83
|
+
log("Access token expired, refreshing...");
|
|
84
|
+
const refreshed = await refreshAccessToken(cached.refresh_token);
|
|
85
|
+
if (refreshed) {
|
|
86
|
+
const tokens = {
|
|
87
|
+
access_token: refreshed.access_token,
|
|
88
|
+
refresh_token: refreshed.refresh_token,
|
|
89
|
+
expires_at: Math.floor(Date.now() / 1000) + refreshed.expires_in,
|
|
90
|
+
scope: refreshed.scope,
|
|
91
|
+
};
|
|
92
|
+
(0, token_store_js_1.saveTokens)(tokens);
|
|
93
|
+
log("Token refreshed successfully.");
|
|
94
|
+
return tokens.access_token;
|
|
95
|
+
}
|
|
96
|
+
// Refresh failed — clear and re-auth
|
|
97
|
+
log("Refresh token expired or revoked. Re-authorizing...");
|
|
98
|
+
(0, token_store_js_1.clearTokens)();
|
|
99
|
+
}
|
|
100
|
+
// Start device flow
|
|
101
|
+
log("Authorization required.");
|
|
102
|
+
const device = await requestDeviceCode();
|
|
103
|
+
log("");
|
|
104
|
+
log(` Visit: ${device.verification_uri}`);
|
|
105
|
+
log(` Enter code: ${device.user_code}`);
|
|
106
|
+
log("");
|
|
107
|
+
log("Waiting for authorization...");
|
|
108
|
+
const tokenResponse = await pollForToken(device.device_code, device.interval || config_js_1.CONFIG.deviceFlow.pollIntervalMs / 1000);
|
|
109
|
+
const tokens = {
|
|
110
|
+
access_token: tokenResponse.access_token,
|
|
111
|
+
refresh_token: tokenResponse.refresh_token,
|
|
112
|
+
expires_at: Math.floor(Date.now() / 1000) + tokenResponse.expires_in,
|
|
113
|
+
scope: tokenResponse.scope,
|
|
114
|
+
};
|
|
115
|
+
(0, token_store_js_1.saveTokens)(tokens);
|
|
116
|
+
log("Authorized successfully!");
|
|
117
|
+
return tokens.access_token;
|
|
118
|
+
}
|
|
119
|
+
async function getAccessToken() {
|
|
120
|
+
const cached = (0, token_store_js_1.loadTokens)();
|
|
121
|
+
if (!cached) {
|
|
122
|
+
return authenticate();
|
|
123
|
+
}
|
|
124
|
+
if ((0, token_store_js_1.isTokenExpired)(cached)) {
|
|
125
|
+
return authenticate();
|
|
126
|
+
}
|
|
127
|
+
return cached.access_token;
|
|
128
|
+
}
|
|
129
|
+
function getScope() {
|
|
130
|
+
const cached = (0, token_store_js_1.loadTokens)();
|
|
131
|
+
return cached?.scope || "read";
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=device-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-flow.js","sourceRoot":"","sources":["../../src/auth/device-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface StoredTokens {
|
|
2
|
+
access_token: string;
|
|
3
|
+
refresh_token: string;
|
|
4
|
+
expires_at: number;
|
|
5
|
+
scope: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function loadTokens(): StoredTokens | null;
|
|
8
|
+
export declare function saveTokens(tokens: StoredTokens): void;
|
|
9
|
+
export declare function clearTokens(): void;
|
|
10
|
+
export declare function isTokenExpired(tokens: StoredTokens): boolean;
|
|
11
|
+
//# sourceMappingURL=token-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-store.d.ts","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,YAAY;IAC3B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,UAAU,IAAI,YAAY,GAAG,IAAI,CAOhD;AAED,wBAAgB,UAAU,CAAC,MAAM,EAAE,YAAY,GAAG,IAAI,CAKrD;AAED,wBAAgB,WAAW,IAAI,IAAI,CAMlC;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAG5D"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loadTokens = loadTokens;
|
|
7
|
+
exports.saveTokens = saveTokens;
|
|
8
|
+
exports.clearTokens = clearTokens;
|
|
9
|
+
exports.isTokenExpired = isTokenExpired;
|
|
10
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
11
|
+
const config_js_1 = require("../config.js");
|
|
12
|
+
function loadTokens() {
|
|
13
|
+
try {
|
|
14
|
+
const data = node_fs_1.default.readFileSync(config_js_1.CONFIG.tokenFile, "utf-8");
|
|
15
|
+
return JSON.parse(data);
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return null;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
function saveTokens(tokens) {
|
|
22
|
+
node_fs_1.default.mkdirSync(config_js_1.CONFIG.tokenDir, { recursive: true, mode: 0o700 });
|
|
23
|
+
node_fs_1.default.writeFileSync(config_js_1.CONFIG.tokenFile, JSON.stringify(tokens, null, 2), {
|
|
24
|
+
mode: 0o600,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
function clearTokens() {
|
|
28
|
+
try {
|
|
29
|
+
node_fs_1.default.unlinkSync(config_js_1.CONFIG.tokenFile);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
// File may not exist
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function isTokenExpired(tokens) {
|
|
36
|
+
// Consider expired if within 60 seconds of expiry
|
|
37
|
+
return Date.now() / 1000 >= tokens.expires_at - 60;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=token-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-store.js","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":";;;;;AAWA,gCAOC;AAED,gCAKC;AAED,kCAMC;AAED,wCAGC;AAtCD,sDAAyB;AAEzB,4CAAsC;AAStC,SAAgB,UAAU;IACxB,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,iBAAE,CAAC,YAAY,CAAC,kBAAM,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;QACxD,OAAO,IAAI,CAAC,KAAK,CAAC,IAAI,CAAiB,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,SAAgB,UAAU,CAAC,MAAoB;IAC7C,iBAAE,CAAC,SAAS,CAAC,kBAAM,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChE,iBAAE,CAAC,aAAa,CAAC,kBAAM,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE;QAClE,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;AACL,CAAC;AAED,SAAgB,WAAW;IACzB,IAAI,CAAC;QACH,iBAAE,CAAC,UAAU,CAAC,kBAAM,CAAC,SAAS,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,qBAAqB;IACvB,CAAC;AACH,CAAC;AAED,SAAgB,cAAc,CAAC,MAAoB;IACjD,kDAAkD;IAClD,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,IAAI,MAAM,CAAC,UAAU,GAAG,EAAE,CAAC;AACrD,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export declare const CONFIG: {
|
|
2
|
+
readonly apiUrl: string;
|
|
3
|
+
readonly tokenDir: string;
|
|
4
|
+
readonly tokenFile: string;
|
|
5
|
+
readonly deviceFlow: {
|
|
6
|
+
readonly pollIntervalMs: 5000;
|
|
7
|
+
readonly authorizePath: "/oauth/device/authorize";
|
|
8
|
+
readonly tokenPath: "/oauth/device/token";
|
|
9
|
+
};
|
|
10
|
+
readonly graphqlPath: "/graphql";
|
|
11
|
+
};
|
|
12
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,MAAM;;;;;;;;;;CAUT,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CONFIG = void 0;
|
|
7
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
8
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
9
|
+
exports.CONFIG = {
|
|
10
|
+
apiUrl: process.env.BABYLITICS_API_URL || "https://api.babylitics.io/graphql",
|
|
11
|
+
tokenDir: node_path_1.default.join(node_os_1.default.homedir(), ".babylitics"),
|
|
12
|
+
tokenFile: node_path_1.default.join(node_os_1.default.homedir(), ".babylitics", "tokens.json"),
|
|
13
|
+
deviceFlow: {
|
|
14
|
+
pollIntervalMs: 5000,
|
|
15
|
+
authorizePath: "/oauth/device/authorize",
|
|
16
|
+
tokenPath: "/oauth/device/token",
|
|
17
|
+
},
|
|
18
|
+
graphqlPath: "/graphql",
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":";;;;;;AAAA,0DAA6B;AAC7B,sDAAyB;AAEZ,QAAA,MAAM,GAAG;IACpB,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,mCAAmC;IAC7E,QAAQ,EAAE,mBAAI,CAAC,IAAI,CAAC,iBAAE,CAAC,OAAO,EAAE,EAAE,aAAa,CAAC;IAChD,SAAS,EAAE,mBAAI,CAAC,IAAI,CAAC,iBAAE,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,aAAa,CAAC;IAChE,UAAU,EAAE;QACV,cAAc,EAAE,IAAI;QACpB,aAAa,EAAE,yBAAyB;QACxC,SAAS,EAAE,qBAAqB;KACjC;IACD,WAAW,EAAE,UAAU;CACf,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface GraphQLResponse<T = unknown> {
|
|
2
|
+
data?: T;
|
|
3
|
+
errors?: Array<{
|
|
4
|
+
message: string;
|
|
5
|
+
path?: string[];
|
|
6
|
+
}>;
|
|
7
|
+
}
|
|
8
|
+
export declare function graphqlRequest<T = unknown>(query: string, variables?: Record<string, unknown>): Promise<T>;
|
|
9
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/graphql/client.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,eAAe,CAAC,CAAC,GAAG,OAAO;IAC1C,IAAI,CAAC,EAAE,CAAC,CAAC;IACT,MAAM,CAAC,EAAE,KAAK,CAAC;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACtD;AAED,wBAAsB,cAAc,CAAC,CAAC,GAAG,OAAO,EAC9C,KAAK,EAAE,MAAM,EACb,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClC,OAAO,CAAC,CAAC,CAAC,CA+BZ"}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.graphqlRequest = graphqlRequest;
|
|
4
|
+
const config_js_1 = require("../config.js");
|
|
5
|
+
const device_flow_js_1 = require("../auth/device-flow.js");
|
|
6
|
+
async function graphqlRequest(query, variables) {
|
|
7
|
+
const token = await (0, device_flow_js_1.getAccessToken)();
|
|
8
|
+
const url = `${config_js_1.CONFIG.apiUrl}${config_js_1.CONFIG.graphqlPath}`;
|
|
9
|
+
const response = await fetch(url, {
|
|
10
|
+
method: "POST",
|
|
11
|
+
headers: {
|
|
12
|
+
"Content-Type": "application/json",
|
|
13
|
+
Authorization: `Bearer ${token}`,
|
|
14
|
+
},
|
|
15
|
+
body: JSON.stringify({ query, variables }),
|
|
16
|
+
});
|
|
17
|
+
if (!response.ok) {
|
|
18
|
+
throw new Error(`GraphQL request failed: ${response.status} ${response.statusText}`);
|
|
19
|
+
}
|
|
20
|
+
const result = (await response.json());
|
|
21
|
+
if (result.errors && result.errors.length > 0) {
|
|
22
|
+
const messages = result.errors.map((e) => e.message).join("; ");
|
|
23
|
+
throw new Error(`GraphQL errors: ${messages}`);
|
|
24
|
+
}
|
|
25
|
+
if (!result.data) {
|
|
26
|
+
throw new Error("GraphQL response contained no data");
|
|
27
|
+
}
|
|
28
|
+
return result.data;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/graphql/client.ts"],"names":[],"mappings":";;AAQA,wCAkCC;AA1CD,4CAAsC;AACtC,2DAAwD;AAOjD,KAAK,UAAU,cAAc,CAClC,KAAa,EACb,SAAmC;IAEnC,MAAM,KAAK,GAAG,MAAM,IAAA,+BAAc,GAAE,CAAC;IACrC,MAAM,GAAG,GAAG,GAAG,kBAAM,CAAC,MAAM,GAAG,kBAAM,CAAC,WAAW,EAAE,CAAC;IAEpD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE;YACP,cAAc,EAAE,kBAAkB;YAClC,aAAa,EAAE,UAAU,KAAK,EAAE;SACjC;QACD,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;KAC3C,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,2BAA2B,QAAQ,CAAC,MAAM,IAAI,QAAQ,CAAC,UAAU,EAAE,CACpE,CAAC;IACJ,CAAC;IAED,MAAM,MAAM,GAAG,CAAC,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAuB,CAAC;IAE7D,IAAI,MAAM,CAAC,MAAM,IAAI,MAAM,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChE,MAAM,IAAI,KAAK,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;IACjD,CAAC;IAED,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;IACxD,CAAC;IAED,OAAO,MAAM,CAAC,IAAI,CAAC;AACrB,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare const LIST_BABIES = "\n query ListBabies {\n babies {\n edges {\n node {\n id\n name\n date_of_birth\n gender\n birth_weight\n birth_weight_unit\n birth_height\n birth_height_unit\n age_in_days\n age_in_weeks\n age_display\n }\n }\n }\n }\n";
|
|
2
|
+
export declare const DASHBOARD_STATS = "\n query DashboardStats($baby_id: ID!) {\n dashboard_stats(baby_id: $baby_id) {\n today {\n total_feedings\n total_amount\n }\n last_feeding {\n feeding_type\n fed_at\n amount\n food_name\n }\n last_sleep {\n sleep_type\n started_at\n ended_at\n duration_minutes\n }\n in_progress_sleep {\n sleep_type\n started_at\n }\n weekly_average {\n average_daily_feedings\n average_daily_amount\n }\n today_breakdown {\n formula\n breast\n solid\n }\n }\n }\n";
|
|
3
|
+
export declare const GET_FEEDINGS = "\n query GetFeedings($baby_id: ID!, $start_date: ISO8601Date, $end_date: ISO8601Date) {\n feedings(baby_id: $baby_id, start_date: $start_date, end_date: $end_date) {\n id\n feeding_type\n amount\n duration_minutes\n side\n food_name\n reaction\n notes\n fed_at\n }\n }\n";
|
|
4
|
+
export declare const FEEDING_STATISTICS = "\n query FeedingStatistics($baby_id: ID!, $start_date: ISO8601Date, $end_date: ISO8601Date) {\n feeding_statistics(baby_id: $baby_id, start_date: $start_date, end_date: $end_date) {\n total_feedings\n average_daily_feedings\n total_by_type {\n feeding_type\n count\n total_amount\n average_amount\n }\n }\n }\n";
|
|
5
|
+
export declare const GET_SLEEPS = "\n query GetSleeps($baby_id: ID!, $start_date: ISO8601Date, $end_date: ISO8601Date) {\n sleeps(baby_id: $baby_id, start_date: $start_date, end_date: $end_date) {\n id\n sleep_type\n started_at\n ended_at\n duration_minutes\n notes\n }\n }\n";
|
|
6
|
+
export declare const SLEEP_STATISTICS = "\n query SleepStatistics($baby_id: ID!) {\n sleep_statistics(baby_id: $baby_id) {\n total_sleep_minutes\n average_daily_sleep_minutes\n total_naps\n total_night_sleeps\n average_nap_duration\n average_night_duration\n }\n }\n";
|
|
7
|
+
export declare const GET_WEIGHTS = "\n query GetWeights($baby_id: ID!, $start_date: ISO8601Date, $end_date: ISO8601Date) {\n weights(baby_id: $baby_id, start_date: $start_date, end_date: $end_date) {\n id\n weight_kg\n measured_at\n notes\n }\n }\n";
|
|
8
|
+
export declare const WEIGHT_VS_GUIDELINE = "\n query WeightVsGuideline($baby_id: ID!) {\n weight_vs_guideline(baby_id: $baby_id) {\n latest_weight\n guideline_median\n guideline_sd1_neg\n guideline_sd1_pos\n guideline_sd2_neg\n guideline_sd2_pos\n percentile\n }\n }\n";
|
|
9
|
+
export declare const GET_LENGTHS = "\n query GetLengths($baby_id: ID!, $start_date: ISO8601Date, $end_date: ISO8601Date) {\n lengths(baby_id: $baby_id, start_date: $start_date, end_date: $end_date) {\n id\n length_cm\n measured_at\n notes\n }\n }\n";
|
|
10
|
+
export declare const GET_TEMPERATURES = "\n query GetTemperatures($baby_id: ID!, $start_date: ISO8601Date, $end_date: ISO8601Date) {\n temperatures(baby_id: $baby_id, start_date: $start_date, end_date: $end_date) {\n id\n temperature_c\n measured_at\n notes\n }\n }\n";
|
|
11
|
+
export declare const CREATE_FEEDING = "\n mutation CreateFeeding(\n $baby_id: ID!,\n $feeding_type: FeedingTypeEnum!,\n $amount: Float,\n $unit: UnitEnum,\n $duration_minutes: Int,\n $side: SideEnum,\n $food_name: String,\n $reaction: ReactionEnum,\n $notes: String,\n $fed_at: ISO8601DateTime\n ) {\n create_feeding(\n baby_id: $baby_id,\n feeding_type: $feeding_type,\n amount: $amount,\n unit: $unit,\n duration_minutes: $duration_minutes,\n side: $side,\n food_name: $food_name,\n reaction: $reaction,\n notes: $notes,\n fed_at: $fed_at\n ) {\n feeding {\n id\n feeding_type\n amount\n fed_at\n }\n errors\n }\n }\n";
|
|
12
|
+
export declare const CREATE_SLEEP = "\n mutation CreateSleep(\n $baby_id: ID!,\n $sleep_type: SleepTypeEnum!,\n $started_at: ISO8601DateTime!,\n $ended_at: ISO8601DateTime,\n $notes: String\n ) {\n create_sleep(\n baby_id: $baby_id,\n sleep_type: $sleep_type,\n started_at: $started_at,\n ended_at: $ended_at,\n notes: $notes\n ) {\n sleep {\n id\n sleep_type\n started_at\n ended_at\n }\n errors\n }\n }\n";
|
|
13
|
+
export declare const CREATE_WEIGHT = "\n mutation CreateWeight(\n $baby_id: ID!,\n $weight: Float!,\n $unit: WeightUnitEnum!,\n $measured_at: ISO8601Date!,\n $notes: String\n ) {\n create_weight(\n baby_id: $baby_id,\n weight: $weight,\n unit: $unit,\n measured_at: $measured_at,\n notes: $notes\n ) {\n weight {\n id\n weight_kg\n measured_at\n }\n errors\n }\n }\n";
|
|
14
|
+
export declare const CREATE_LENGTH = "\n mutation CreateLength(\n $baby_id: ID!,\n $length: Float!,\n $unit: LengthUnitEnum!,\n $measured_at: ISO8601Date!,\n $notes: String\n ) {\n create_length(\n baby_id: $baby_id,\n length: $length,\n unit: $unit,\n measured_at: $measured_at,\n notes: $notes\n ) {\n length {\n id\n length_cm\n measured_at\n }\n errors\n }\n }\n";
|
|
15
|
+
export declare const CREATE_TEMPERATURE = "\n mutation CreateTemperature(\n $baby_id: ID!,\n $temperature: Float!,\n $unit: TemperatureUnitEnum!,\n $measured_at: ISO8601DateTime!,\n $notes: String\n ) {\n create_temperature(\n baby_id: $baby_id,\n temperature: $temperature,\n unit: $unit,\n measured_at: $measured_at,\n notes: $notes\n ) {\n temperature {\n id\n temperature_c\n measured_at\n }\n errors\n }\n }\n";
|
|
16
|
+
export declare const GET_USER_SETTINGS = "\n query GetUserSettings {\n me {\n user_setting {\n preferred_unit\n preferred_weight_unit\n preferred_length_unit\n preferred_temperature_unit\n preferred_language\n }\n }\n }\n";
|
|
17
|
+
//# sourceMappingURL=queries.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"queries.d.ts","sourceRoot":"","sources":["../../src/graphql/queries.ts"],"names":[],"mappings":"AACA,eAAO,MAAM,WAAW,mWAoBvB,CAAC;AAEF,eAAO,MAAM,eAAe,koBAkC3B,CAAC;AAGF,eAAO,MAAM,YAAY,wUAcxB,CAAC;AAEF,eAAO,MAAM,kBAAkB,mXAa9B,CAAC;AAGF,eAAO,MAAM,UAAU,2RAWtB,CAAC;AAEF,eAAO,MAAM,gBAAgB,4QAW5B,CAAC;AAGF,eAAO,MAAM,WAAW,qPASvB,CAAC;AAEF,eAAO,MAAM,mBAAmB,gRAY/B,CAAC;AAGF,eAAO,MAAM,WAAW,qPASvB,CAAC;AAGF,eAAO,MAAM,gBAAgB,mQAS5B,CAAC;AAGF,eAAO,MAAM,cAAc,gtBAkC1B,CAAC;AAEF,eAAO,MAAM,YAAY,qdAwBxB,CAAC;AAEF,eAAO,MAAM,aAAa,qaAuBzB,CAAC;AAEF,eAAO,MAAM,aAAa,qaAuBzB,CAAC;AAEF,eAAO,MAAM,kBAAkB,gdAuB9B,CAAC;AAGF,eAAO,MAAM,iBAAiB,6OAY7B,CAAC"}
|