sbb-mcp 0.4.2 → 0.5.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/LICENSE +50 -57
- package/README.md +26 -296
- package/dist/index.js +47 -17
- package/package.json +10 -29
- package/dist/auth.d.ts +0 -2
- package/dist/auth.js +0 -44
- package/dist/auth.js.map +0 -1
- package/dist/cache.d.ts +0 -12
- package/dist/cache.js +0 -58
- package/dist/cache.js.map +0 -1
- package/dist/client.d.ts +0 -17
- package/dist/client.js +0 -70
- package/dist/client.js.map +0 -1
- package/dist/formatters.d.ts +0 -22
- package/dist/formatters.js +0 -210
- package/dist/formatters.js.map +0 -1
- package/dist/http.d.ts +0 -2
- package/dist/http.js +0 -61
- package/dist/http.js.map +0 -1
- package/dist/i18n.d.ts +0 -22
- package/dist/i18n.js +0 -36
- package/dist/i18n.js.map +0 -1
- package/dist/index.d.ts +0 -2
- package/dist/index.js.map +0 -1
- package/dist/journey.d.ts +0 -5
- package/dist/journey.js +0 -67
- package/dist/journey.js.map +0 -1
- package/dist/prices.d.ts +0 -3
- package/dist/prices.js +0 -51
- package/dist/prices.js.map +0 -1
- package/dist/profile.d.ts +0 -16
- package/dist/profile.js +0 -77
- package/dist/profile.js.map +0 -1
- package/dist/rate-limit.d.ts +0 -5
- package/dist/rate-limit.js +0 -44
- package/dist/rate-limit.js.map +0 -1
- package/dist/structured.d.ts +0 -119
- package/dist/structured.js +0 -133
- package/dist/structured.js.map +0 -1
- package/dist/swisstrip.d.ts +0 -41
- package/dist/swisstrip.js +0 -119
- package/dist/swisstrip.js.map +0 -1
- package/dist/tools.d.ts +0 -2
- package/dist/tools.js +0 -464
- package/dist/tools.js.map +0 -1
- package/dist/transport/index.d.ts +0 -9
- package/dist/transport/index.js +0 -9
- package/dist/transport/index.js.map +0 -1
- package/dist/transport/smapi-auth.d.ts +0 -2
- package/dist/transport/smapi-auth.js +0 -39
- package/dist/transport/smapi-auth.js.map +0 -1
- package/dist/transport/smapi-client.d.ts +0 -22
- package/dist/transport/smapi-client.js +0 -83
- package/dist/transport/smapi-client.js.map +0 -1
- package/dist/transport/smapi-journey.d.ts +0 -23
- package/dist/transport/smapi-journey.js +0 -82
- package/dist/transport/smapi-journey.js.map +0 -1
- package/dist/transport/smapi-mock.d.ts +0 -9
- package/dist/transport/smapi-mock.js +0 -151
- package/dist/transport/smapi-mock.js.map +0 -1
- package/dist/transport/smapi-prices.d.ts +0 -14
- package/dist/transport/smapi-prices.js +0 -73
- package/dist/transport/smapi-prices.js.map +0 -1
- package/dist/transport/smapi-types.d.ts +0 -153
- package/dist/transport/smapi-types.js +0 -2
- package/dist/transport/smapi-types.js.map +0 -1
- package/dist/types.d.ts +0 -139
- package/dist/types.js +0 -3
- package/dist/types.js.map +0 -1
- package/dist/widgets.d.ts +0 -33
- package/dist/widgets.js +0 -120
- package/dist/widgets.js.map +0 -1
- package/web/dist/widgets.css +0 -1
- package/web/dist/widgets.js +0 -1
package/dist/journey.js
DELETED
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { smapiRequest, getJourneyBaseUrl } from './client.js';
|
|
2
|
-
export async function searchPlaces(params) {
|
|
3
|
-
const body = {
|
|
4
|
-
placeInput: { name: params.name },
|
|
5
|
-
restrictions: {
|
|
6
|
-
...(params.type && { type: params.type }),
|
|
7
|
-
numberOfResults: params.numberOfResults ?? 10,
|
|
8
|
-
},
|
|
9
|
-
};
|
|
10
|
-
const result = await smapiRequest(getJourneyBaseUrl(), '/v1/places', { method: 'POST', body });
|
|
11
|
-
return result.places ?? [];
|
|
12
|
-
}
|
|
13
|
-
export async function searchTrips(params) {
|
|
14
|
-
const body = {
|
|
15
|
-
origin: {
|
|
16
|
-
objectType: 'StopPlaceRef',
|
|
17
|
-
stopPlaceRef: params.origin,
|
|
18
|
-
},
|
|
19
|
-
destination: {
|
|
20
|
-
objectType: 'StopPlaceRef',
|
|
21
|
-
stopPlaceRef: params.destination,
|
|
22
|
-
},
|
|
23
|
-
};
|
|
24
|
-
if (params.departureTime) {
|
|
25
|
-
body.departureTime = params.departureTime;
|
|
26
|
-
}
|
|
27
|
-
else if (params.arrivalTime) {
|
|
28
|
-
body.arrivalTime = params.arrivalTime;
|
|
29
|
-
}
|
|
30
|
-
else {
|
|
31
|
-
body.departureTime = new Date().toISOString();
|
|
32
|
-
}
|
|
33
|
-
if (params.transferLimit !== undefined) {
|
|
34
|
-
body.parameters = { transferLimit: params.transferLimit };
|
|
35
|
-
}
|
|
36
|
-
if (params.vias?.length) {
|
|
37
|
-
body.vias = params.vias.map((via) => ({
|
|
38
|
-
viaPlace: {
|
|
39
|
-
objectType: 'StopPlaceRef',
|
|
40
|
-
stopPlaceRef: via.stopPlaceRef,
|
|
41
|
-
},
|
|
42
|
-
...(via.dwellTime && { dwellTime: via.dwellTime }),
|
|
43
|
-
}));
|
|
44
|
-
}
|
|
45
|
-
if (params.ptModeFilter) {
|
|
46
|
-
const parameters = body.parameters || {};
|
|
47
|
-
parameters.dataFilter = {
|
|
48
|
-
ptModeFilter: {
|
|
49
|
-
exclude: params.ptModeFilter.exclude,
|
|
50
|
-
transportModes: params.ptModeFilter.transportModes.map((mode) => ({
|
|
51
|
-
ptMode: mode,
|
|
52
|
-
})),
|
|
53
|
-
},
|
|
54
|
-
};
|
|
55
|
-
body.parameters = parameters;
|
|
56
|
-
}
|
|
57
|
-
return smapiRequest(getJourneyBaseUrl(), '/v1/trips-collection', { method: 'POST', body });
|
|
58
|
-
}
|
|
59
|
-
export async function getTrip(tripId, stopBehavior = 'ORIGIN_DESTINATION_ONLY') {
|
|
60
|
-
const params = new URLSearchParams({ stopBehavior });
|
|
61
|
-
return smapiRequest(getJourneyBaseUrl(), `/v1/trips/${encodeURIComponent(tripId)}?${params}`);
|
|
62
|
-
}
|
|
63
|
-
export async function paginateTrips(collectionId, direction) {
|
|
64
|
-
const params = new URLSearchParams({ page: direction });
|
|
65
|
-
return smapiRequest(getJourneyBaseUrl(), `/v1/trips-collections/${encodeURIComponent(collectionId)}?${params}`);
|
|
66
|
-
}
|
|
67
|
-
//# sourceMappingURL=journey.js.map
|
package/dist/journey.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"journey.js","sourceRoot":"","sources":["../src/journey.ts"],"names":[],"mappings":"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"}
|
package/dist/prices.d.ts
DELETED
package/dist/prices.js
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
import { smapiRequest, getTicketingBaseUrl } from './client.js';
|
|
2
|
-
export async function getTripPrices(tripIds, travelers) {
|
|
3
|
-
const results = await Promise.all(tripIds.map(async (tripId) => {
|
|
4
|
-
const params = new URLSearchParams({ tripId });
|
|
5
|
-
const path = travelers?.length
|
|
6
|
-
? `/api/v2/prices?${params}`
|
|
7
|
-
: `/api/prices?${params}`;
|
|
8
|
-
try {
|
|
9
|
-
const data = await smapiRequest(getTicketingBaseUrl(), path, {
|
|
10
|
-
method: travelers?.length ? 'POST' : 'GET',
|
|
11
|
-
...(travelers?.length && { body: { travelers } }),
|
|
12
|
-
});
|
|
13
|
-
const prices = data.prices ?? (data.price ? [{
|
|
14
|
-
amount: data.price.amount,
|
|
15
|
-
currency: data.price.currency,
|
|
16
|
-
class: '2',
|
|
17
|
-
}] : []);
|
|
18
|
-
return {
|
|
19
|
-
tripId,
|
|
20
|
-
prices: prices.map((p) => ({
|
|
21
|
-
amount: p.amount,
|
|
22
|
-
currency: p.currency || 'CHF',
|
|
23
|
-
class: (p.class || '2'),
|
|
24
|
-
reductionCard: p.reductionCard,
|
|
25
|
-
})),
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
catch (err) {
|
|
29
|
-
console.error(`[sbb-mcp] Failed to get price for trip ${tripId}:`, err);
|
|
30
|
-
return { tripId, prices: [] };
|
|
31
|
-
}
|
|
32
|
-
}));
|
|
33
|
-
return results;
|
|
34
|
-
}
|
|
35
|
-
export async function getTripOfferLink(tripId, travelers) {
|
|
36
|
-
const body = {
|
|
37
|
-
tripId,
|
|
38
|
-
travelers: travelers.map((t) => ({
|
|
39
|
-
externalId: t.id,
|
|
40
|
-
type: t.type,
|
|
41
|
-
...(t.dateOfBirth && { dateOfBirth: t.dateOfBirth }),
|
|
42
|
-
...(t.reductionCard && t.reductionCard !== 'NONE' && {
|
|
43
|
-
cards: [{ type: t.reductionCard }],
|
|
44
|
-
}),
|
|
45
|
-
})),
|
|
46
|
-
};
|
|
47
|
-
const data = await smapiRequest(getTicketingBaseUrl(), '/api/trip-offers', { method: 'POST', body });
|
|
48
|
-
const links = (data.links ?? []);
|
|
49
|
-
return links.find((l) => l.rel === 'online-offers')?.href ?? null;
|
|
50
|
-
}
|
|
51
|
-
//# sourceMappingURL=prices.js.map
|
package/dist/prices.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"prices.js","sourceRoot":"","sources":["../src/prices.ts"],"names":[],"mappings":"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"}
|
package/dist/profile.d.ts
DELETED
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
import type { Lang } from './i18n.js';
|
|
2
|
-
export type UserProfile = {
|
|
3
|
-
first_name?: string;
|
|
4
|
-
last_name?: string;
|
|
5
|
-
date_of_birth?: string;
|
|
6
|
-
reduction_card?: 'HALF_FARE' | 'GA' | 'NONE';
|
|
7
|
-
reduction_card_valid_until?: string;
|
|
8
|
-
language?: Lang;
|
|
9
|
-
created_at?: string;
|
|
10
|
-
updated_at?: string;
|
|
11
|
-
};
|
|
12
|
-
export declare function getProfilePath(): string;
|
|
13
|
-
export declare function loadProfile(): UserProfile | null;
|
|
14
|
-
export declare function saveProfile(profile: UserProfile): void;
|
|
15
|
-
export declare function isReductionCardExpired(profile: UserProfile): boolean;
|
|
16
|
-
export declare function formatProfileSummary(profile: UserProfile, lang?: Lang): string;
|
package/dist/profile.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
2
|
-
import { join } from 'path';
|
|
3
|
-
import { homedir } from 'os';
|
|
4
|
-
import { toLocale, t } from './i18n.js';
|
|
5
|
-
const PROFILE_DIR = join(homedir(), '.sbb-mcp');
|
|
6
|
-
const PROFILE_PATH = join(PROFILE_DIR, 'profile.json');
|
|
7
|
-
export function getProfilePath() {
|
|
8
|
-
return PROFILE_PATH;
|
|
9
|
-
}
|
|
10
|
-
export function loadProfile() {
|
|
11
|
-
try {
|
|
12
|
-
if (!existsSync(PROFILE_PATH))
|
|
13
|
-
return null;
|
|
14
|
-
const raw = readFileSync(PROFILE_PATH, 'utf-8');
|
|
15
|
-
return JSON.parse(raw);
|
|
16
|
-
}
|
|
17
|
-
catch {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
}
|
|
21
|
-
export function saveProfile(profile) {
|
|
22
|
-
mkdirSync(PROFILE_DIR, { recursive: true });
|
|
23
|
-
const existing = loadProfile();
|
|
24
|
-
const merged = {
|
|
25
|
-
...existing,
|
|
26
|
-
...profile,
|
|
27
|
-
updated_at: new Date().toISOString(),
|
|
28
|
-
created_at: existing?.created_at || new Date().toISOString(),
|
|
29
|
-
};
|
|
30
|
-
writeFileSync(PROFILE_PATH, JSON.stringify(merged, null, 2), 'utf-8');
|
|
31
|
-
}
|
|
32
|
-
export function isReductionCardExpired(profile) {
|
|
33
|
-
if (!profile.reduction_card || profile.reduction_card === 'NONE')
|
|
34
|
-
return false;
|
|
35
|
-
if (!profile.reduction_card_valid_until)
|
|
36
|
-
return false; // no expiry set, assume valid
|
|
37
|
-
const validUntil = new Date(profile.reduction_card_valid_until).getTime();
|
|
38
|
-
return Date.now() > validUntil;
|
|
39
|
-
}
|
|
40
|
-
export function formatProfileSummary(profile, lang = 'en') {
|
|
41
|
-
const tr = t(lang);
|
|
42
|
-
const locale = toLocale(lang);
|
|
43
|
-
const lines = ['**Your Travel Profile**', ''];
|
|
44
|
-
if (profile.first_name || profile.last_name) {
|
|
45
|
-
lines.push(`Name: ${[profile.first_name, profile.last_name].filter(Boolean).join(' ')}`);
|
|
46
|
-
}
|
|
47
|
-
if (profile.date_of_birth) {
|
|
48
|
-
lines.push(`Date of birth: ${profile.date_of_birth}`);
|
|
49
|
-
}
|
|
50
|
-
if (profile.reduction_card && profile.reduction_card !== 'NONE') {
|
|
51
|
-
const cardName = profile.reduction_card === 'HALF_FARE' ? 'Halbtax (Half-Fare)' : 'GA Travelcard';
|
|
52
|
-
const expired = isReductionCardExpired(profile);
|
|
53
|
-
let cardLine = `Reduction card: ${cardName}`;
|
|
54
|
-
if (profile.reduction_card_valid_until) {
|
|
55
|
-
cardLine += ` (valid until ${profile.reduction_card_valid_until})`;
|
|
56
|
-
}
|
|
57
|
-
if (expired) {
|
|
58
|
-
cardLine += ' — EXPIRED. Ask the user if they renewed it.';
|
|
59
|
-
}
|
|
60
|
-
lines.push(cardLine);
|
|
61
|
-
}
|
|
62
|
-
else {
|
|
63
|
-
lines.push('Reduction card: None');
|
|
64
|
-
}
|
|
65
|
-
if (profile.language) {
|
|
66
|
-
lines.push(`Language: ${profile.language}`);
|
|
67
|
-
}
|
|
68
|
-
if (profile.updated_at) {
|
|
69
|
-
lines.push(`Last updated: ${new Date(profile.updated_at).toLocaleDateString(locale)}`);
|
|
70
|
-
}
|
|
71
|
-
// Suppress unused-var warning for tr until we translate the labels above
|
|
72
|
-
void tr;
|
|
73
|
-
lines.push('');
|
|
74
|
-
lines.push(`*Profile stored at \`${PROFILE_PATH}\`. Edit or delete anytime.*`);
|
|
75
|
-
return lines.join('\n');
|
|
76
|
-
}
|
|
77
|
-
//# sourceMappingURL=profile.js.map
|
package/dist/profile.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"profile.js","sourceRoot":"","sources":["../src/profile.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,IAAI,CAAA;AACvE,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAA;AAC3B,OAAO,EAAE,OAAO,EAAE,MAAM,IAAI,CAAA;AAE5B,OAAO,EAAE,QAAQ,EAAE,CAAC,EAAE,MAAM,WAAW,CAAA;AAavC,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,CAAC,CAAA;AAC/C,MAAM,YAAY,GAAG,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAA;AAEtD,MAAM,UAAU,cAAc;IAC5B,OAAO,YAAY,CAAA;AACrB,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,IAAI,CAAC;QACH,IAAI,CAAC,UAAU,CAAC,YAAY,CAAC;YAAE,OAAO,IAAI,CAAA;QAC1C,MAAM,GAAG,GAAG,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAA;QAC/C,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAgB,CAAA;IACvC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,OAAoB;IAC9C,SAAS,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;IAC3C,MAAM,QAAQ,GAAG,WAAW,EAAE,CAAA;IAC9B,MAAM,MAAM,GAAgB;QAC1B,GAAG,QAAQ;QACX,GAAG,OAAO;QACV,UAAU,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QACpC,UAAU,EAAE,QAAQ,EAAE,UAAU,IAAI,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KAC7D,CAAA;IACD,aAAa,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAA;AACvE,CAAC;AAED,MAAM,UAAU,sBAAsB,CAAC,OAAoB;IACzD,IAAI,CAAC,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,KAAK,MAAM;QAAE,OAAO,KAAK,CAAA;IAC9E,IAAI,CAAC,OAAO,CAAC,0BAA0B;QAAE,OAAO,KAAK,CAAA,CAAC,8BAA8B;IACpF,MAAM,UAAU,GAAG,IAAI,IAAI,CAAC,OAAO,CAAC,0BAA0B,CAAC,CAAC,OAAO,EAAE,CAAA;IACzE,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,CAAA;AAChC,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,OAAoB,EAAE,OAAa,IAAI;IAC1E,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,CAAC,CAAA;IAClB,MAAM,MAAM,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAA;IAC7B,MAAM,KAAK,GAAa,CAAC,yBAAyB,EAAE,EAAE,CAAC,CAAA;IACvD,IAAI,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;QAC5C,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAC1F,CAAC;IACD,IAAI,OAAO,CAAC,aAAa,EAAE,CAAC;QAC1B,KAAK,CAAC,IAAI,CAAC,kBAAkB,OAAO,CAAC,aAAa,EAAE,CAAC,CAAA;IACvD,CAAC;IACD,IAAI,OAAO,CAAC,cAAc,IAAI,OAAO,CAAC,cAAc,KAAK,MAAM,EAAE,CAAC;QAChE,MAAM,QAAQ,GAAG,OAAO,CAAC,cAAc,KAAK,WAAW,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,eAAe,CAAA;QACjG,MAAM,OAAO,GAAG,sBAAsB,CAAC,OAAO,CAAC,CAAA;QAC/C,IAAI,QAAQ,GAAG,mBAAmB,QAAQ,EAAE,CAAA;QAC5C,IAAI,OAAO,CAAC,0BAA0B,EAAE,CAAC;YACvC,QAAQ,IAAI,iBAAiB,OAAO,CAAC,0BAA0B,GAAG,CAAA;QACpE,CAAC;QACD,IAAI,OAAO,EAAE,CAAC;YACZ,QAAQ,IAAI,8CAA8C,CAAA;QAC5D,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACtB,CAAC;SAAM,CAAC;QACN,KAAK,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;IACpC,CAAC;IACD,IAAI,OAAO,CAAC,QAAQ,EAAE,CAAC;QACrB,KAAK,CAAC,IAAI,CAAC,aAAa,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAA;IAC7C,CAAC;IACD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACvB,KAAK,CAAC,IAAI,CAAC,iBAAiB,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,kBAAkB,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;IACxF,CAAC;IACD,yEAAyE;IACzE,KAAK,EAAE,CAAA;IACP,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAA;IACd,KAAK,CAAC,IAAI,CAAC,wBAAwB,YAAY,8BAA8B,CAAC,CAAA;IAC9E,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACzB,CAAC"}
|
package/dist/rate-limit.d.ts
DELETED
package/dist/rate-limit.js
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Simple in-memory rate limiter per IP.
|
|
3
|
-
* 60 requests per minute per IP. Max 50k tracked IPs.
|
|
4
|
-
*/
|
|
5
|
-
const requests = new Map();
|
|
6
|
-
const WINDOW_MS = 60 * 1000; // 1 minute
|
|
7
|
-
const MAX_REQUESTS = 60; // per window
|
|
8
|
-
const MAX_IPS = 50000; // max tracked IPs
|
|
9
|
-
export function isRateLimited(ip) {
|
|
10
|
-
const now = Date.now();
|
|
11
|
-
const entry = requests.get(ip);
|
|
12
|
-
if (!entry || now >= entry.resetAt) {
|
|
13
|
-
// Evict if map is too large
|
|
14
|
-
if (requests.size >= MAX_IPS) {
|
|
15
|
-
for (const [k, v] of requests) {
|
|
16
|
-
if (now >= v.resetAt)
|
|
17
|
-
requests.delete(k);
|
|
18
|
-
}
|
|
19
|
-
// If still too large after cleanup, drop oldest entries
|
|
20
|
-
if (requests.size >= MAX_IPS) {
|
|
21
|
-
let toDrop = Math.floor(MAX_IPS * 0.1);
|
|
22
|
-
for (const k of requests.keys()) {
|
|
23
|
-
if (toDrop-- <= 0)
|
|
24
|
-
break;
|
|
25
|
-
requests.delete(k);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
requests.set(ip, { count: 1, resetAt: now + WINDOW_MS });
|
|
30
|
-
return false;
|
|
31
|
-
}
|
|
32
|
-
entry.count++;
|
|
33
|
-
return entry.count > MAX_REQUESTS;
|
|
34
|
-
}
|
|
35
|
-
// Cleanup old entries every 5 minutes
|
|
36
|
-
setInterval(() => {
|
|
37
|
-
const now = Date.now();
|
|
38
|
-
for (const [ip, entry] of requests) {
|
|
39
|
-
if (now >= entry.resetAt) {
|
|
40
|
-
requests.delete(ip);
|
|
41
|
-
}
|
|
42
|
-
}
|
|
43
|
-
}, 5 * 60 * 1000).unref();
|
|
44
|
-
//# sourceMappingURL=rate-limit.js.map
|
package/dist/rate-limit.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rate-limit.js","sourceRoot":"","sources":["../src/rate-limit.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,MAAM,QAAQ,GAAG,IAAI,GAAG,EAA8C,CAAA;AAEtE,MAAM,SAAS,GAAG,EAAE,GAAG,IAAI,CAAA,CAAE,WAAW;AACxC,MAAM,YAAY,GAAG,EAAE,CAAA,CAAO,aAAa;AAC3C,MAAM,OAAO,GAAG,KAAK,CAAA,CAAS,kBAAkB;AAEhD,MAAM,UAAU,aAAa,CAAC,EAAU;IACtC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAA;IAE9B,IAAI,CAAC,KAAK,IAAI,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;QACnC,4BAA4B;QAC5B,IAAI,QAAQ,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC;YAC7B,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,QAAQ,EAAE,CAAC;gBAC9B,IAAI,GAAG,IAAI,CAAC,CAAC,OAAO;oBAAE,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;YAC1C,CAAC;YACD,wDAAwD;YACxD,IAAI,QAAQ,CAAC,IAAI,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAC,CAAA;gBACtC,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC;oBAChC,IAAI,MAAM,EAAE,IAAI,CAAC;wBAAE,MAAK;oBACxB,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;QACD,QAAQ,CAAC,GAAG,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,GAAG,GAAG,SAAS,EAAE,CAAC,CAAA;QACxD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,CAAC,KAAK,EAAE,CAAA;IACb,OAAO,KAAK,CAAC,KAAK,GAAG,YAAY,CAAA;AACnC,CAAC;AAED,sCAAsC;AACtC,WAAW,CAAC,GAAG,EAAE;IACf,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;IACtB,KAAK,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,IAAI,QAAQ,EAAE,CAAC;QACnC,IAAI,GAAG,IAAI,KAAK,CAAC,OAAO,EAAE,CAAC;YACzB,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC,CAAA;QACrB,CAAC;IACH,CAAC;AACH,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,KAAK,EAAE,CAAA"}
|
package/dist/structured.d.ts
DELETED
|
@@ -1,119 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure extractors from SMAPI types to widget-friendly DTOs.
|
|
3
|
-
* Shape must stay in sync with web/src/types.ts.
|
|
4
|
-
*
|
|
5
|
-
* Keep these side-effect free. They're tested in unit tests and run on
|
|
6
|
-
* every tool invocation to populate `structuredContent` on responses.
|
|
7
|
-
*/
|
|
8
|
-
import type { SmapiPlace, SmapiTrip, SmapiTripsCollection, SmapiPriceResult } from './transport/smapi-types.js';
|
|
9
|
-
export interface StationDTO {
|
|
10
|
-
id: string;
|
|
11
|
-
name: string;
|
|
12
|
-
lat?: number;
|
|
13
|
-
lon?: number;
|
|
14
|
-
}
|
|
15
|
-
export interface StationsListDTO {
|
|
16
|
-
query: string;
|
|
17
|
-
stations: StationDTO[];
|
|
18
|
-
}
|
|
19
|
-
export interface LegDTO {
|
|
20
|
-
type: 'train' | 'walk';
|
|
21
|
-
line?: string;
|
|
22
|
-
platform?: string;
|
|
23
|
-
minutes: number;
|
|
24
|
-
}
|
|
25
|
-
export interface ConnectionDTO {
|
|
26
|
-
tripId: string;
|
|
27
|
-
departureTime: string;
|
|
28
|
-
arrivalTime: string;
|
|
29
|
-
durationMinutes: number;
|
|
30
|
-
transfers: number;
|
|
31
|
-
legs: LegDTO[];
|
|
32
|
-
}
|
|
33
|
-
export interface ConnectionListDTO {
|
|
34
|
-
origin: StationDTO;
|
|
35
|
-
destination: StationDTO;
|
|
36
|
-
date: string;
|
|
37
|
-
collectionId: string;
|
|
38
|
-
connections: ConnectionDTO[];
|
|
39
|
-
weather?: {
|
|
40
|
-
summary: string;
|
|
41
|
-
};
|
|
42
|
-
}
|
|
43
|
-
export interface TripStopDTO {
|
|
44
|
-
name: string;
|
|
45
|
-
arrivalTime?: string;
|
|
46
|
-
departureTime?: string;
|
|
47
|
-
}
|
|
48
|
-
export interface TripLegDTO {
|
|
49
|
-
type: 'train' | 'walk';
|
|
50
|
-
line?: string;
|
|
51
|
-
operator?: string;
|
|
52
|
-
durationMinutes: number;
|
|
53
|
-
from?: {
|
|
54
|
-
name: string;
|
|
55
|
-
time: string;
|
|
56
|
-
platform?: string;
|
|
57
|
-
};
|
|
58
|
-
to?: {
|
|
59
|
-
name: string;
|
|
60
|
-
time: string;
|
|
61
|
-
platform?: string;
|
|
62
|
-
};
|
|
63
|
-
intermediateStops?: TripStopDTO[];
|
|
64
|
-
occupancy?: {
|
|
65
|
-
firstClass?: string;
|
|
66
|
-
secondClass?: string;
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
export interface TripDetailsDTO {
|
|
70
|
-
tripId: string;
|
|
71
|
-
origin: StationDTO;
|
|
72
|
-
destination: StationDTO;
|
|
73
|
-
departureTime: string;
|
|
74
|
-
arrivalTime: string;
|
|
75
|
-
durationMinutes: number;
|
|
76
|
-
transfers: number;
|
|
77
|
-
status: string;
|
|
78
|
-
legs: TripLegDTO[];
|
|
79
|
-
}
|
|
80
|
-
export interface PriceDTO {
|
|
81
|
-
tripId: string;
|
|
82
|
-
secondClass?: {
|
|
83
|
-
amount: number;
|
|
84
|
-
currency: string;
|
|
85
|
-
};
|
|
86
|
-
firstClass?: {
|
|
87
|
-
amount: number;
|
|
88
|
-
currency: string;
|
|
89
|
-
};
|
|
90
|
-
}
|
|
91
|
-
export interface PricesTableDTO {
|
|
92
|
-
prices: PriceDTO[];
|
|
93
|
-
}
|
|
94
|
-
export interface TicketCardDTO {
|
|
95
|
-
tripId: string;
|
|
96
|
-
origin: StationDTO;
|
|
97
|
-
destination: StationDTO;
|
|
98
|
-
departureTime: string;
|
|
99
|
-
arrivalTime: string;
|
|
100
|
-
primaryLink: string;
|
|
101
|
-
affiliateLink?: string;
|
|
102
|
-
}
|
|
103
|
-
export declare function toStationsListDTO(query: string, places: SmapiPlace[]): StationsListDTO;
|
|
104
|
-
export declare function toConnectionListDTO(collection: SmapiTripsCollection, weather?: {
|
|
105
|
-
summary: string;
|
|
106
|
-
}): ConnectionListDTO;
|
|
107
|
-
export declare function toTripDetailsDTO(trip: SmapiTrip): TripDetailsDTO;
|
|
108
|
-
export declare function toPricesTableDTO(results: SmapiPriceResult[]): PricesTableDTO;
|
|
109
|
-
export declare function toTicketCardDTO(params: {
|
|
110
|
-
tripId: string;
|
|
111
|
-
fromName: string;
|
|
112
|
-
fromId: string;
|
|
113
|
-
toName: string;
|
|
114
|
-
toId: string;
|
|
115
|
-
departureTime: string;
|
|
116
|
-
arrivalTime: string;
|
|
117
|
-
primaryLink: string;
|
|
118
|
-
affiliateLink?: string;
|
|
119
|
-
}): TicketCardDTO;
|
package/dist/structured.js
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pure extractors from SMAPI types to widget-friendly DTOs.
|
|
3
|
-
* Shape must stay in sync with web/src/types.ts.
|
|
4
|
-
*
|
|
5
|
-
* Keep these side-effect free. They're tested in unit tests and run on
|
|
6
|
-
* every tool invocation to populate `structuredContent` on responses.
|
|
7
|
-
*/
|
|
8
|
-
// ──────────────────────────────────────────────────────────────────────
|
|
9
|
-
function toStation(p) {
|
|
10
|
-
return {
|
|
11
|
-
id: p.id,
|
|
12
|
-
name: p.name,
|
|
13
|
-
lat: p.geoPosition?.latitude,
|
|
14
|
-
lon: p.geoPosition?.longitude,
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
function parseIsoDurationMinutes(iso) {
|
|
18
|
-
const m = iso.match(/PT(?:(\d+)H)?(?:(\d+)M)?/);
|
|
19
|
-
if (!m)
|
|
20
|
-
return 0;
|
|
21
|
-
return parseInt(m[1] ?? '0', 10) * 60 + parseInt(m[2] ?? '0', 10);
|
|
22
|
-
}
|
|
23
|
-
function legToDTO(leg) {
|
|
24
|
-
if (leg.type === 'timed') {
|
|
25
|
-
const tl = leg;
|
|
26
|
-
return {
|
|
27
|
-
type: 'train',
|
|
28
|
-
line: tl.service.publishedLineName,
|
|
29
|
-
platform: tl.board.platform,
|
|
30
|
-
minutes: parseIsoDurationMinutes(tl.duration),
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
if (leg.type === 'transfer') {
|
|
34
|
-
const tr = leg;
|
|
35
|
-
return { type: 'walk', minutes: parseIsoDurationMinutes(tr.duration) };
|
|
36
|
-
}
|
|
37
|
-
return { type: 'walk', minutes: parseIsoDurationMinutes(leg.duration) };
|
|
38
|
-
}
|
|
39
|
-
export function toStationsListDTO(query, places) {
|
|
40
|
-
return { query, stations: places.map(toStation) };
|
|
41
|
-
}
|
|
42
|
-
export function toConnectionListDTO(collection, weather) {
|
|
43
|
-
const first = collection.trips[0];
|
|
44
|
-
const fallbackStation = { id: '', name: '—' };
|
|
45
|
-
return {
|
|
46
|
-
origin: first ? toStation(first.origin) : fallbackStation,
|
|
47
|
-
destination: first ? toStation(first.destination) : fallbackStation,
|
|
48
|
-
date: first?.startTime ?? '',
|
|
49
|
-
collectionId: collection.id,
|
|
50
|
-
connections: collection.trips.map((t) => ({
|
|
51
|
-
tripId: t.id,
|
|
52
|
-
departureTime: t.startTime,
|
|
53
|
-
arrivalTime: t.endTime,
|
|
54
|
-
durationMinutes: parseIsoDurationMinutes(t.duration),
|
|
55
|
-
transfers: t.transfers,
|
|
56
|
-
legs: t.legs.map(legToDTO),
|
|
57
|
-
})),
|
|
58
|
-
...(weather ? { weather } : {}),
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
export function toTripDetailsDTO(trip) {
|
|
62
|
-
return {
|
|
63
|
-
tripId: trip.id,
|
|
64
|
-
origin: toStation(trip.origin),
|
|
65
|
-
destination: toStation(trip.destination),
|
|
66
|
-
departureTime: trip.startTime,
|
|
67
|
-
arrivalTime: trip.endTime,
|
|
68
|
-
durationMinutes: parseIsoDurationMinutes(trip.duration),
|
|
69
|
-
transfers: trip.transfers,
|
|
70
|
-
status: trip.tripStatus,
|
|
71
|
-
legs: trip.legs.map((leg) => {
|
|
72
|
-
if (leg.type === 'timed') {
|
|
73
|
-
const tl = leg;
|
|
74
|
-
return {
|
|
75
|
-
type: 'train',
|
|
76
|
-
line: tl.service.publishedLineName,
|
|
77
|
-
operator: tl.service.operatorName,
|
|
78
|
-
durationMinutes: parseIsoDurationMinutes(tl.duration),
|
|
79
|
-
from: {
|
|
80
|
-
name: tl.board.stopPlace.name,
|
|
81
|
-
time: tl.board.departureTime,
|
|
82
|
-
platform: tl.board.platform,
|
|
83
|
-
},
|
|
84
|
-
to: {
|
|
85
|
-
name: tl.alight.stopPlace.name,
|
|
86
|
-
time: tl.alight.arrivalTime,
|
|
87
|
-
platform: tl.alight.platform,
|
|
88
|
-
},
|
|
89
|
-
intermediateStops: tl.intermediateStops?.map((s) => ({
|
|
90
|
-
name: s.stopPlace.name,
|
|
91
|
-
arrivalTime: s.arrivalTime,
|
|
92
|
-
departureTime: s.departureTime,
|
|
93
|
-
})),
|
|
94
|
-
occupancy: tl.occupancy
|
|
95
|
-
? {
|
|
96
|
-
firstClass: tl.occupancy.firstClass,
|
|
97
|
-
secondClass: tl.occupancy.secondClass,
|
|
98
|
-
}
|
|
99
|
-
: undefined,
|
|
100
|
-
};
|
|
101
|
-
}
|
|
102
|
-
return {
|
|
103
|
-
type: 'walk',
|
|
104
|
-
durationMinutes: parseIsoDurationMinutes(leg.duration),
|
|
105
|
-
};
|
|
106
|
-
}),
|
|
107
|
-
};
|
|
108
|
-
}
|
|
109
|
-
export function toPricesTableDTO(results) {
|
|
110
|
-
return {
|
|
111
|
-
prices: results.map((r) => {
|
|
112
|
-
const second = r.prices.find((p) => p.class === '2');
|
|
113
|
-
const first = r.prices.find((p) => p.class === '1');
|
|
114
|
-
return {
|
|
115
|
-
tripId: r.tripId,
|
|
116
|
-
...(second ? { secondClass: { amount: second.amount, currency: second.currency } } : {}),
|
|
117
|
-
...(first ? { firstClass: { amount: first.amount, currency: first.currency } } : {}),
|
|
118
|
-
};
|
|
119
|
-
}),
|
|
120
|
-
};
|
|
121
|
-
}
|
|
122
|
-
export function toTicketCardDTO(params) {
|
|
123
|
-
return {
|
|
124
|
-
tripId: params.tripId,
|
|
125
|
-
origin: { id: params.fromId, name: params.fromName },
|
|
126
|
-
destination: { id: params.toId, name: params.toName },
|
|
127
|
-
departureTime: params.departureTime,
|
|
128
|
-
arrivalTime: params.arrivalTime,
|
|
129
|
-
primaryLink: params.primaryLink,
|
|
130
|
-
...(params.affiliateLink ? { affiliateLink: params.affiliateLink } : {}),
|
|
131
|
-
};
|
|
132
|
-
}
|
|
133
|
-
//# sourceMappingURL=structured.js.map
|
package/dist/structured.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"structured.js","sourceRoot":"","sources":["../src/structured.ts"],"names":[],"mappings":"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"}
|
package/dist/swisstrip.d.ts
DELETED
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SwissTrip API client for sbb-mcp (Layer 3)
|
|
3
|
-
*
|
|
4
|
-
* When SWISSTRIP_TOKEN is set, sbb-mcp fetches traveler profiles from the
|
|
5
|
-
* SwissTrip cloud API instead of (or in addition to) the local file.
|
|
6
|
-
* This enables cloud-synced profiles and multi-traveler support (partner, kids).
|
|
7
|
-
*/
|
|
8
|
-
import type { SmapiTraveler } from './transport/smapi-types.js';
|
|
9
|
-
export type SwissTripProfile = {
|
|
10
|
-
id: string;
|
|
11
|
-
email: string;
|
|
12
|
-
travel_first_name: string | null;
|
|
13
|
-
travel_last_name: string | null;
|
|
14
|
-
travel_date_of_birth: string | null;
|
|
15
|
-
travel_reduction_card: string | null;
|
|
16
|
-
travel_reduction_card_valid_until: string | null;
|
|
17
|
-
locale: string | null;
|
|
18
|
-
preferred_currency: string | null;
|
|
19
|
-
};
|
|
20
|
-
export type SwissTripTraveler = {
|
|
21
|
-
id: string;
|
|
22
|
-
user_id: string;
|
|
23
|
-
label: string | null;
|
|
24
|
-
first_name: string | null;
|
|
25
|
-
last_name: string | null;
|
|
26
|
-
date_of_birth: string | null;
|
|
27
|
-
reduction_card: string | null;
|
|
28
|
-
reduction_card_valid_until: string | null;
|
|
29
|
-
is_primary: boolean;
|
|
30
|
-
created_at: string;
|
|
31
|
-
updated_at: string;
|
|
32
|
-
};
|
|
33
|
-
export declare function isSwissTripConfigured(): boolean;
|
|
34
|
-
export declare function fetchProfile(): Promise<SwissTripProfile>;
|
|
35
|
-
export declare function fetchTravelers(): Promise<SwissTripTraveler[]>;
|
|
36
|
-
/** Convert a SwissTrip traveler to an SMAPI traveler for pricing/offers */
|
|
37
|
-
export declare function toSmapiTraveler(t: SwissTripTraveler, index: number): SmapiTraveler;
|
|
38
|
-
/** Convert the primary profile (from /api/mcp/profile) to an SMAPI traveler */
|
|
39
|
-
export declare function profileToSmapiTraveler(p: SwissTripProfile): SmapiTraveler;
|
|
40
|
-
export declare function formatTravelersList(travelers: SwissTripTraveler[]): string;
|
|
41
|
-
export declare function formatCloudProfile(profile: SwissTripProfile): string;
|