migros-mcp 0.2.0 → 0.3.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 +108 -24
- package/dist/auth/api.d.ts +19 -0
- package/dist/auth/api.js +63 -0
- package/dist/auth/api.js.map +1 -0
- package/dist/auth/cookies.d.ts +25 -0
- package/dist/auth/cookies.js +66 -0
- package/dist/auth/cookies.js.map +1 -0
- package/dist/auth/index.d.ts +17 -0
- package/dist/auth/index.js +36 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/login.d.ts +20 -0
- package/dist/auth/login.js +138 -0
- package/dist/auth/login.js.map +1 -0
- package/dist/auth/oauth.d.ts +20 -0
- package/dist/auth/oauth.js +116 -0
- package/dist/auth/oauth.js.map +1 -0
- package/dist/auth/paths.d.ts +11 -0
- package/dist/auth/paths.js +26 -0
- package/dist/auth/paths.js.map +1 -0
- package/dist/auth-tools/_shared.d.ts +6 -0
- package/dist/auth-tools/_shared.js +12 -0
- package/dist/auth-tools/_shared.js.map +1 -0
- package/dist/auth-tools/account.d.ts +9 -0
- package/dist/auth-tools/account.js +35 -0
- package/dist/auth-tools/account.js.map +1 -0
- package/dist/auth-tools/cart.d.ts +37 -0
- package/dist/auth-tools/cart.js +118 -0
- package/dist/auth-tools/cart.js.map +1 -0
- package/dist/auth-tools/cumulus.d.ts +31 -0
- package/dist/auth-tools/cumulus.js +83 -0
- package/dist/auth-tools/cumulus.js.map +1 -0
- package/dist/auth-tools/orders.d.ts +15 -0
- package/dist/auth-tools/orders.js +32 -0
- package/dist/auth-tools/orders.js.map +1 -0
- package/dist/auth-tools.d.ts +9 -0
- package/dist/auth-tools.js +10 -0
- package/dist/auth-tools.js.map +1 -0
- package/dist/index.d.ts +0 -0
- package/dist/index.js +37 -80
- package/dist/index.js.map +1 -1
- package/dist/migros.d.ts +17 -0
- package/dist/migros.js +42 -1
- package/dist/migros.js.map +1 -1
- package/dist/register.d.ts +11 -0
- package/dist/register.js +23 -0
- package/dist/register.js.map +1 -0
- package/dist/schemas.d.ts +125 -0
- package/dist/schemas.js +82 -12
- package/dist/schemas.js.map +1 -1
- package/dist/tools.d.ts +17 -0
- package/dist/tools.js +48 -1
- package/dist/tools.js.map +1 -1
- package/dist/types.d.ts +0 -0
- package/dist/types.js +0 -0
- package/dist/types.js.map +0 -0
- package/package.json +3 -2
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { AxiosInstance } from "axios";
|
|
2
|
+
import type { Session } from "./cookies.js";
|
|
3
|
+
export declare function client(): AxiosInstance;
|
|
4
|
+
export declare function uaFor(host: string): string;
|
|
5
|
+
export declare function uniformHeaders(host: string, session: Session, extra?: Record<string, string>): Record<string, string>;
|
|
6
|
+
/**
|
|
7
|
+
* Run the silent OAuth flow against current SSO cookies and return a fresh
|
|
8
|
+
* access token. Mutates `session` in place (cookies + jwt + jwtExp).
|
|
9
|
+
*
|
|
10
|
+
* Throws if the SSO cookies are missing/expired (e.g., user logged out of
|
|
11
|
+
* migros.ch in their browser, or session.json is stale by weeks).
|
|
12
|
+
*
|
|
13
|
+
* Caller is responsible for persisting the session afterward.
|
|
14
|
+
*/
|
|
15
|
+
export declare function silentOAuth(session: Session): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Returns a usable JWT, refreshing via silent OAuth if the cached one is
|
|
18
|
+
* within `bufferSeconds` of expiring (or missing). Mutates `session`.
|
|
19
|
+
*/
|
|
20
|
+
export declare function getJwt(session: Session, bufferSeconds?: number): Promise<string>;
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import https from "node:https";
|
|
2
|
+
import axios from "axios";
|
|
3
|
+
import { cookieHeader, ingestSetCookie } from "./cookies.js";
|
|
4
|
+
// IMPORTANT: per-host User-Agent. Akamai on www.migros.ch rejects Chrome but
|
|
5
|
+
// accepts this Firefox/Linux UA (same approach as migros-api-wrapper). The login
|
|
6
|
+
// origin uses Cloudflare which is more permissive and accepts Chrome.
|
|
7
|
+
const UA_LOGIN = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/147.0.0.0 Safari/537.36";
|
|
8
|
+
const UA_WWW = "Mozilla/5.0 (X11; Linux x86_64; rv:144.0) Gecko/20100101 Firefox/144.0";
|
|
9
|
+
const REDIRECT_URI = "https://www.migros.ch/m-login-silent-login-redirect.html";
|
|
10
|
+
let _client = null;
|
|
11
|
+
export function client() {
|
|
12
|
+
// Lazily build to avoid creating an https.Agent at module-load time.
|
|
13
|
+
if (_client)
|
|
14
|
+
return _client;
|
|
15
|
+
_client = axios.create({
|
|
16
|
+
httpsAgent: new https.Agent({ minVersion: "TLSv1.3" }),
|
|
17
|
+
validateStatus: () => true,
|
|
18
|
+
maxRedirects: 0,
|
|
19
|
+
});
|
|
20
|
+
return _client;
|
|
21
|
+
}
|
|
22
|
+
export function uaFor(host) {
|
|
23
|
+
return host === "www.migros.ch" ? UA_WWW : UA_LOGIN;
|
|
24
|
+
}
|
|
25
|
+
export function uniformHeaders(host, session, extra = {}) {
|
|
26
|
+
return {
|
|
27
|
+
"User-Agent": uaFor(host),
|
|
28
|
+
"Accept-Language": "en-US,en;q=0.9",
|
|
29
|
+
"Accept-Encoding": "gzip, deflate, br",
|
|
30
|
+
Cookie: cookieHeader(session, host),
|
|
31
|
+
...extra,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function decodeJwtExp(jwt) {
|
|
35
|
+
const parts = jwt.split(".");
|
|
36
|
+
if (parts.length !== 3)
|
|
37
|
+
throw new Error("malformed JWT");
|
|
38
|
+
const payload = JSON.parse(Buffer.from(parts[1], "base64").toString());
|
|
39
|
+
if (typeof payload.exp !== "number")
|
|
40
|
+
throw new Error("JWT has no exp claim");
|
|
41
|
+
return payload.exp;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Run the silent OAuth flow against current SSO cookies and return a fresh
|
|
45
|
+
* access token. Mutates `session` in place (cookies + jwt + jwtExp).
|
|
46
|
+
*
|
|
47
|
+
* Throws if the SSO cookies are missing/expired (e.g., user logged out of
|
|
48
|
+
* migros.ch in their browser, or session.json is stale by weeks).
|
|
49
|
+
*
|
|
50
|
+
* Caller is responsible for persisting the session afterward.
|
|
51
|
+
*/
|
|
52
|
+
export async function silentOAuth(session) {
|
|
53
|
+
// Step 1: ask www.migros.ch for the silent-SSO URL on login.migros.ch.
|
|
54
|
+
const authorizeUrl = "https://www.migros.ch/authentication/public/v1/api/oauth/authorize" +
|
|
55
|
+
"?redirectUri=" + encodeURIComponent(REDIRECT_URI) +
|
|
56
|
+
"&withLoginPrompt=false&claimType=LOGIN&authorizationNotRequired=true";
|
|
57
|
+
let r = await client().get(authorizeUrl, {
|
|
58
|
+
headers: uniformHeaders("www.migros.ch", session, { Accept: "application/json, text/plain, */*" }),
|
|
59
|
+
});
|
|
60
|
+
ingestSetCookie(session, "www.migros.ch", r.headers["set-cookie"]);
|
|
61
|
+
if (r.status !== 200)
|
|
62
|
+
throw new Error(`oauth/authorize -> ${r.status}`);
|
|
63
|
+
const data = typeof r.data === "string" ? JSON.parse(r.data) : r.data;
|
|
64
|
+
const ssoUrl = data?.url;
|
|
65
|
+
if (!ssoUrl)
|
|
66
|
+
throw new Error("oauth/authorize did not return a sso url");
|
|
67
|
+
// Step 2: hit login.migros.ch with our SSO cookies. With prompt=none, valid
|
|
68
|
+
// cookies redirect with ?code=...&state=...; expired cookies return an error.
|
|
69
|
+
r = await client().get(ssoUrl, {
|
|
70
|
+
headers: uniformHeaders("login.migros.ch", session, { Accept: "text/html" }),
|
|
71
|
+
});
|
|
72
|
+
ingestSetCookie(session, "login.migros.ch", r.headers["set-cookie"]);
|
|
73
|
+
const location = r.headers.location;
|
|
74
|
+
if (!location) {
|
|
75
|
+
throw new Error("silent SSO did not redirect — login.migros.ch session likely expired");
|
|
76
|
+
}
|
|
77
|
+
const u = new URL(location);
|
|
78
|
+
const code = u.searchParams.get("code");
|
|
79
|
+
const state = u.searchParams.get("state");
|
|
80
|
+
if (!code || !state)
|
|
81
|
+
throw new Error("silent SSO redirected without code/state");
|
|
82
|
+
// Step 3: exchange the code for a JWT.
|
|
83
|
+
const successUrl = "https://www.migros.ch/authentication/public/v1/api/oauth/login-success" +
|
|
84
|
+
`?code=${encodeURIComponent(code)}&state=${encodeURIComponent(state)}` +
|
|
85
|
+
"&redirectUri=" + encodeURIComponent(REDIRECT_URI) +
|
|
86
|
+
"&authorizationNotRequired=true";
|
|
87
|
+
r = await client().get(successUrl, {
|
|
88
|
+
headers: uniformHeaders("www.migros.ch", session, { Accept: "application/json" }),
|
|
89
|
+
});
|
|
90
|
+
ingestSetCookie(session, "www.migros.ch", r.headers["set-cookie"]);
|
|
91
|
+
if (r.status !== 200)
|
|
92
|
+
throw new Error(`oauth/login-success -> ${r.status}`);
|
|
93
|
+
const tokenBody = (typeof r.data === "string" ? JSON.parse(r.data) : r.data);
|
|
94
|
+
let token = (tokenBody.accessToken ?? tokenBody.access_token ?? tokenBody.token ?? null);
|
|
95
|
+
if (!token)
|
|
96
|
+
throw new Error("oauth/login-success did not return a token");
|
|
97
|
+
// Migros returns the token with a literal "Bearer " prefix in the JSON body.
|
|
98
|
+
// Strip so callers can safely set `Authorization: Bearer ${token}`.
|
|
99
|
+
if (/^bearer\s+/i.test(token))
|
|
100
|
+
token = token.replace(/^bearer\s+/i, "");
|
|
101
|
+
session.jwt = token;
|
|
102
|
+
session.jwtExp = decodeJwtExp(token);
|
|
103
|
+
return token;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Returns a usable JWT, refreshing via silent OAuth if the cached one is
|
|
107
|
+
* within `bufferSeconds` of expiring (or missing). Mutates `session`.
|
|
108
|
+
*/
|
|
109
|
+
export async function getJwt(session, bufferSeconds = 60) {
|
|
110
|
+
const now = Math.floor(Date.now() / 1000);
|
|
111
|
+
if (session.jwt && session.jwtExp && session.jwtExp - now > bufferSeconds) {
|
|
112
|
+
return session.jwt;
|
|
113
|
+
}
|
|
114
|
+
return silentOAuth(session);
|
|
115
|
+
}
|
|
116
|
+
//# sourceMappingURL=oauth.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"oauth.js","sourceRoot":"","sources":["../../src/auth/oauth.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OS-appropriate user config directory for this MCP.
|
|
3
|
+
* Created lazily by callers; this function does not touch the filesystem.
|
|
4
|
+
*
|
|
5
|
+
* - macOS: ~/Library/Application Support/migros-mcp
|
|
6
|
+
* - Linux: $XDG_CONFIG_HOME/migros-mcp (or ~/.config/migros-mcp)
|
|
7
|
+
* - Windows: %APPDATA%/migros-mcp
|
|
8
|
+
*/
|
|
9
|
+
export declare function configDir(): string;
|
|
10
|
+
/** Path to the persisted session (cookies + cached JWT). */
|
|
11
|
+
export declare function sessionFile(): string;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import os from "node:os";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
const APP = "migros-mcp";
|
|
4
|
+
/**
|
|
5
|
+
* OS-appropriate user config directory for this MCP.
|
|
6
|
+
* Created lazily by callers; this function does not touch the filesystem.
|
|
7
|
+
*
|
|
8
|
+
* - macOS: ~/Library/Application Support/migros-mcp
|
|
9
|
+
* - Linux: $XDG_CONFIG_HOME/migros-mcp (or ~/.config/migros-mcp)
|
|
10
|
+
* - Windows: %APPDATA%/migros-mcp
|
|
11
|
+
*/
|
|
12
|
+
export function configDir() {
|
|
13
|
+
const home = os.homedir();
|
|
14
|
+
if (process.platform === "darwin") {
|
|
15
|
+
return path.join(home, "Library", "Application Support", APP);
|
|
16
|
+
}
|
|
17
|
+
if (process.platform === "win32") {
|
|
18
|
+
return path.join(process.env.APPDATA ?? home, APP);
|
|
19
|
+
}
|
|
20
|
+
return path.join(process.env.XDG_CONFIG_HOME ?? path.join(home, ".config"), APP);
|
|
21
|
+
}
|
|
22
|
+
/** Path to the persisted session (cookies + cached JWT). */
|
|
23
|
+
export function sessionFile() {
|
|
24
|
+
return path.join(configDir(), "session.json");
|
|
25
|
+
}
|
|
26
|
+
//# sourceMappingURL=paths.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"paths.js","sourceRoot":"","sources":["../../src/auth/paths.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,MAAM,GAAG,GAAG,YAAY,CAAC;AAEzB;;;;;;;GAOG;AACH,MAAM,UAAU,SAAS;IACvB,MAAM,IAAI,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC;IAC1B,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,qBAAqB,EAAE,GAAG,CAAC,CAAC;IAChE,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QACjC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,IAAI,EAAE,GAAG,CAAC,CAAC;IACrD,CAAC;IACD,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,GAAG,CAAC,CAAC;AACnF,CAAC;AAED,4DAA4D;AAC5D,MAAM,UAAU,WAAW;IACzB,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,cAAc,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Credentials } from "../auth/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Read credentials from env. Returns undefined if not all vars are set, in
|
|
4
|
+
* which case the auth layer falls back to a cached session if one exists.
|
|
5
|
+
*/
|
|
6
|
+
export declare function credsFromEnv(): Credentials | undefined;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Read credentials from env. Returns undefined if not all vars are set, in
|
|
3
|
+
* which case the auth layer falls back to a cached session if one exists.
|
|
4
|
+
*/
|
|
5
|
+
export function credsFromEnv() {
|
|
6
|
+
const email = process.env.MIGROS_EMAIL;
|
|
7
|
+
const password = process.env.MIGROS_PASSWORD;
|
|
8
|
+
if (!email || !password)
|
|
9
|
+
return undefined;
|
|
10
|
+
return { email, password, totpSecret: process.env.MIGROS_TOTP_SECRET };
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=_shared.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"_shared.js","sourceRoot":"","sources":["../../src/auth-tools/_shared.ts"],"names":[],"mappings":"AAEA;;;GAGG;AACH,MAAM,UAAU,YAAY;IAC1B,MAAM,KAAK,GAAG,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC;IACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,eAAe,CAAC;IAC7C,IAAI,CAAC,KAAK,IAAI,CAAC,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC1C,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,GAAG,CAAC,kBAAkB,EAAE,CAAC;AACzE,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch the logged-in customer's profile. Returns formatted JSON for the LLM.
|
|
3
|
+
*/
|
|
4
|
+
export declare function getProfile(): Promise<string>;
|
|
5
|
+
/**
|
|
6
|
+
* Fetch the user's saved addresses (delivery + billing). Filtered server-side
|
|
7
|
+
* by the deliveryOnly/billingOnly flags; we ask for both by default.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getAddresses(): Promise<string>;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { api } from "../auth/api.js";
|
|
2
|
+
import { credsFromEnv } from "./_shared.js";
|
|
3
|
+
/**
|
|
4
|
+
* Fetch the logged-in customer's profile. Returns formatted JSON for the LLM.
|
|
5
|
+
*/
|
|
6
|
+
export async function getProfile() {
|
|
7
|
+
const profile = (await api("GET", "/retentionapi/public/web/v1/customers/profile", undefined, { creds: credsFromEnv() }));
|
|
8
|
+
return JSON.stringify({
|
|
9
|
+
userId: profile.userId,
|
|
10
|
+
title: profile.title,
|
|
11
|
+
firstName: profile.firstName,
|
|
12
|
+
lastName: profile.lastName,
|
|
13
|
+
email: profile.email,
|
|
14
|
+
languageCode: profile.languageCode,
|
|
15
|
+
preferredCooperative: profile.preferredCooperative,
|
|
16
|
+
}, null, 2);
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Fetch the user's saved addresses (delivery + billing). Filtered server-side
|
|
20
|
+
* by the deliveryOnly/billingOnly flags; we ask for both by default.
|
|
21
|
+
*/
|
|
22
|
+
export async function getAddresses() {
|
|
23
|
+
const list = (await api("GET", "/retentionapi/public/web/v1/customers/addresses?deliveryOnly=false&billingOnly=false", undefined, { creds: credsFromEnv() }));
|
|
24
|
+
return JSON.stringify(list.map((a) => ({
|
|
25
|
+
uid: a.uid,
|
|
26
|
+
name: [a.identity?.firstName, a.identity?.lastName].filter(Boolean).join(" "),
|
|
27
|
+
address: [a.postalAddress?.street, a.postalAddress?.streetNumber].filter(Boolean).join(" "),
|
|
28
|
+
city: [a.postalAddress?.zipCode, a.postalAddress?.city].filter(Boolean).join(" "),
|
|
29
|
+
country: a.postalAddress?.country,
|
|
30
|
+
delivery: !!a.isDelivery,
|
|
31
|
+
billing: !!a.isBilling,
|
|
32
|
+
default: !!a.default,
|
|
33
|
+
})), null, 2);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=account.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"account.js","sourceRoot":"","sources":["../../src/auth-tools/account.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAkB5C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,MAAM,OAAO,GAAG,CAAC,MAAM,GAAG,CACxB,KAAK,EACL,+CAA+C,EAC/C,SAAS,EACT,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAC1B,CAA4B,CAAC;IAE9B,OAAO,IAAI,CAAC,SAAS,CACnB;QACE,MAAM,EAAE,OAAO,CAAC,MAAM;QACtB,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,SAAS,EAAE,OAAO,CAAC,SAAS;QAC5B,QAAQ,EAAE,OAAO,CAAC,QAAQ;QAC1B,KAAK,EAAE,OAAO,CAAC,KAAK;QACpB,YAAY,EAAE,OAAO,CAAC,YAAY;QAClC,oBAAoB,EAAE,OAAO,CAAC,oBAAoB;KACnD,EACD,IAAI,EACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CACrB,KAAK,EACL,sFAAsF,EACtF,SAAS,EACT,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAC1B,CAAmB,CAAC;IAErB,OAAO,IAAI,CAAC,SAAS,CACnB,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;QACf,GAAG,EAAE,CAAC,CAAC,GAAG;QACV,IAAI,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE,SAAS,EAAE,CAAC,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAC7E,OAAO,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,MAAM,EAAE,CAAC,CAAC,aAAa,EAAE,YAAY,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QAC3F,IAAI,EAAE,CAAC,CAAC,CAAC,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC,aAAa,EAAE,IAAI,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC;QACjF,OAAO,EAAE,CAAC,CAAC,aAAa,EAAE,OAAO;QACjC,QAAQ,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU;QACxB,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,SAAS;QACtB,OAAO,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO;KACrB,CAAC,CAAC,EACH,IAAI,EACJ,CAAC,CACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetch the contents of a shopping list (basket). Returns a flat summary of
|
|
3
|
+
* items + totals. Product names are not returned by this endpoint — call
|
|
4
|
+
* get_product_details with the returned ids to enrich.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getBasket(args?: {
|
|
7
|
+
shoppingListId?: number;
|
|
8
|
+
}): Promise<string>;
|
|
9
|
+
/**
|
|
10
|
+
* Add a product to the basket. Sets the target quantity (default 1). If the
|
|
11
|
+
* item is already present, the quantity is REPLACED, not incremented — the
|
|
12
|
+
* underlying API is upsert-to-target. Use update_basket_quantity to set an
|
|
13
|
+
* explicit total when you want increment-like semantics.
|
|
14
|
+
*/
|
|
15
|
+
export declare function addToBasket(args: {
|
|
16
|
+
productId: string;
|
|
17
|
+
quantity?: number;
|
|
18
|
+
shoppingListId?: number;
|
|
19
|
+
}): Promise<string>;
|
|
20
|
+
/** Set an item's exact target quantity. */
|
|
21
|
+
export declare function updateBasketQuantity(args: {
|
|
22
|
+
productId: string;
|
|
23
|
+
quantity: number;
|
|
24
|
+
shoppingListId?: number;
|
|
25
|
+
}): Promise<string>;
|
|
26
|
+
/** Remove an item entirely (quantity 0). */
|
|
27
|
+
export declare function removeFromBasket(args: {
|
|
28
|
+
productId: string;
|
|
29
|
+
shoppingListId?: number;
|
|
30
|
+
}): Promise<string>;
|
|
31
|
+
/**
|
|
32
|
+
* Returns the URL the user should open in their browser to review the basket
|
|
33
|
+
* and complete checkout. Order placement requires payment confirmation in a
|
|
34
|
+
* real browser (Datatrans 3DS / saved-card prompt), so we hand off rather than
|
|
35
|
+
* try to automate the money step. Includes a basket summary for the LLM.
|
|
36
|
+
*/
|
|
37
|
+
export declare function getCheckoutLink(): Promise<string>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { api } from "../auth/api.js";
|
|
2
|
+
import { credsFromEnv } from "./_shared.js";
|
|
3
|
+
/**
|
|
4
|
+
* Resolve the user's primary shopping list id, calling /lists/overview if not
|
|
5
|
+
* provided. Most users have a single list named "Shopping list".
|
|
6
|
+
*/
|
|
7
|
+
async function resolveShoppingListId(provided) {
|
|
8
|
+
if (typeof provided === "number")
|
|
9
|
+
return provided;
|
|
10
|
+
const lists = (await api("GET", "/shopping-list/public/v1/lists/overview", undefined, { creds: credsFromEnv() }));
|
|
11
|
+
if (!lists?.length)
|
|
12
|
+
throw new Error("no shopping lists found for this account");
|
|
13
|
+
return lists[0].shoppingListId;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Format a basket response into the same flat shape get_basket returns.
|
|
17
|
+
* Used by both reads and writes since the v3/items endpoint returns the
|
|
18
|
+
* full updated basket on each call.
|
|
19
|
+
*/
|
|
20
|
+
function formatBasket(data) {
|
|
21
|
+
const items = (data.categories ?? []).flatMap((c) => (c.items ?? []).map((i) => ({
|
|
22
|
+
productId: i.id,
|
|
23
|
+
type: i.type,
|
|
24
|
+
quantity: i.quantity,
|
|
25
|
+
availability: i.ecomProductAvailability,
|
|
26
|
+
categoryId: c.id,
|
|
27
|
+
})));
|
|
28
|
+
return JSON.stringify({
|
|
29
|
+
shoppingListId: data.shoppingListId,
|
|
30
|
+
name: data.name,
|
|
31
|
+
itemCount: items.length,
|
|
32
|
+
totals: {
|
|
33
|
+
instore: data.totals?.instoreTotal,
|
|
34
|
+
online: data.totals?.onlineTotal?.estimatedTotal,
|
|
35
|
+
freeDelivery: data.totals?.onlineTotal?.freeDelivery,
|
|
36
|
+
firstOrder: data.totals?.onlineTotal?.firstOrder,
|
|
37
|
+
minimumOrderValueReached: data.totals?.onlineTotal?.minimumOrderValueReached,
|
|
38
|
+
},
|
|
39
|
+
items,
|
|
40
|
+
hint: items.length > 0
|
|
41
|
+
? "Use get_product_details with productId to fetch each item's name, price, and other info."
|
|
42
|
+
: "Basket is empty.",
|
|
43
|
+
}, null, 2);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Fetch the contents of a shopping list (basket). Returns a flat summary of
|
|
47
|
+
* items + totals. Product names are not returned by this endpoint — call
|
|
48
|
+
* get_product_details with the returned ids to enrich.
|
|
49
|
+
*/
|
|
50
|
+
export async function getBasket(args = {}) {
|
|
51
|
+
const shoppingListId = await resolveShoppingListId(args.shoppingListId);
|
|
52
|
+
const data = (await api("GET", `/shopping-list/public/v2/list/details?shoppingListId=${shoppingListId}`, undefined, { creds: credsFromEnv() }));
|
|
53
|
+
return formatBasket(data);
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Set an item's quantity in the basket. The Migros endpoint is upsert-with-
|
|
57
|
+
* target-quantity semantics: quantity=0 removes, quantity=N replaces (not
|
|
58
|
+
* increments). Used by add/update/remove tools below.
|
|
59
|
+
*/
|
|
60
|
+
async function setItemQuantity(productId, quantity, shoppingListId) {
|
|
61
|
+
const listId = await resolveShoppingListId(shoppingListId);
|
|
62
|
+
const data = (await api("PUT", "/shopping-list/public/v3/items", {
|
|
63
|
+
shoppingListId: listId,
|
|
64
|
+
items: [{ id: productId, quantity, type: "PRODUCT" }],
|
|
65
|
+
}, { creds: credsFromEnv() }));
|
|
66
|
+
return formatBasket(data);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Add a product to the basket. Sets the target quantity (default 1). If the
|
|
70
|
+
* item is already present, the quantity is REPLACED, not incremented — the
|
|
71
|
+
* underlying API is upsert-to-target. Use update_basket_quantity to set an
|
|
72
|
+
* explicit total when you want increment-like semantics.
|
|
73
|
+
*/
|
|
74
|
+
export async function addToBasket(args) {
|
|
75
|
+
const qty = args.quantity ?? 1;
|
|
76
|
+
if (qty < 1)
|
|
77
|
+
throw new Error("quantity must be >= 1 for add_to_basket; use remove_from_basket to delete");
|
|
78
|
+
return setItemQuantity(args.productId, qty, args.shoppingListId);
|
|
79
|
+
}
|
|
80
|
+
/** Set an item's exact target quantity. */
|
|
81
|
+
export async function updateBasketQuantity(args) {
|
|
82
|
+
if (args.quantity < 0)
|
|
83
|
+
throw new Error("quantity must be >= 0");
|
|
84
|
+
return setItemQuantity(args.productId, args.quantity, args.shoppingListId);
|
|
85
|
+
}
|
|
86
|
+
/** Remove an item entirely (quantity 0). */
|
|
87
|
+
export async function removeFromBasket(args) {
|
|
88
|
+
return setItemQuantity(args.productId, 0, args.shoppingListId);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Returns the URL the user should open in their browser to review the basket
|
|
92
|
+
* and complete checkout. Order placement requires payment confirmation in a
|
|
93
|
+
* real browser (Datatrans 3DS / saved-card prompt), so we hand off rather than
|
|
94
|
+
* try to automate the money step. Includes a basket summary for the LLM.
|
|
95
|
+
*/
|
|
96
|
+
export async function getCheckoutLink() {
|
|
97
|
+
const shoppingListId = await resolveShoppingListId();
|
|
98
|
+
const data = (await api("GET", `/shopping-list/public/v2/list/details?shoppingListId=${shoppingListId}`, undefined, { creds: credsFromEnv() }));
|
|
99
|
+
const items = (data.categories ?? []).flatMap((c) => c.items ?? []);
|
|
100
|
+
if (items.length === 0) {
|
|
101
|
+
return JSON.stringify({ ok: false, message: "Basket is empty. Add items with add_to_basket before checkout." }, null, 2);
|
|
102
|
+
}
|
|
103
|
+
const total = data.totals?.onlineTotal?.estimatedTotal;
|
|
104
|
+
const minOk = data.totals?.onlineTotal?.minimumOrderValueReached ?? true;
|
|
105
|
+
const freeDelivery = data.totals?.onlineTotal?.freeDelivery;
|
|
106
|
+
return JSON.stringify({
|
|
107
|
+
ok: true,
|
|
108
|
+
itemCount: items.length,
|
|
109
|
+
onlineTotal: total,
|
|
110
|
+
freeDelivery,
|
|
111
|
+
minimumOrderValueReached: minOk,
|
|
112
|
+
checkoutUrl: "https://www.migros.ch/en?context=ecommerce",
|
|
113
|
+
message: minOk
|
|
114
|
+
? `Open the checkout URL in your browser to confirm address, delivery slot, and payment, then click "Place order".`
|
|
115
|
+
: `Basket below minimum online order value. Add more items, then re-run get_checkout_link.`,
|
|
116
|
+
}, null, 2);
|
|
117
|
+
}
|
|
118
|
+
//# sourceMappingURL=cart.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cart.js","sourceRoot":"","sources":["../../src/auth-tools/cart.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Cumulus card status: points balance, level, cardholder, lifetime savings.
|
|
3
|
+
* Useful as a "what's my Migros loyalty status" overview.
|
|
4
|
+
*/
|
|
5
|
+
export declare function getCumulusStatus(): Promise<string>;
|
|
6
|
+
/**
|
|
7
|
+
* List in-store receipts (Kassenbons) over a date range. Default range: last
|
|
8
|
+
* 30 days. The supermarketOnly flag excludes online order invoices, so this
|
|
9
|
+
* tool answers "what did I buy at the physical store?".
|
|
10
|
+
*/
|
|
11
|
+
export declare function getInStoreReceipts(args?: {
|
|
12
|
+
startDate?: string;
|
|
13
|
+
endDate?: string;
|
|
14
|
+
limit?: number;
|
|
15
|
+
}): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* In-store receipt line items live on `account.migros.ch` behind a legacy
|
|
18
|
+
* CSRF-cookie auth flow that the modern Bearer JWT doesn't access. Rather
|
|
19
|
+
* than implement a parallel auth path, return the URL where the user can
|
|
20
|
+
* inspect the receipt in their browser. The list endpoint
|
|
21
|
+
* (get_in_store_receipts) already gives store, date, total, and points;
|
|
22
|
+
* line-by-line is rarely the deciding factor for LLM workflows.
|
|
23
|
+
*/
|
|
24
|
+
export declare function getReceiptDetails(args: {
|
|
25
|
+
receiptId: string | number;
|
|
26
|
+
}): Promise<string>;
|
|
27
|
+
/**
|
|
28
|
+
* Active Cumulus coupons targeted at the user. Migros personalises these based
|
|
29
|
+
* on shopping history — they typically expire after a few weeks.
|
|
30
|
+
*/
|
|
31
|
+
export declare function getCumulusCoupons(): Promise<string>;
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { api } from "../auth/api.js";
|
|
2
|
+
import { credsFromEnv } from "./_shared.js";
|
|
3
|
+
/**
|
|
4
|
+
* Cumulus card status: points balance, level, cardholder, lifetime savings.
|
|
5
|
+
* Useful as a "what's my Migros loyalty status" overview.
|
|
6
|
+
*/
|
|
7
|
+
export async function getCumulusStatus() {
|
|
8
|
+
const data = (await api("GET", "/retentionapi/public/web/v1/customers/cumulus/details", undefined, { creds: credsFromEnv() }));
|
|
9
|
+
// The exact field set varies; surface the common ones the LLM will care about.
|
|
10
|
+
const owner = data.cumulusCardOwner;
|
|
11
|
+
return JSON.stringify({
|
|
12
|
+
cumulusId: data.cumulusId,
|
|
13
|
+
level: data.level ?? data.cumulusLevel,
|
|
14
|
+
pointsBalance: data.periodToDatePointsBalance ?? data.pointsBalance,
|
|
15
|
+
lifetimePoints: data.lifetimePoints ?? data.totalPoints,
|
|
16
|
+
cardholder: owner ? `${owner.firstName ?? ""} ${owner.lastName ?? ""}`.trim() : undefined,
|
|
17
|
+
cardholderTitle: owner?.title,
|
|
18
|
+
raw: data, // keep raw for the LLM in case it wants other fields
|
|
19
|
+
}, null, 2);
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* List in-store receipts (Kassenbons) over a date range. Default range: last
|
|
23
|
+
* 30 days. The supermarketOnly flag excludes online order invoices, so this
|
|
24
|
+
* tool answers "what did I buy at the physical store?".
|
|
25
|
+
*/
|
|
26
|
+
export async function getInStoreReceipts(args = {}) {
|
|
27
|
+
const today = new Date().toISOString().slice(0, 10);
|
|
28
|
+
const thirtyDaysAgo = new Date(Date.now() - 30 * 24 * 3600 * 1000).toISOString().slice(0, 10);
|
|
29
|
+
const startDate = args.startDate ?? thirtyDaysAgo;
|
|
30
|
+
const endDate = args.endDate ?? today;
|
|
31
|
+
const limit = args.limit ?? 50;
|
|
32
|
+
const url = `/retentionapi/public/web/v1/receipts?startDate=${encodeURIComponent(startDate)}` +
|
|
33
|
+
`&endDate=${encodeURIComponent(endDate)}` +
|
|
34
|
+
`&supermarketOnly=true&limit=${limit}`;
|
|
35
|
+
const data = await api("GET", url, undefined, { creds: credsFromEnv() });
|
|
36
|
+
// Response may be an array or an envelope; normalize.
|
|
37
|
+
const list = Array.isArray(data) ? data : data.receipts ?? [];
|
|
38
|
+
return JSON.stringify({
|
|
39
|
+
startDate,
|
|
40
|
+
endDate,
|
|
41
|
+
count: list.length,
|
|
42
|
+
receipts: list,
|
|
43
|
+
hint: list.length > 0
|
|
44
|
+
? "Use get_receipt_details with a receipt id to inspect line items."
|
|
45
|
+
: `No in-store receipts in ${startDate} to ${endDate}.`,
|
|
46
|
+
}, null, 2);
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* In-store receipt line items live on `account.migros.ch` behind a legacy
|
|
50
|
+
* CSRF-cookie auth flow that the modern Bearer JWT doesn't access. Rather
|
|
51
|
+
* than implement a parallel auth path, return the URL where the user can
|
|
52
|
+
* inspect the receipt in their browser. The list endpoint
|
|
53
|
+
* (get_in_store_receipts) already gives store, date, total, and points;
|
|
54
|
+
* line-by-line is rarely the deciding factor for LLM workflows.
|
|
55
|
+
*/
|
|
56
|
+
export async function getReceiptDetails(args) {
|
|
57
|
+
const id = String(args.receiptId);
|
|
58
|
+
return JSON.stringify({
|
|
59
|
+
receiptId: id,
|
|
60
|
+
message: "Full line items aren't accessible via the public API used by this MCP. Open the URL below in your browser to view the receipt details directly.",
|
|
61
|
+
url: `https://account.migros.ch/purchases/receipts`,
|
|
62
|
+
hint: "The receipt list (get_in_store_receipts) returns store, date, amount, and Cumulus points which is enough for most spending-analysis queries.",
|
|
63
|
+
}, null, 2);
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Active Cumulus coupons targeted at the user. Migros personalises these based
|
|
67
|
+
* on shopping history — they typically expire after a few weeks.
|
|
68
|
+
*/
|
|
69
|
+
export async function getCumulusCoupons() {
|
|
70
|
+
// The SPA calls cumulus-coupons with a deliveryRequestKey when in checkout
|
|
71
|
+
// context (filters to coupons valid for the active delivery). For a general
|
|
72
|
+
// "what coupons do I have" view, omit the key — the server returns all.
|
|
73
|
+
const data = await api("GET", "/retentionapi/public/web/v1/cumulus-coupons", undefined, { creds: credsFromEnv() });
|
|
74
|
+
const list = Array.isArray(data) ? data : data.coupons ?? [];
|
|
75
|
+
return JSON.stringify({
|
|
76
|
+
count: list.length,
|
|
77
|
+
coupons: list,
|
|
78
|
+
hint: list.length > 0
|
|
79
|
+
? "Each coupon has an id, discount, eligible products / categories, and expiry."
|
|
80
|
+
: "No active personal coupons.",
|
|
81
|
+
}, null, 2);
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=cumulus.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cumulus.js","sourceRoot":"","sources":["../../src/auth-tools/cumulus.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
type OrderStatus = "PENDING" | "DELIVERED" | "CANCELLED" | "ALL";
|
|
2
|
+
/**
|
|
3
|
+
* Fetch the user's order history, paginated by status.
|
|
4
|
+
* - status: PENDING (open), DELIVERED, CANCELLED, or ALL. Default: ALL.
|
|
5
|
+
* - page: 0-based.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getOrders(args?: {
|
|
8
|
+
status?: OrderStatus;
|
|
9
|
+
page?: number;
|
|
10
|
+
}): Promise<string>;
|
|
11
|
+
/** Fetch the full details of one order by its id (numeric, e.g. from get_orders). */
|
|
12
|
+
export declare function getOrderDetails(args: {
|
|
13
|
+
orderId: string | number;
|
|
14
|
+
}): Promise<string>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { api } from "../auth/api.js";
|
|
2
|
+
import { credsFromEnv } from "./_shared.js";
|
|
3
|
+
/**
|
|
4
|
+
* Fetch the user's order history, paginated by status.
|
|
5
|
+
* - status: PENDING (open), DELIVERED, CANCELLED, or ALL. Default: ALL.
|
|
6
|
+
* - page: 0-based.
|
|
7
|
+
*/
|
|
8
|
+
export async function getOrders(args = {}) {
|
|
9
|
+
const status = args.status ?? "ALL";
|
|
10
|
+
const page = args.page ?? 0;
|
|
11
|
+
const data = (await api("GET", `/ordergateway/public/web/v1/customers/customer-orders?status=${encodeURIComponent(status)}&page=${page}`, undefined, { creds: credsFromEnv() }));
|
|
12
|
+
// Endpoint may return either an envelope { orders, numberOfOrders, ... } or
|
|
13
|
+
// a bare array depending on backend version. Normalize.
|
|
14
|
+
const orders = Array.isArray(data) ? data : (data.orders ?? []);
|
|
15
|
+
return JSON.stringify({
|
|
16
|
+
status,
|
|
17
|
+
page,
|
|
18
|
+
orderCount: orders.length,
|
|
19
|
+
totalCount: Array.isArray(data) ? undefined : data.numberOfOrders,
|
|
20
|
+
totalPages: Array.isArray(data) ? undefined : data.totalPages,
|
|
21
|
+
orders,
|
|
22
|
+
hint: orders.length === 0
|
|
23
|
+
? `No ${status === "ALL" ? "" : status.toLowerCase() + " "}orders on this page.`
|
|
24
|
+
: "Use get_order_details with an order id to inspect a specific order.",
|
|
25
|
+
}, null, 2);
|
|
26
|
+
}
|
|
27
|
+
/** Fetch the full details of one order by its id (numeric, e.g. from get_orders). */
|
|
28
|
+
export async function getOrderDetails(args) {
|
|
29
|
+
const data = await api("GET", `/ordergateway/public/web/v1/orders/${encodeURIComponent(String(args.orderId))}`, undefined, { creds: credsFromEnv() });
|
|
30
|
+
return JSON.stringify(data, null, 2);
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=orders.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"orders.js","sourceRoot":"","sources":["../../src/auth-tools/orders.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,gBAAgB,CAAC;AACrC,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAI5C;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAAC,OAAgD,EAAE;IAChF,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,KAAK,CAAC;IACpC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC;IAC5B,MAAM,IAAI,GAAG,CAAC,MAAM,GAAG,CACrB,KAAK,EACL,gEAAgE,kBAAkB,CAAC,MAAM,CAAC,SAAS,IAAI,EAAE,EACzG,SAAS,EACT,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAC1B,CAA0G,CAAC;IAE5G,4EAA4E;IAC5E,wDAAwD;IACxD,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;IAChE,OAAO,IAAI,CAAC,SAAS,CACnB;QACE,MAAM;QACN,IAAI;QACJ,UAAU,EAAE,MAAM,CAAC,MAAM;QACzB,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc;QACjE,UAAU,EAAE,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU;QAC7D,MAAM;QACN,IAAI,EACF,MAAM,CAAC,MAAM,KAAK,CAAC;YACjB,CAAC,CAAC,MAAM,MAAM,KAAK,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,EAAE,GAAG,GAAG,sBAAsB;YAChF,CAAC,CAAC,qEAAqE;KAC5E,EACD,IAAI,EACJ,CAAC,CACF,CAAC;AACJ,CAAC;AAED,qFAAqF;AACrF,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAkC;IACtE,MAAM,IAAI,GAAG,MAAM,GAAG,CACpB,KAAK,EACL,sCAAsC,kBAAkB,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,EAChF,SAAS,EACT,EAAE,KAAK,EAAE,YAAY,EAAE,EAAE,CAC1B,CAAC;IACF,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AACvC,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Barrel re-exports for the authenticated tool surface. The actual code is
|
|
3
|
+
* split by domain into ./auth-tools/{account,cart,orders,cumulus}.ts to
|
|
4
|
+
* keep each file focused and easy to scan.
|
|
5
|
+
*/
|
|
6
|
+
export { getProfile, getAddresses } from "./auth-tools/account.js";
|
|
7
|
+
export { getBasket, addToBasket, updateBasketQuantity, removeFromBasket, getCheckoutLink, } from "./auth-tools/cart.js";
|
|
8
|
+
export { getOrders, getOrderDetails } from "./auth-tools/orders.js";
|
|
9
|
+
export { getCumulusStatus, getInStoreReceipts, getReceiptDetails, getCumulusCoupons, } from "./auth-tools/cumulus.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Barrel re-exports for the authenticated tool surface. The actual code is
|
|
3
|
+
* split by domain into ./auth-tools/{account,cart,orders,cumulus}.ts to
|
|
4
|
+
* keep each file focused and easy to scan.
|
|
5
|
+
*/
|
|
6
|
+
export { getProfile, getAddresses } from "./auth-tools/account.js";
|
|
7
|
+
export { getBasket, addToBasket, updateBasketQuantity, removeFromBasket, getCheckoutLink, } from "./auth-tools/cart.js";
|
|
8
|
+
export { getOrders, getOrderDetails } from "./auth-tools/orders.js";
|
|
9
|
+
export { getCumulusStatus, getInStoreReceipts, getReceiptDetails, getCumulusCoupons, } from "./auth-tools/cumulus.js";
|
|
10
|
+
//# sourceMappingURL=auth-tools.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"auth-tools.js","sourceRoot":"","sources":["../src/auth-tools.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,EACL,SAAS,EACT,WAAW,EACX,oBAAoB,EACpB,gBAAgB,EAChB,eAAe,GAChB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACpE,OAAO,EACL,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,GAClB,MAAM,yBAAyB,CAAC"}
|