gotrain 1.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md ADDED
@@ -0,0 +1,54 @@
1
+ # Changelog
2
+
3
+ ## Unreleased
4
+
5
+ ### Fixes
6
+
7
+ - Fixed npm, git, and Homebrew installs to use verified release artifacts.
8
+ - Fixed release publishing to use the stable GitHub Actions Node toolchain.
9
+
10
+ ### Changes
11
+
12
+ - Renamed the published npm and Homebrew package to `gotrain`.
13
+ - Documented the local release wrapper and normalized release workflow naming.
14
+
15
+ ## 1.2.1 - 2026-03-30
16
+
17
+ ### Changes
18
+
19
+ - Added release automation scripts.
20
+
21
+ ## 1.2.0 - 2026-03-19
22
+
23
+ ### Features
24
+
25
+ - Showed ride duration on train boards.
26
+
27
+ ## 1.1.1 - 2026-01-25
28
+
29
+ ### Changes
30
+
31
+ - Added relevant npm package keywords.
32
+
33
+ ## 1.1.0 - 2026-01-25
34
+
35
+ Initial release.
36
+
37
+ ### Features
38
+
39
+ - Added the `gotrain` CLI for MTA system train departures.
40
+ - Added commands, tests, favorites support, arrivals, flags, and alerts.
41
+ - Added improved alert aesthetics, deduplication, pagination, filtering, and `--all` support.
42
+ - Added install script verification and PATH setup.
43
+
44
+ ### Fixes
45
+
46
+ - Fixed `--help` exit behavior for install verification.
47
+ - Fixed download error handling in `install.sh`.
48
+ - Fixed transit system output formatting.
49
+
50
+ ### Changes
51
+
52
+ - Renamed the script from `nyc-train` to `gotrain`.
53
+ - Removed runtime dependencies and refactored API output formatting to TSV.
54
+ - Updated README installation, usage, examples, favorites, and contributing guidance.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gustavo Madeira Santana
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,130 @@
1
+ <img src="assets/gotrain.jpg" alt="gotrain terminal preview" width="280" />
2
+
3
+ # 🚂 gotrain
4
+
5
+ > Atomic CLI for MTA system train departures (NYC Subway, LIRR, Metro-North)
6
+
7
+ No dependencies. No config. Just trains.
8
+
9
+ ![CI](https://img.shields.io/badge/CI-bash--only-yellow)
10
+ ![Platform](https://img.shields.io/badge/Platform-macOS%20%7C%20Linux-blue)
11
+ ![License](https://img.shields.io/badge/License-MIT-green)
12
+
13
+ ## Why?
14
+
15
+ Most train apps are bloated. This is one shell script.
16
+
17
+ ## Install
18
+
19
+ **Via Homebrew:**
20
+ ```bash
21
+ brew tap gumadeiras/tap
22
+ brew install gotrain
23
+ ```
24
+
25
+ **Via npm:**
26
+ ```bash
27
+ npm install -g gotrain
28
+ ```
29
+
30
+ **One-liner (Universal Bash):**
31
+ ```bash
32
+ curl -sL https://raw.githubusercontent.com/gumadeiras/gotrain-cli/main/install.sh | bash
33
+ ```
34
+
35
+ ## Usage
36
+
37
+ ```bash
38
+ # Search stations
39
+ gotrain stations penn # Search for "penn"
40
+ gotrain stations # List all stations
41
+
42
+ # Departures & Arrivals
43
+ gotrain departures MNR-149 # Departures from New Haven
44
+ gotrain departures nh --to MNR-1 # Filter departures to Grand Central (using alias)
45
+ gotrain arrivals MNR-1 # Arrivals at Grand Central
46
+ gotrain arrivals MNR-1 --from nh # Filter arrivals from New Haven
47
+
48
+ # Service alerts
49
+ gotrain alerts # Active service alerts
50
+
51
+ # Favorites
52
+ gotrain favs add MNR-149 nh # Add with alias 'nh'
53
+ gotrain favs rm nh # Remove by alias
54
+ gotrain favs # List favorite stations
55
+ ```
56
+
57
+ ### Examples
58
+
59
+ ```bash
60
+ $ gotrain stations "new haven"
61
+ 🟥 MNR │ New Haven (CT) Lines: New Haven ♿ ID: MNR-149
62
+ 🟥 MNR │ New Haven-State St (CT) Lines: New Haven ♿ ID: MNR-150
63
+
64
+ $ gotrain departures MNR-149
65
+ Departures for New Haven (MNR-149)
66
+ ──────────────────────────────────────────────────────────
67
+ 10:39 AM EST │ Grand Central (Off Peak) [Line: New Haven]
68
+ │ On Time Track 1 • Ride 2h 04m (Train #1539)
69
+
70
+ 11:24 AM EST │ Grand Central (Off Peak) [Line: New Haven]
71
+ │ On Time Track 2 • Ride 2h 01m (Train #1545)
72
+
73
+ $ gotrain arrivals MNR-1 --from nh
74
+ Arrivals for Grand Central (MNR-1)
75
+ Origin: New Haven (MNR-149)
76
+ ──────────────────────────────────────────────────────────
77
+ 12:43 PM EST │ Grand Central (Off Peak) [Line: New Haven]
78
+ │ On Time No Track • Dep 10:39 AM EST • Ride 2h 04m (Train #1539)
79
+
80
+ $ gotrain favorite add MNR-149 home
81
+ Added MNR-149 to favorites (Alias: home) ✅
82
+
83
+ $ gotrain departures home
84
+ 🟦 Departures for New Haven (MNR-149)
85
+ ──────────────────────────────────────────────────────────
86
+ ...
87
+
88
+ $ gotrain alerts
89
+ ⚠️ Uptown [4][5] trains are running with delays...
90
+ No description....
91
+ ```
92
+
93
+ ## Commands
94
+
95
+ | Command | Description |
96
+ |---------|-------------|
97
+ | `stations [query]` | Search/list stations |
98
+ | `departures <id> [--to <id>]` | Show departures (optional destination filter) |
99
+ | `arrivals <id> [--from <id>]` | Show arrivals (optional origin filter) |
100
+ | `alerts [--station <id>] [--all]` | Active service alerts (optional station filter, all alerts) |
101
+ | `favs [add|rm] [id] [alias]` | Manage favorites (list, add, remove, toggle) |
102
+
103
+ ## Clawdbot Integration
104
+
105
+ This tool is available as a **ClawdHub skill**! Use it from any chat where Clawdbot is connected.
106
+
107
+ - **Skill**: [`gotrain`](https://clawdhub.com/skills/gotrain) on ClawdHub
108
+
109
+ ## Data Source
110
+
111
+ Powered by [MetroFlow API](https://metroflow.ainslie.digital) — real-time MTA transit data.
112
+
113
+ ## Contributing
114
+
115
+ PRs are welcome! If you find any bugs or have feature requests, please [open an issue](https://github.com/gumadeiras/gotrain-cli/issues/new).
116
+
117
+ - **Development**: Run `npm test` and `npm run build` to verify changes locally.
118
+ - **Style**: Keep the CLI small and direct.
119
+
120
+ ## Scripts
121
+
122
+ - `./scripts/committer "message" path...`: stage only the listed paths and create a commit
123
+ - `./scripts/release check 1.2.1`: verify synced release versions and run the release test gates
124
+ - `./scripts/release run 1.2.1`: bump versions, run tests, package artifacts, tag, push, wait for the release workflow, publish npm, and update Homebrew
125
+
126
+ Release CI publishes to npm with trusted publishing.
127
+
128
+ ## License
129
+
130
+ MIT 🐧
package/dist/api.d.ts ADDED
@@ -0,0 +1,39 @@
1
+ export interface Station {
2
+ id: string;
3
+ name: string;
4
+ system: string;
5
+ borough?: string;
6
+ accessibilityStatus?: string;
7
+ lines: string[];
8
+ }
9
+ export interface Departure {
10
+ routeShortName?: string;
11
+ routeLongName?: string;
12
+ destination: string;
13
+ departureTime: string;
14
+ status: string;
15
+ track?: string;
16
+ peakStatus?: string;
17
+ direction?: string;
18
+ tripId?: string;
19
+ }
20
+ export interface Alert {
21
+ title: string;
22
+ description?: string;
23
+ activePeriods: {
24
+ start?: string;
25
+ end?: string;
26
+ }[];
27
+ affectedLines: string[];
28
+ affectedStations: string[];
29
+ affectedStationsLabels: string[];
30
+ }
31
+ export declare function fetchWithCache<T>(endpoint: string, ttl?: number): Promise<T>;
32
+ export declare function getStations(): Promise<Station[]>;
33
+ export declare function getDepartures(stationId: string): Promise<Departure[]>;
34
+ export declare function getAlerts(): Promise<Alert[]>;
35
+ export declare function getFavorites(): Record<string, string>;
36
+ export declare function addFavorite(id: string, alias?: string): void;
37
+ export declare function removeFavorite(idOrAlias: string): void;
38
+ export declare function resolveAlias(input: string): string;
39
+ //# sourceMappingURL=api.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AA0BA,MAAM,WAAW,OAAO;IACtB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B,KAAK,EAAE,MAAM,EAAE,CAAC;CACjB;AAED,MAAM,WAAW,SAAS;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,WAAW,EAAE,MAAM,CAAC;IACpB,aAAa,EAAE,MAAM,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,KAAK;IACpB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAClD,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,sBAAsB,EAAE,MAAM,EAAE,CAAC;CAClC;AAED,wBAAsB,cAAc,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,GAAE,MAAkB,GAAG,OAAO,CAAC,CAAC,CAAC,CAgB7F;AAED,wBAAsB,WAAW,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC,CActD;AAED,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC,CAE3E;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC,CAElD;AAED,wBAAgB,YAAY,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAErD;AAED,wBAAgB,WAAW,CAAC,EAAE,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,QAIrD;AAED,wBAAgB,cAAc,CAAC,SAAS,EAAE,MAAM,QAa/C;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAMlD"}
package/dist/api.js ADDED
@@ -0,0 +1,97 @@
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.fetchWithCache = fetchWithCache;
7
+ exports.getStations = getStations;
8
+ exports.getDepartures = getDepartures;
9
+ exports.getAlerts = getAlerts;
10
+ exports.getFavorites = getFavorites;
11
+ exports.addFavorite = addFavorite;
12
+ exports.removeFavorite = removeFavorite;
13
+ exports.resolveAlias = resolveAlias;
14
+ const conf_1 = __importDefault(require("conf"));
15
+ const path_1 = __importDefault(require("path"));
16
+ const fs_1 = __importDefault(require("fs"));
17
+ const os_1 = __importDefault(require("os"));
18
+ const API_BASE = 'https://metroflow.ainslie.digital/api/v1';
19
+ const CACHE_TTL = 60 * 1000; // 60 seconds in ms
20
+ const STATIONS_CACHE_TTL = 7 * 24 * 3600 * 1000; // 7 days in ms
21
+ const config = new conf_1.default({
22
+ projectName: 'gotrain',
23
+ defaults: {
24
+ favorites: {},
25
+ lastStationsUpdate: 0,
26
+ }
27
+ });
28
+ const cacheDir = path_1.default.join(os_1.default.homedir(), '.cache', 'gotrain');
29
+ if (!fs_1.default.existsSync(cacheDir)) {
30
+ fs_1.default.mkdirSync(cacheDir, { recursive: true });
31
+ }
32
+ async function fetchWithCache(endpoint, ttl = CACHE_TTL) {
33
+ const cacheKey = endpoint.replace(/\//g, '-');
34
+ const cacheFile = path_1.default.join(cacheDir, `${cacheKey}.json`);
35
+ const now = Date.now();
36
+ if (fs_1.default.existsSync(cacheFile)) {
37
+ const stats = fs_1.default.statSync(cacheFile);
38
+ if (now - stats.mtimeMs < ttl) {
39
+ return JSON.parse(fs_1.default.readFileSync(cacheFile, 'utf-8'));
40
+ }
41
+ }
42
+ const response = await fetch(`${API_BASE}${endpoint}`);
43
+ const data = await response.json();
44
+ fs_1.default.writeFileSync(cacheFile, JSON.stringify(data));
45
+ return data;
46
+ }
47
+ async function getStations() {
48
+ const now = Date.now();
49
+ const lastUpdate = config.get('lastStationsUpdate');
50
+ const stationsFile = path_1.default.join(cacheDir, 'stations.json');
51
+ if (fs_1.default.existsSync(stationsFile) && (now - lastUpdate < STATIONS_CACHE_TTL)) {
52
+ return JSON.parse(fs_1.default.readFileSync(stationsFile, 'utf-8'));
53
+ }
54
+ const response = await fetch(`${API_BASE}/stations`);
55
+ const data = await response.json();
56
+ fs_1.default.writeFileSync(stationsFile, JSON.stringify(data));
57
+ config.set('lastStationsUpdate', now);
58
+ return data;
59
+ }
60
+ async function getDepartures(stationId) {
61
+ return fetchWithCache(`/departures/${stationId}`);
62
+ }
63
+ async function getAlerts() {
64
+ return fetchWithCache('/alerts?activeNow=true&includeLabels=true');
65
+ }
66
+ function getFavorites() {
67
+ return config.get('favorites');
68
+ }
69
+ function addFavorite(id, alias) {
70
+ const favorites = config.get('favorites');
71
+ favorites[id] = alias || '';
72
+ config.set('favorites', favorites);
73
+ }
74
+ function removeFavorite(idOrAlias) {
75
+ const favorites = config.get('favorites');
76
+ // Check if it's an ID
77
+ if (favorites[idOrAlias] !== undefined) {
78
+ delete favorites[idOrAlias];
79
+ }
80
+ else {
81
+ // Check if it's an alias
82
+ const id = Object.keys(favorites).find(key => favorites[key] === idOrAlias);
83
+ if (id) {
84
+ delete favorites[id];
85
+ }
86
+ }
87
+ config.set('favorites', favorites);
88
+ }
89
+ function resolveAlias(input) {
90
+ const favorites = config.get('favorites');
91
+ // If it's an alias, return the ID
92
+ const id = Object.keys(favorites).find(key => favorites[key] === input);
93
+ if (id)
94
+ return id;
95
+ return input;
96
+ }
97
+ //# sourceMappingURL=api.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ export declare function cmdAlerts(options: {
2
+ station?: string;
3
+ all?: boolean;
4
+ }): Promise<void>;
5
+ //# sourceMappingURL=alerts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alerts.d.ts","sourceRoot":"","sources":["../../src/commands/alerts.ts"],"names":[],"mappings":"AAIA,wBAAsB,SAAS,CAAC,OAAO,EAAE;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,OAAO,CAAA;CAAE,iBAwF3E"}
@@ -0,0 +1,85 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cmdAlerts = cmdAlerts;
4
+ const api_1 = require("../api");
5
+ const utils_1 = require("../utils");
6
+ async function cmdAlerts(options) {
7
+ const alerts = await (0, api_1.getAlerts)();
8
+ let filterId = '';
9
+ let filterName = '';
10
+ if (options.station) {
11
+ filterId = (0, api_1.resolveAlias)(options.station);
12
+ const stations = await (0, api_1.getStations)();
13
+ const station = stations.find(s => s.id === filterId);
14
+ filterName = station ? station.name : options.station;
15
+ }
16
+ console.log(utils_1.colors.bold(utils_1.colors.yellow('Service Alerts')));
17
+ if (filterName) {
18
+ console.log(`Filtering for: ${utils_1.colors.bold(filterName)}`);
19
+ }
20
+ console.log(utils_1.colors.dim('──────────────────────────────────────────────────────────'));
21
+ let filteredAlerts = alerts;
22
+ if (filterId) {
23
+ filteredAlerts = alerts.filter(a => a.affectedStations.includes(filterId) ||
24
+ (filterName && a.affectedStationsLabels.some(label => label.toLowerCase().includes(filterName.toLowerCase()))));
25
+ }
26
+ // Deduplicate by title
27
+ const uniqueAlerts = Array.from(new Map(filteredAlerts.map(a => [a.title, a])).values());
28
+ // Sort by start time (newest first)
29
+ uniqueAlerts.sort((a, b) => {
30
+ const startA = a.activePeriods[0]?.start ? new Date(a.activePeriods[0].start).getTime() : 0;
31
+ const startB = b.activePeriods[0]?.start ? new Date(b.activePeriods[0].start).getTime() : 0;
32
+ return startB - startA;
33
+ });
34
+ const total = uniqueAlerts.length;
35
+ const limit = options.all ? total : 5;
36
+ const displayAlerts = uniqueAlerts.slice(0, limit);
37
+ if (total > 0) {
38
+ if (options.all) {
39
+ console.log(utils_1.colors.dim(`Showing all ${utils_1.colors.bold(total.toString())} distinct active alerts.`));
40
+ }
41
+ else {
42
+ console.log(utils_1.colors.dim(`Showing top ${utils_1.colors.bold(displayAlerts.length.toString())} of ${utils_1.colors.bold(total.toString())} distinct active alerts.`));
43
+ }
44
+ console.log('');
45
+ }
46
+ else {
47
+ console.log('No active alerts found.');
48
+ return;
49
+ }
50
+ displayAlerts.forEach(a => {
51
+ const start = a.activePeriods[0]?.start;
52
+ const end = a.activePeriods[0]?.end;
53
+ let timeInfo = '';
54
+ if (start) {
55
+ const startFmt = (0, utils_1.formatTime)(start, 'MMM dd h:mm a');
56
+ timeInfo = `🕒 ${utils_1.colors.dim('Start:')} ${startFmt}`;
57
+ }
58
+ if (end) {
59
+ const endFmt = (0, utils_1.formatTime)(end, 'MMM dd h:mm a');
60
+ timeInfo += ` ${utils_1.colors.dim('End:')} ${endFmt}`;
61
+ }
62
+ let scopeInfo = '';
63
+ if (a.affectedLines.length > 0) {
64
+ scopeInfo = utils_1.colors.magenta(`Lines: ${a.affectedLines.join(', ')}`);
65
+ }
66
+ else if (a.affectedStationsLabels.length > 0) {
67
+ let stations = a.affectedStationsLabels.join(', ');
68
+ if (stations.length > 50)
69
+ stations = stations.substring(0, 47) + '...';
70
+ scopeInfo = utils_1.colors.magenta(`Stations: ${stations}`);
71
+ }
72
+ else {
73
+ scopeInfo = utils_1.colors.dim('General');
74
+ }
75
+ console.log(`${utils_1.colors.yellow('⚠️')} ${utils_1.colors.bold(a.title)}`);
76
+ console.log(` ${timeInfo} • ${scopeInfo}`);
77
+ if (a.description) {
78
+ console.log(` ${utils_1.colors.dim('────────────────────────────────────────────────')}`);
79
+ const cleanDesc = a.description.replace(/\n/g, '\n ');
80
+ console.log(` ${cleanDesc}`);
81
+ }
82
+ console.log('');
83
+ });
84
+ }
85
+ //# sourceMappingURL=alerts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alerts.js","sourceRoot":"","sources":["../../src/commands/alerts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function cmdBoard(stationId: string, mode: 'departures' | 'arrivals', filterId?: string): Promise<void>;
2
+ //# sourceMappingURL=board.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.d.ts","sourceRoot":"","sources":["../../src/commands/board.ts"],"names":[],"mappings":"AAsCA,wBAAsB,QAAQ,CAC1B,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,YAAY,GAAG,UAAU,EAC/B,QAAQ,CAAC,EAAE,MAAM,iBAmJpB"}
@@ -0,0 +1,147 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cmdBoard = cmdBoard;
4
+ const api_1 = require("../api");
5
+ const utils_1 = require("../utils");
6
+ function normalizeStationName(name) {
7
+ return name.trim().toLowerCase();
8
+ }
9
+ function resolveStationIdByName(stations, stationName, preferredSystem) {
10
+ const normalizedName = normalizeStationName(stationName);
11
+ const exactMatches = stations.filter(s => normalizeStationName(s.name) === normalizedName);
12
+ if (preferredSystem) {
13
+ const sameSystemMatches = exactMatches.filter(s => s.system === preferredSystem);
14
+ if (sameSystemMatches.length > 0)
15
+ return sameSystemMatches[0].id;
16
+ }
17
+ return exactMatches[0]?.id;
18
+ }
19
+ function formatRideDuration(startTime, endTime) {
20
+ if (!startTime || !endTime)
21
+ return undefined;
22
+ const diffMs = new Date(endTime).getTime() - new Date(startTime).getTime();
23
+ if (!Number.isFinite(diffMs) || diffMs <= 0)
24
+ return undefined;
25
+ const totalMinutes = Math.round(diffMs / 60000);
26
+ const hours = Math.floor(totalMinutes / 60);
27
+ const minutes = totalMinutes % 60;
28
+ if (hours === 0)
29
+ return `${minutes}m`;
30
+ return `${hours}h ${String(minutes).padStart(2, '0')}m`;
31
+ }
32
+ async function cmdBoard(stationId, mode, filterId) {
33
+ const resolvedId = (0, api_1.resolveAlias)(stationId);
34
+ const resolvedFilterId = filterId ? (0, api_1.resolveAlias)(filterId) : undefined;
35
+ const stations = await (0, api_1.getStations)();
36
+ const station = stations.find(s => s.id === resolvedId);
37
+ const stationName = station ? station.name : resolvedId;
38
+ const filterStation = resolvedFilterId ? stations.find(s => s.id === resolvedFilterId) : undefined;
39
+ const filterName = filterStation ? filterStation.name : resolvedFilterId;
40
+ let departures = await (0, api_1.getDepartures)(resolvedId);
41
+ // Filter based on mode
42
+ if (mode === 'departures') {
43
+ departures = departures.filter(d => d.destination !== stationName);
44
+ }
45
+ else {
46
+ departures = departures.filter(d => d.destination === stationName);
47
+ }
48
+ // Filter by destination/origin if provided
49
+ if (resolvedFilterId && filterName) {
50
+ if (mode === 'departures') {
51
+ departures = departures.filter(d => d.destination.toLowerCase().includes(filterName.toLowerCase()));
52
+ }
53
+ else {
54
+ // Arrivals origin filter logic (from bash script)
55
+ departures = departures.filter(d => {
56
+ const routeMatch = (d.routeLongName?.toLowerCase().includes(filterName.toLowerCase()) ||
57
+ d.routeShortName?.toLowerCase().includes(filterName.toLowerCase()));
58
+ // Hub logic from bash
59
+ const isHub = resolvedFilterId === 'MNR-1' || resolvedFilterId === 'LIRR-1';
60
+ if (isHub && d.direction === 'Outbound')
61
+ return true;
62
+ return routeMatch;
63
+ });
64
+ }
65
+ }
66
+ // Sort by departure time
67
+ departures.sort((a, b) => new Date(a.departureTime).getTime() - new Date(b.departureTime).getTime());
68
+ const tripLookups = new Map();
69
+ if (mode === 'departures') {
70
+ const destinationStationIds = Array.from(new Set(departures
71
+ .map(d => resolveStationIdByName(stations, d.destination, station?.system))
72
+ .filter((id) => Boolean(id))));
73
+ const destinationBoards = await Promise.all(destinationStationIds.map(async (id) => [id, await (0, api_1.getDepartures)(id)]));
74
+ destinationBoards.forEach(([id, board]) => {
75
+ tripLookups.set(id, new Map(board
76
+ .filter(item => Boolean(item.tripId))
77
+ .map(item => [item.tripId, item])));
78
+ });
79
+ }
80
+ if (mode === 'arrivals' && resolvedFilterId) {
81
+ const originBoard = await (0, api_1.getDepartures)(resolvedFilterId);
82
+ tripLookups.set(resolvedFilterId, new Map(originBoard
83
+ .filter(item => Boolean(item.tripId))
84
+ .map(item => [item.tripId, item])));
85
+ }
86
+ const title = mode === 'departures' ? 'Departures' : 'Arrivals';
87
+ console.log(`${utils_1.colors.bold(utils_1.colors.blue(title))} for ${utils_1.colors.bold(`${stationName} (${resolvedId})`)}`);
88
+ if (filterName) {
89
+ const label = mode === 'departures' ? 'Destination' : 'Origin';
90
+ console.log(utils_1.colors.dim(`${label}: ${filterName} (${resolvedFilterId})`));
91
+ }
92
+ console.log(utils_1.colors.dim('──────────────────────────────────────────────────────────'));
93
+ departures.forEach(d => {
94
+ const timeFmt = (0, utils_1.formatTime)(d.departureTime);
95
+ const metadata = [];
96
+ let statusColor = utils_1.colors.green;
97
+ if (d.status.includes('Delayed'))
98
+ statusColor = utils_1.colors.yellow;
99
+ else if (d.status.includes('Cancel'))
100
+ statusColor = utils_1.colors.red;
101
+ else if (d.status.includes('Due'))
102
+ statusColor = utils_1.colors.green;
103
+ let destDisplay = d.destination;
104
+ if (mode === 'arrivals') {
105
+ let originGuess = '';
106
+ if (d.direction === 'Outbound') {
107
+ if (resolvedId.startsWith('MNR'))
108
+ originGuess = 'Grand Central';
109
+ if (resolvedId.startsWith('LIRR'))
110
+ originGuess = 'New York';
111
+ }
112
+ if (originGuess === stationName)
113
+ originGuess = '';
114
+ if (d.destination === stationName) {
115
+ destDisplay = originGuess ? `From ${originGuess}` : d.destination;
116
+ }
117
+ else {
118
+ destDisplay = originGuess ? `${originGuess} ➤ ${d.destination}` : `Continues to ${d.destination}`;
119
+ }
120
+ }
121
+ if (mode === 'departures') {
122
+ const destinationStationId = resolveStationIdByName(stations, d.destination, station?.system);
123
+ const destinationStop = destinationStationId ? tripLookups.get(destinationStationId)?.get(d.tripId ?? '') : undefined;
124
+ const rideDuration = formatRideDuration(d.departureTime, destinationStop?.departureTime);
125
+ if (rideDuration)
126
+ metadata.push(utils_1.colors.dim(`Ride ${rideDuration}`));
127
+ }
128
+ if (mode === 'arrivals' && resolvedFilterId) {
129
+ const originStop = tripLookups.get(resolvedFilterId)?.get(d.tripId ?? '');
130
+ if (originStop) {
131
+ metadata.push(utils_1.colors.dim(`Dep ${(0, utils_1.formatTime)(originStop.departureTime)}`));
132
+ const rideDuration = formatRideDuration(originStop.departureTime, d.departureTime);
133
+ if (rideDuration)
134
+ metadata.push(utils_1.colors.dim(`Ride ${rideDuration}`));
135
+ }
136
+ }
137
+ const peakStr = d.peakStatus && d.peakStatus !== 'null' ? ` ${utils_1.colors.dim(`(${d.peakStatus})`)}` : '';
138
+ const lineInfo = d.routeLongName && d.routeLongName !== 'null' ? ` ${utils_1.colors.magenta(`[Line: ${d.routeLongName}]`)}` : '';
139
+ const metadataStr = metadata.length > 0 ? ` ${utils_1.colors.dim('•')} ${metadata.join(` ${utils_1.colors.dim('•')} `)}` : '';
140
+ console.log(`${utils_1.colors.cyan(timeFmt.padEnd(15))} ${utils_1.colors.dim('│')} ${utils_1.colors.bold(destDisplay)}${peakStr}${lineInfo}`);
141
+ const trackDisplay = d.track && d.track !== '-' && d.track !== 'null' ? `Track ${utils_1.colors.bold(d.track)}` : utils_1.colors.dim('No Track');
142
+ const tripDisplay = d.tripId ? ` ${utils_1.colors.dim(`(Train #${d.tripId})`)}` : '';
143
+ console.log(` ${utils_1.colors.dim('│')} ${statusColor(d.status.padEnd(14))} ${trackDisplay}${metadataStr}${tripDisplay}`);
144
+ console.log('');
145
+ });
146
+ }
147
+ //# sourceMappingURL=board.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"board.js","sourceRoot":"","sources":["../../src/commands/board.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function cmdFavorite(subcmd: string, id?: string, alias?: string): Promise<void>;
2
+ export declare function cmdFavs(): Promise<void>;
3
+ //# sourceMappingURL=favorites.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"favorites.d.ts","sourceRoot":"","sources":["../../src/commands/favorites.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW,CAAC,MAAM,EAAE,MAAM,EAAE,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,iBAgC5E;AAED,wBAAsB,OAAO,kBA2B5B"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cmdFavorite = cmdFavorite;
4
+ exports.cmdFavs = cmdFavs;
5
+ const api_1 = require("../api");
6
+ const utils_1 = require("../utils");
7
+ async function cmdFavorite(subcmd, id, alias) {
8
+ if (subcmd === 'add') {
9
+ if (!id) {
10
+ console.error(utils_1.colors.red('Usage: gotrain favs add <station-id> [alias]'));
11
+ process.exit(1);
12
+ }
13
+ (0, api_1.addFavorite)(id, alias);
14
+ console.log(`${utils_1.colors.green('Added/Updated')} ${utils_1.colors.bold(id)} ${utils_1.colors.green('to favorites')}${alias ? ` with alias '${utils_1.colors.bold(alias)}'` : ''} ${utils_1.colors.green('✅')}`);
15
+ return;
16
+ }
17
+ if (subcmd === 'remove' || subcmd === 'rm') {
18
+ if (!id) {
19
+ console.error(utils_1.colors.red('Usage: gotrain favs rm <station-id|alias>'));
20
+ process.exit(1);
21
+ }
22
+ const resolved = (0, api_1.resolveAlias)(id);
23
+ (0, api_1.removeFavorite)(resolved);
24
+ console.log(`${utils_1.colors.red('Removed')} ${utils_1.colors.bold(resolved)} ${utils_1.colors.red('from favorites')} 🗑️`);
25
+ return;
26
+ }
27
+ // Toggle behavior for convenience
28
+ const favorites = (0, api_1.getFavorites)();
29
+ const resolved = (0, api_1.resolveAlias)(subcmd);
30
+ if (favorites[resolved] !== undefined) {
31
+ (0, api_1.removeFavorite)(resolved);
32
+ console.log(`${utils_1.colors.red('Removed')} ${utils_1.colors.bold(resolved)} ${utils_1.colors.red('from favorites')} 🗑️`);
33
+ }
34
+ else {
35
+ (0, api_1.addFavorite)(resolved, id); // id here would be alias
36
+ console.log(`${utils_1.colors.green('Added')} ${utils_1.colors.bold(resolved)} ${utils_1.colors.green('to favorites')}${id ? ` (Alias: ${id})` : ''} ✅`);
37
+ }
38
+ }
39
+ async function cmdFavs() {
40
+ console.log(utils_1.colors.bold(utils_1.colors.blue('Favorite Stations')));
41
+ console.log(utils_1.colors.dim('──────────────────────────────────────────────────────────'));
42
+ const favorites = (0, api_1.getFavorites)();
43
+ const stationIds = Object.keys(favorites);
44
+ if (stationIds.length === 0) {
45
+ console.log("No favorites yet. Use 'gotrain favs add <id>' to add.");
46
+ return;
47
+ }
48
+ const stations = await (0, api_1.getStations)();
49
+ stationIds.forEach(id => {
50
+ const station = stations.find(s => s.id === id);
51
+ if (station) {
52
+ const alias = favorites[id];
53
+ const aliasDisplay = alias ? ` ${utils_1.colors.magenta(`(Alias: ${alias})`)}` : '';
54
+ const sysIcon = (0, utils_1.getSystemIcon)(station.system);
55
+ console.log(`${sysIcon} ${utils_1.colors.bold(station.system.padEnd(6))} | ${station.name} ${utils_1.colors.dim(`(${station.id})`)}${aliasDisplay}`);
56
+ }
57
+ else {
58
+ // In case station is no longer in the cache but in favorites
59
+ console.log(` Unknown | ${id} ${favorites[id] ? utils_1.colors.magenta(`(Alias: ${favorites[id]})`) : ''}`);
60
+ }
61
+ });
62
+ }
63
+ //# sourceMappingURL=favorites.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"favorites.js","sourceRoot":"","sources":["../../src/commands/favorites.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare function cmdStations(query?: string): Promise<void>;
2
+ //# sourceMappingURL=stations.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stations.d.ts","sourceRoot":"","sources":["../../src/commands/stations.ts"],"names":[],"mappings":"AAIA,wBAAsB,WAAW,CAAC,KAAK,CAAC,EAAE,MAAM,iBAkB/C"}
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.cmdStations = cmdStations;
4
+ const api_1 = require("../api");
5
+ const utils_1 = require("../utils");
6
+ async function cmdStations(query) {
7
+ const stations = await (0, api_1.getStations)();
8
+ console.log(utils_1.colors.bold(utils_1.colors.blue('NYC Transit Stations')));
9
+ console.log(utils_1.colors.dim('──────────────────────────────────────────────────────────'));
10
+ const filteredStations = query
11
+ ? stations.filter(s => s.name.toLowerCase().includes(query.toLowerCase()))
12
+ : stations;
13
+ filteredStations.forEach(s => {
14
+ const sysIcon = (0, utils_1.getSystemIcon)(s.system);
15
+ const accessIcon = (0, utils_1.getAccessIcon)(s.accessibilityStatus);
16
+ const locInfo = s.borough && s.borough !== 'null' ? utils_1.colors.dim(`(${s.borough})`) : '';
17
+ const linesInfo = s.lines.length > 0 ? ` ${utils_1.colors.magenta('Lines: ' + s.lines.join(','))}` : '';
18
+ console.log(`${sysIcon} ${utils_1.colors.bold(s.system)} │ ${s.name} ${locInfo}${linesInfo}${accessIcon} ${utils_1.colors.dim('ID: ' + s.id)}`);
19
+ });
20
+ }
21
+ //# sourceMappingURL=stations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stations.js","sourceRoot":"","sources":["../../src/commands/stations.ts"],"names":[],"mappings":";;AAIA,kCAkBC;AArBD,gCAA8C;AAC9C,oCAAgE;AAEzD,KAAK,UAAU,WAAW,CAAC,KAAc;IAC5C,MAAM,QAAQ,GAAG,MAAM,IAAA,iBAAW,GAAE,CAAC;IAErC,OAAO,CAAC,GAAG,CAAC,cAAM,CAAC,IAAI,CAAC,cAAM,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC;IAC9D,OAAO,CAAC,GAAG,CAAC,cAAM,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC,CAAC;IAEtF,MAAM,gBAAgB,GAAG,KAAK;QAC1B,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,CAAC;QAC1E,CAAC,CAAC,QAAQ,CAAC;IAEf,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QACzB,MAAM,OAAO,GAAG,IAAA,qBAAa,EAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,UAAU,GAAG,IAAA,qBAAa,EAAC,CAAC,CAAC,mBAAmB,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,KAAK,MAAM,CAAC,CAAC,CAAC,cAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,OAAO,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACtF,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,cAAM,CAAC,OAAO,CAAC,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAEhG,OAAO,CAAC,GAAG,CAAC,GAAG,OAAO,IAAI,cAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,OAAO,GAAG,SAAS,GAAG,UAAU,IAAI,cAAM,CAAC,GAAG,CAAC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;IACpI,CAAC,CAAC,CAAC;AACP,CAAC"}
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
package/dist/index.js ADDED
@@ -0,0 +1,100 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ const commander_1 = require("commander");
5
+ const stations_1 = require("./commands/stations");
6
+ const board_1 = require("./commands/board");
7
+ const alerts_1 = require("./commands/alerts");
8
+ const favorites_1 = require("./commands/favorites");
9
+ const program = new commander_1.Command();
10
+ const pkg = require('../package.json');
11
+ program
12
+ .name('gotrain')
13
+ .description('Atomic CLI for NYC train departures (MTA, LIRR, MNR)')
14
+ .version(pkg.version);
15
+ program
16
+ .command('stations')
17
+ .alias('s')
18
+ .description('List stations (filter by query)')
19
+ .argument('[query]', 'filter stations by name')
20
+ .action(async (query) => {
21
+ try {
22
+ await (0, stations_1.cmdStations)(query);
23
+ }
24
+ catch (err) {
25
+ console.error('Error fetching stations:', err instanceof Error ? err.message : err);
26
+ }
27
+ });
28
+ program
29
+ .command('departures')
30
+ .alias('d')
31
+ .description('Show departures')
32
+ .argument('<id>', 'station ID or alias')
33
+ .option('--to <id>', 'destination station ID or alias')
34
+ .action(async (id, options) => {
35
+ try {
36
+ await (0, board_1.cmdBoard)(id, 'departures', options.to);
37
+ }
38
+ catch (err) {
39
+ console.error('Error fetching departures:', err instanceof Error ? err.message : err);
40
+ }
41
+ });
42
+ program
43
+ .command('arrivals')
44
+ .alias('ar')
45
+ .description('Show arrivals')
46
+ .argument('<id>', 'station ID or alias')
47
+ .option('--from <id>', 'origin station ID or alias')
48
+ .action(async (id, options) => {
49
+ try {
50
+ await (0, board_1.cmdBoard)(id, 'arrivals', options.from);
51
+ }
52
+ catch (err) {
53
+ console.error('Error fetching arrivals:', err instanceof Error ? err.message : err);
54
+ }
55
+ });
56
+ program
57
+ .command('alerts')
58
+ .alias('a')
59
+ .description('Show active service alerts')
60
+ .option('-s, --station <id>', 'filter by station ID or alias')
61
+ .option('--all', 'show all alerts instead of top 5')
62
+ .action(async (options) => {
63
+ try {
64
+ await (0, alerts_1.cmdAlerts)(options);
65
+ }
66
+ catch (err) {
67
+ console.error('Error fetching alerts:', err instanceof Error ? err.message : err);
68
+ }
69
+ });
70
+ program
71
+ .command('favs')
72
+ .alias('fav')
73
+ .description('Manage favorite stations (list, add, remove)')
74
+ .argument('[subcmd|id]', 'subcommand (add, remove, rm) or station ID')
75
+ .argument('[id|alias]', 'station ID for add/remove, or alias if toggle')
76
+ .argument('[alias]', 'alias if add/remove and ID provided')
77
+ .action(async (arg1, arg2, arg3) => {
78
+ try {
79
+ if (!arg1) {
80
+ await (0, favorites_1.cmdFavs)();
81
+ }
82
+ else if (['add', 'remove', 'rm', 'list'].includes(arg1)) {
83
+ if (arg1 === 'list') {
84
+ await (0, favorites_1.cmdFavs)();
85
+ }
86
+ else {
87
+ await (0, favorites_1.cmdFavorite)(arg1, arg2, arg3);
88
+ }
89
+ }
90
+ else {
91
+ // Default toggle/fallback behavior
92
+ await (0, favorites_1.cmdFavorite)(arg1, arg2);
93
+ }
94
+ }
95
+ catch (err) {
96
+ console.error('Error managing favorites:', err instanceof Error ? err.message : err);
97
+ }
98
+ });
99
+ program.parse();
100
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import chalk from 'chalk';
2
+ export declare function formatTime(isoString: string | null | undefined, fmt?: string): string;
3
+ export declare const colors: {
4
+ bold: chalk.Chalk;
5
+ dim: chalk.Chalk;
6
+ red: chalk.Chalk;
7
+ green: chalk.Chalk;
8
+ yellow: chalk.Chalk;
9
+ blue: chalk.Chalk;
10
+ magenta: chalk.Chalk;
11
+ cyan: chalk.Chalk;
12
+ nc: chalk.Chalk;
13
+ };
14
+ export declare function getSystemIcon(system: string): string;
15
+ export declare function getAccessIcon(status?: string): string;
16
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,wBAAgB,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,EAAE,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,CAiBrF;AAED,eAAO,MAAM,MAAM;;;;;;;;;;CAUlB,CAAC;AAEF,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAOpD;AAED,wBAAgB,aAAa,CAAC,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAIrD"}
package/dist/utils.js ADDED
@@ -0,0 +1,56 @@
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.colors = void 0;
7
+ exports.formatTime = formatTime;
8
+ exports.getSystemIcon = getSystemIcon;
9
+ exports.getAccessIcon = getAccessIcon;
10
+ const chalk_1 = __importDefault(require("chalk"));
11
+ function formatTime(isoString, fmt) {
12
+ if (!isoString || isoString === 'null')
13
+ return '--';
14
+ try {
15
+ const date = new Date(isoString);
16
+ if (isNaN(date.getTime()))
17
+ return isoString;
18
+ const options = {
19
+ hour: 'numeric',
20
+ minute: '2-digit',
21
+ hour12: true,
22
+ timeZoneName: 'short'
23
+ };
24
+ return new Intl.DateTimeFormat('en-US', options).format(date);
25
+ }
26
+ catch (e) {
27
+ return isoString;
28
+ }
29
+ }
30
+ exports.colors = {
31
+ bold: chalk_1.default.bold,
32
+ dim: chalk_1.default.gray,
33
+ red: chalk_1.default.red,
34
+ green: chalk_1.default.green,
35
+ yellow: chalk_1.default.yellow,
36
+ blue: chalk_1.default.blue,
37
+ magenta: chalk_1.default.magenta,
38
+ cyan: chalk_1.default.cyan,
39
+ nc: chalk_1.default.reset,
40
+ };
41
+ function getSystemIcon(system) {
42
+ switch (system.toUpperCase()) {
43
+ case 'SUBWAY': return '🟦';
44
+ case 'LIRR': return '🟩';
45
+ case 'MNR': return '🟥';
46
+ default: return ' ';
47
+ }
48
+ }
49
+ function getAccessIcon(status) {
50
+ if (status === 'Fully Accessible')
51
+ return ' ♿';
52
+ if (status === 'Partially Accessible')
53
+ return ' ⚠️';
54
+ return '';
55
+ }
56
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":";;;;;;AAEA,gCAiBC;AAcD,sCAOC;AAED,sCAIC;AA9CD,kDAA0B;AAE1B,SAAgB,UAAU,CAAC,SAAoC,EAAE,GAAY;IACzE,IAAI,CAAC,SAAS,IAAI,SAAS,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IACpD,IAAI,CAAC;QACD,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC;QACjC,IAAI,KAAK,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAAE,OAAO,SAAS,CAAC;QAE5C,MAAM,OAAO,GAA+B;YACxC,IAAI,EAAE,SAAS;YACf,MAAM,EAAE,SAAS;YACjB,MAAM,EAAE,IAAI;YACZ,YAAY,EAAE,OAAO;SACxB,CAAC;QAEF,OAAO,IAAI,IAAI,CAAC,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IAClE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACT,OAAO,SAAS,CAAC;IACrB,CAAC;AACL,CAAC;AAEY,QAAA,MAAM,GAAG;IAClB,IAAI,EAAE,eAAK,CAAC,IAAI;IAChB,GAAG,EAAE,eAAK,CAAC,IAAI;IACf,GAAG,EAAE,eAAK,CAAC,GAAG;IACd,KAAK,EAAE,eAAK,CAAC,KAAK;IAClB,MAAM,EAAE,eAAK,CAAC,MAAM;IACpB,IAAI,EAAE,eAAK,CAAC,IAAI;IAChB,OAAO,EAAE,eAAK,CAAC,OAAO;IACtB,IAAI,EAAE,eAAK,CAAC,IAAI;IAChB,EAAE,EAAE,eAAK,CAAC,KAAK;CAClB,CAAC;AAEF,SAAgB,aAAa,CAAC,MAAc;IACxC,QAAQ,MAAM,CAAC,WAAW,EAAE,EAAE,CAAC;QAC3B,KAAK,QAAQ,CAAC,CAAC,OAAO,IAAI,CAAC;QAC3B,KAAK,MAAM,CAAC,CAAC,OAAO,IAAI,CAAC;QACzB,KAAK,KAAK,CAAC,CAAC,OAAO,IAAI,CAAC;QACxB,OAAO,CAAC,CAAC,OAAO,IAAI,CAAC;IACzB,CAAC;AACL,CAAC;AAED,SAAgB,aAAa,CAAC,MAAe;IACzC,IAAI,MAAM,KAAK,kBAAkB;QAAE,OAAO,IAAI,CAAC;IAC/C,IAAI,MAAM,KAAK,sBAAsB;QAAE,OAAO,KAAK,CAAC;IACpD,OAAO,EAAE,CAAC;AACd,CAAC"}
package/package.json ADDED
@@ -0,0 +1,66 @@
1
+ {
2
+ "name": "gotrain",
3
+ "version": "1.2.4",
4
+ "description": "Atomic CLI for MTA system train departures (NYC Subway, LIRR, Metro-North)",
5
+ "main": "dist/index.js",
6
+ "bin": {
7
+ "gotrain": "dist/index.js"
8
+ },
9
+ "files": [
10
+ "dist",
11
+ "README.md",
12
+ "CHANGELOG.md",
13
+ "LICENSE"
14
+ ],
15
+ "directories": {
16
+ "test": "tests"
17
+ },
18
+ "scripts": {
19
+ "build": "rimraf dist && tsc",
20
+ "postbuild": "chmod +x dist/index.js",
21
+ "prepublishOnly": "npm run build",
22
+ "test": "npm run build && jest",
23
+ "start": "node dist/index.js"
24
+ },
25
+ "repository": {
26
+ "type": "git",
27
+ "url": "git+https://github.com/gumadeiras/gotrain-cli.git"
28
+ },
29
+ "keywords": [
30
+ "mta",
31
+ "nyc",
32
+ "subway",
33
+ "lirr",
34
+ "mnr",
35
+ "metro-north",
36
+ "train",
37
+ "departures",
38
+ "arrivals",
39
+ "transit",
40
+ "cli",
41
+ "real-time"
42
+ ],
43
+ "author": "",
44
+ "license": "ISC",
45
+ "type": "commonjs",
46
+ "bugs": {
47
+ "url": "https://github.com/gumadeiras/gotrain-cli/issues"
48
+ },
49
+ "homepage": "https://github.com/gumadeiras/gotrain-cli#readme",
50
+ "devDependencies": {
51
+ "@types/jest": "^30.0.0",
52
+ "@types/node": "^25.0.10",
53
+ "jest": "^30.2.0",
54
+ "nock": "^14.0.10",
55
+ "rimraf": "^6.1.2",
56
+ "supertest": "^7.2.2",
57
+ "ts-jest": "^29.4.6",
58
+ "ts-node": "^10.9.2",
59
+ "typescript": "^5.9.3"
60
+ },
61
+ "dependencies": {
62
+ "chalk": "^4.1.2",
63
+ "commander": "^14.0.2",
64
+ "conf": "^10.2.0"
65
+ }
66
+ }