zet-api 1.0.0 → 1.0.2

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 CHANGED
@@ -12,7 +12,6 @@
12
12
  - ⏱️ Get **trip stop times** with live tracking
13
13
  - 📰 Access **ZET newsfeed** for service updates
14
14
  - 🚗 Track **live vehicle positions** with GPS coordinates
15
- - � **Automatic authentication** with token refresh
16
15
  - 💾 Built-in **TTL-based caching** for optimal performance
17
16
  - ✅ **Zod schema validation** for type-safe data
18
17
  - ⚡ Written in **TypeScript**, ready for Node.js (≥20.2.0)
@@ -252,6 +251,68 @@ activeNews.forEach((item) => {
252
251
 
253
252
  ---
254
253
 
254
+ ## 🌍 GTFS Data Manager
255
+
256
+ The `GTFSManager` is a separate utility for working with pre-processed GTFS (General Transit Feed Specification) data stored as JSON files. This is useful for accessing static transit data without hitting the live API.
257
+
258
+ ### Setup
259
+
260
+ ```typescript
261
+ import { GTFSManager } from "zet-api";
262
+
263
+ // Initialize with raw URL to your GTFS JSON files
264
+ const gtfs = new GTFSManager("https://digital39999.github.io/zet-api", 30000);
265
+ ```
266
+
267
+ ### Usage
268
+
269
+ ```typescript
270
+ // Get all routes
271
+ const routes = await gtfs.getGTFSRoutes();
272
+ console.log("Total routes:", Object.keys(routes).length);
273
+
274
+ // Get specific route by ID
275
+ const route = await gtfs.getGTFSRouteById("1");
276
+ console.log(route?.route_short_name); // e.g., "1"
277
+
278
+ // Get all stops
279
+ const stops = await gtfs.getGTFSStops();
280
+
281
+ // Get specific stop
282
+ const stop = await gtfs.getGTFSStopById("317_1");
283
+ console.log(stop?.stop_name);
284
+
285
+ // Get trips for a route
286
+ const trips = await gtfs.getGTFSTripsByRoute("1");
287
+
288
+ // Get stop times for a trip
289
+ const stopTimes = await gtfs.getGTFSStopTimesByTrip("0_5_105_1_10687");
290
+
291
+ // Get shape points for a trip
292
+ const shape = await gtfs.getGTFSShapeById("1_12");
293
+ console.log("Shape has", shape.length, "points");
294
+
295
+ // Refresh cache manually
296
+ await gtfs.refreshGTFSCache();
297
+
298
+ // Clear cache
299
+ gtfs.clearGTFSCache();
300
+ ```
301
+
302
+ ### GTFS Data Structure
303
+
304
+ The manager expects the following JSON files on GitHub:
305
+
306
+ - `routes.json` - Route definitions
307
+ - `stops.json` - Stop locations and info
308
+ - `trips.json` - Trip schedules (grouped by route_id)
309
+ - `stop_times.json` - Stop sequences and times (grouped by trip_id)
310
+ - `shapes.json` - Route shapes/polylines (grouped by shape_id)
311
+
312
+ All data is cached indefinitely after first fetch to minimize network requests.
313
+
314
+ ---
315
+
255
316
  ## 📄 License
256
317
 
257
318
  This project is licensed under the GPL-v3 License. See the [LICENSE](LICENSE) file for details.
@@ -88,8 +88,8 @@ export declare const AccountSchema: z.ZodObject<{
88
88
  messages: z.ZodArray<z.ZodUnknown, "many">;
89
89
  processes: z.ZodNullable<z.ZodUnknown>;
90
90
  }, "strip", z.ZodTypeAny, {
91
- email: string;
92
91
  id: number;
92
+ email: string;
93
93
  uid: string;
94
94
  firstName: string;
95
95
  lastName: string;
@@ -100,8 +100,8 @@ export declare const AccountSchema: z.ZodObject<{
100
100
  messages: unknown[];
101
101
  processes?: unknown;
102
102
  }, {
103
- email: string;
104
103
  id: number;
104
+ email: string;
105
105
  uid: string;
106
106
  firstName: string;
107
107
  lastName: string;
@@ -153,13 +153,8 @@ export declare const StopIncomingTripSchema: z.ZodObject<{
153
153
  } | undefined;
154
154
  }>, "many">;
155
155
  }, "strip", z.ZodTypeAny, {
156
- tripId: string;
157
- routeShortName: string;
158
156
  headsign: string;
159
- expectedArrivalDateTime: string;
160
157
  hasLiveTracking: boolean;
161
- daysFromToday: number;
162
- shapeId: string;
163
158
  vehicles: {
164
159
  id: string;
165
160
  isForDisabledPeople: boolean | null;
@@ -169,14 +164,14 @@ export declare const StopIncomingTripSchema: z.ZodObject<{
169
164
  longitude: number;
170
165
  } | undefined;
171
166
  }[];
172
- }, {
167
+ shapeId: string;
168
+ expectedArrivalDateTime: string;
169
+ daysFromToday: number;
173
170
  tripId: string;
174
171
  routeShortName: string;
172
+ }, {
175
173
  headsign: string;
176
- expectedArrivalDateTime: string;
177
174
  hasLiveTracking: boolean;
178
- daysFromToday: number;
179
- shapeId: string;
180
175
  vehicles: {
181
176
  id: string;
182
177
  isForDisabledPeople: boolean | null;
@@ -186,6 +181,11 @@ export declare const StopIncomingTripSchema: z.ZodObject<{
186
181
  longitude: number;
187
182
  } | undefined;
188
183
  }[];
184
+ shapeId: string;
185
+ expectedArrivalDateTime: string;
186
+ daysFromToday: number;
187
+ tripId: string;
188
+ routeShortName: string;
189
189
  }>;
190
190
  export type StopIncomingTripWithDates = Omit<StopIncomingTrip, 'expectedArrivalDateTime'> & {
191
191
  expectedArrivalDateTime: Date;
@@ -241,13 +241,8 @@ export declare const StopIncomingTripsResponseSchema: z.ZodArray<z.ZodObject<{
241
241
  } | undefined;
242
242
  }>, "many">;
243
243
  }, "strip", z.ZodTypeAny, {
244
- tripId: string;
245
- routeShortName: string;
246
244
  headsign: string;
247
- expectedArrivalDateTime: string;
248
245
  hasLiveTracking: boolean;
249
- daysFromToday: number;
250
- shapeId: string;
251
246
  vehicles: {
252
247
  id: string;
253
248
  isForDisabledPeople: boolean | null;
@@ -257,14 +252,14 @@ export declare const StopIncomingTripsResponseSchema: z.ZodArray<z.ZodObject<{
257
252
  longitude: number;
258
253
  } | undefined;
259
254
  }[];
260
- }, {
255
+ shapeId: string;
256
+ expectedArrivalDateTime: string;
257
+ daysFromToday: number;
261
258
  tripId: string;
262
259
  routeShortName: string;
260
+ }, {
263
261
  headsign: string;
264
- expectedArrivalDateTime: string;
265
262
  hasLiveTracking: boolean;
266
- daysFromToday: number;
267
- shapeId: string;
268
263
  vehicles: {
269
264
  id: string;
270
265
  isForDisabledPeople: boolean | null;
@@ -274,4 +269,9 @@ export declare const StopIncomingTripsResponseSchema: z.ZodArray<z.ZodObject<{
274
269
  longitude: number;
275
270
  } | undefined;
276
271
  }[];
272
+ shapeId: string;
273
+ expectedArrivalDateTime: string;
274
+ daysFromToday: number;
275
+ tripId: string;
276
+ routeShortName: string;
277
277
  }>, "many">;
@@ -1,5 +1,6 @@
1
1
  declare const _default: {
2
2
  baseUrl: string;
3
+ gtfsRtUrl: string;
3
4
  timetableServiceUrl: string;
4
5
  newsProxyServiceUrl: string;
5
6
  authServiceUrl: string;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.headers = void 0;
4
4
  exports.default = {
5
5
  baseUrl: 'https://api.zet.hr',
6
+ gtfsRtUrl: 'https://www.zet.hr/gtfs-rt-protobuf',
6
7
  timetableServiceUrl: 'https://api.zet.hr/TimetableService.Api/api/gtfs',
7
8
  newsProxyServiceUrl: 'https://api.zet.hr/NewsProxyService.Api/api/newsfeed',
8
9
  authServiceUrl: 'https://api.zet.hr/AuthService.Api/api/auth',
@@ -19,7 +19,21 @@ export declare enum NewsTypeEnum {
19
19
  ScheduleChange = 3,
20
20
  ServiceChange = 4
21
21
  }
22
+ export declare enum ScheduleRelationshipEnum {
23
+ Scheduled = "SCHEDULED",
24
+ Added = "ADDED",
25
+ Unscheduled = "UNSCHEDULED",
26
+ Canceled = "CANCELED",
27
+ Replacement = "REPLACEMENT",
28
+ Duplicated = "DUPLICATED"
29
+ }
30
+ export declare enum IncrementalityEnum {
31
+ FullDataSet = "FULL_DATASET",
32
+ Differential = "DIFFERENTIAL"
33
+ }
22
34
  export declare const routeTypeMap: Record<RouteTypeEnum, string>;
23
35
  export declare const directionMap: Record<DirectionEnum, string>;
24
36
  export declare const tripStatusMap: Record<TripStatusEnum, string>;
25
37
  export declare const newsTypeMap: Record<NewsTypeEnum, string>;
38
+ export declare const scheduleRelationshipMap: Record<ScheduleRelationshipEnum, string>;
39
+ export declare const incrementalityMap: Record<IncrementalityEnum, string>;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.newsTypeMap = exports.tripStatusMap = exports.directionMap = exports.routeTypeMap = exports.NewsTypeEnum = exports.TripStatusEnum = exports.DirectionEnum = exports.RouteTypeEnum = void 0;
3
+ exports.incrementalityMap = exports.scheduleRelationshipMap = exports.newsTypeMap = exports.tripStatusMap = exports.directionMap = exports.routeTypeMap = exports.IncrementalityEnum = exports.ScheduleRelationshipEnum = exports.NewsTypeEnum = exports.TripStatusEnum = exports.DirectionEnum = exports.RouteTypeEnum = void 0;
4
4
  var RouteTypeEnum;
5
5
  (function (RouteTypeEnum) {
6
6
  RouteTypeEnum[RouteTypeEnum["Tram"] = 0] = "Tram";
@@ -28,6 +28,20 @@ var NewsTypeEnum;
28
28
  NewsTypeEnum[NewsTypeEnum["ScheduleChange"] = 3] = "ScheduleChange";
29
29
  NewsTypeEnum[NewsTypeEnum["ServiceChange"] = 4] = "ServiceChange";
30
30
  })(NewsTypeEnum || (exports.NewsTypeEnum = NewsTypeEnum = {}));
31
+ var ScheduleRelationshipEnum;
32
+ (function (ScheduleRelationshipEnum) {
33
+ ScheduleRelationshipEnum["Scheduled"] = "SCHEDULED";
34
+ ScheduleRelationshipEnum["Added"] = "ADDED";
35
+ ScheduleRelationshipEnum["Unscheduled"] = "UNSCHEDULED";
36
+ ScheduleRelationshipEnum["Canceled"] = "CANCELED";
37
+ ScheduleRelationshipEnum["Replacement"] = "REPLACEMENT";
38
+ ScheduleRelationshipEnum["Duplicated"] = "DUPLICATED";
39
+ })(ScheduleRelationshipEnum || (exports.ScheduleRelationshipEnum = ScheduleRelationshipEnum = {}));
40
+ var IncrementalityEnum;
41
+ (function (IncrementalityEnum) {
42
+ IncrementalityEnum["FullDataSet"] = "FULL_DATASET";
43
+ IncrementalityEnum["Differential"] = "DIFFERENTIAL";
44
+ })(IncrementalityEnum || (exports.IncrementalityEnum = IncrementalityEnum = {}));
31
45
  exports.routeTypeMap = {
32
46
  [RouteTypeEnum.Tram]: 'Tram',
33
47
  [RouteTypeEnum.Bus]: 'Bus',
@@ -49,3 +63,15 @@ exports.newsTypeMap = {
49
63
  [NewsTypeEnum.ScheduleChange]: 'Schedule Change',
50
64
  [NewsTypeEnum.ServiceChange]: 'Service Change',
51
65
  };
66
+ exports.scheduleRelationshipMap = {
67
+ [ScheduleRelationshipEnum.Scheduled]: 'Scheduled',
68
+ [ScheduleRelationshipEnum.Added]: 'Added',
69
+ [ScheduleRelationshipEnum.Unscheduled]: 'Unscheduled',
70
+ [ScheduleRelationshipEnum.Canceled]: 'Canceled',
71
+ [ScheduleRelationshipEnum.Replacement]: 'Replacement',
72
+ [ScheduleRelationshipEnum.Duplicated]: 'Duplicated',
73
+ };
74
+ exports.incrementalityMap = {
75
+ [IncrementalityEnum.FullDataSet]: 'Full Dataset',
76
+ [IncrementalityEnum.Differential]: 'Differential',
77
+ };
@@ -1,4 +1,4 @@
1
- import { Route, Stop, News, GetRoutesInput, GetRouteTripsInput, GetStopsInput, GetTripStopTimesInput, SearchRoutesInput, SearchStopsInput, GetLiveVehiclesInput, TripWithDates, TripStopTimeWithDates, NewsWithDates, Vehicle } from './parsers';
1
+ import { Route, Stop, News, GetRoutesInput, GetRouteTripsInput, GetStopsInput, GetTripStopTimesInput, SearchRoutesInput, SearchStopsInput, TripWithDates, TripStopTimeWithDates, NewsWithDates, GTFSRTVehiclePosition } from './parsers';
2
2
  import { GetStopIncomingTripsInput, StopIncomingTripWithDates, Account } from '../auth/types';
3
3
  import { ZetAuthManager } from '../auth/manager';
4
4
  import { RouteTypeEnum } from './constants';
@@ -30,8 +30,7 @@ export declare class ZetManager {
30
30
  private getNewsfeedInternal;
31
31
  getNewsfeed(): Promise<NewsWithDates[]>;
32
32
  getNewsByRoute(routeId: number): Promise<News[]>;
33
- getLiveVehicles(options?: GetLiveVehiclesInput): Promise<Vehicle[]>;
34
- getVehicleById(vehicleId: string): Promise<Vehicle | null>;
33
+ getLiveVehicles(routeId?: number): Promise<GTFSRTVehiclePosition[]>;
35
34
  refreshCache(): Promise<void>;
36
35
  clearCache(): void;
37
36
  private fetchAndCacheRoutes;
@@ -284,31 +284,16 @@ class ZetManager {
284
284
  return news.filter((item) => item.lines.includes(routeId));
285
285
  }
286
286
  // Vehicles.
287
- async getLiveVehicles(options) {
288
- const routes = options?.routeId ? [await this.getRouteById(options.routeId)].filter((r) => r !== null) : await this.getRoutes();
289
- const vehicles = [];
290
- for (const route of routes) {
291
- try {
292
- const trips = await this.getRouteTrips({ routeId: route.id, daysFromToday: 0 });
293
- for (const trip of trips) {
294
- for (const vehicle of trip.vehicles) {
295
- if (options?.vehicleId && vehicle.id !== options.vehicleId)
296
- continue;
297
- if (vehicle.position) {
298
- vehicles.push(vehicle);
299
- }
300
- }
301
- }
302
- }
303
- catch (error) {
304
- continue;
305
- }
287
+ async getLiveVehicles(routeId) {
288
+ const response = await axios_1.default.get(config_1.default.gtfsRtUrl, { headers: config_1.headers, timeout: this.timeoutMs, responseType: 'arraybuffer' }).catch((err) => err.response);
289
+ if (!response || response.status !== 200)
290
+ throw new Error(`Failed to fetch GTFS-RT feed: ${response?.statusText || 'Unknown error'}`);
291
+ const allVehicles = (0, utils_1.parseGtfsRtVehicles)(response.data);
292
+ if (routeId !== undefined) {
293
+ const routeIdStr = routeId.toString();
294
+ return allVehicles.filter((vehicle) => vehicle.trip.routeId === routeIdStr);
306
295
  }
307
- return vehicles;
308
- }
309
- async getVehicleById(vehicleId) {
310
- const vehicles = await this.getLiveVehicles({ vehicleId });
311
- return vehicles[0] || null;
296
+ return allVehicles;
312
297
  }
313
298
  // Cache.
314
299
  async refreshCache() {