gtfs 4.18.7 → 4.19.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/dist/index.d.ts CHANGED
@@ -619,13 +619,24 @@ interface RunPiece {
619
619
  end_trip_id: string;
620
620
  end_trip_position: number | null;
621
621
  }
622
+ interface ServiceAlertInformedEntity {
623
+ alert_id: string;
624
+ stop_id: string | null;
625
+ route_id: string | null;
626
+ route_type: number | null;
627
+ trip_id: string | null;
628
+ direction_id: number | null;
629
+ created_timestamp: UnixTimestamp;
630
+ expiration_timestamp: UnixTimestamp;
631
+ }
622
632
  interface ServiceAlert {
623
633
  id: string;
634
+ active_period: string | null;
624
635
  cause: string | null;
625
636
  effect: string | null;
626
637
  url: string | null;
627
- start_time: string;
628
- end_time: string;
638
+ start_time: string | null;
639
+ end_time: string | null;
629
640
  header_text: string;
630
641
  description_text: string;
631
642
  tts_header_text: string | null;
@@ -633,6 +644,7 @@ interface ServiceAlert {
633
644
  severity_level: string | null;
634
645
  created_timestamp: UnixTimestamp;
635
646
  expiration_timestamp: UnixTimestamp;
647
+ informed_entities: ServiceAlertInformedEntity[];
636
648
  }
637
649
  interface StopTimeUpdate {
638
650
  trip_id: string | null;
@@ -965,7 +977,25 @@ declare function getTripUpdates<Fields extends keyof TripUpdate>(query?: SqlWher
965
977
 
966
978
  declare function getVehiclePositions<Fields extends keyof VehiclePosition>(query?: SqlWhere, fields?: Fields[], orderBy?: SqlOrderBy, options?: QueryOptions): QueryResult<VehiclePosition, Fields>[];
967
979
 
968
- declare function getServiceAlerts<Fields extends keyof ServiceAlert>(query?: SqlWhere, fields?: Fields[], orderBy?: SqlOrderBy, options?: QueryOptions): QueryResult<ServiceAlert, Fields>[];
980
+ declare function getServiceAlerts<Fields extends keyof ServiceAlert>(query?: SqlWhere, fields?: Fields[], orderBy?: SqlOrderBy, options?: QueryOptions): {
981
+ informed_entities: ServiceAlertInformedEntity[];
982
+ start_time: string | null;
983
+ end_time: string | null;
984
+ id: string;
985
+ created_timestamp: UnixTimestamp;
986
+ expiration_timestamp: UnixTimestamp;
987
+ active_period: string | null;
988
+ cause: string | null;
989
+ effect: string | null;
990
+ url: string | null;
991
+ header_text: string;
992
+ description_text: string;
993
+ tts_header_text: string | null;
994
+ tts_description_text: string | null;
995
+ severity_level: string | null;
996
+ }[];
997
+
998
+ declare function getServiceAlertInformedEntities<Fields extends keyof ServiceAlertInformedEntity>(query?: SqlWhere, fields?: Fields[], orderBy?: SqlOrderBy, options?: QueryOptions): QueryResult<ServiceAlertInformedEntity, Fields>[];
969
999
 
970
1000
  declare function getDeadheads<Fields extends keyof Deadhead>(query?: SqlWhere, fields?: Fields[], orderBy?: SqlOrderBy, options?: QueryOptions): QueryResult<Deadhead, Fields>[];
971
1001
 
@@ -977,4 +1007,4 @@ declare function getRunEvents<Fields extends keyof RunEvent>(query?: SqlWhere, f
977
1007
 
978
1008
  declare function getRunsPieces<Fields extends keyof RunPiece>(query?: SqlWhere, fields?: Fields[], orderBy?: SqlOrderBy, options?: QueryOptions): QueryResult<RunPiece, Fields>[];
979
1009
 
980
- export { type Agency, type Area, type Attribution, type BoardAlight, type BookingRule, type Calendar, type CalendarAttribute, type CalendarDate, type Config, type ConfigAgency, type Deadhead, type DeadheadTime, type Direction, type FareAttribute, type FareLegRule, type FareMedia, type FareProduct, type FareRule, type FareTransferRule, type FeedInfo, type Frequency, GtfsError, GtfsErrorCategory, GtfsErrorCode, type GtfsWarning, GtfsWarningCode, type ImportReport, type JoinOptions, type Level, type Location, type LocationGroup, type LocationGroupStop, type Model, type ModelColumn, type Network, type OpsLocation, type Pathway, type QueryOptions, type QueryResult, type RideFeedInfo, type RiderCategory, type RiderTrip, type Ridership, type Route, type RouteAttribute, type RouteNetwork, type RunEvent, type RunPiece, type ServiceAlert, type Shape, type SqlOrderBy, type SqlValue, type SqlWhere, type Stop, type StopArea, type StopAttribute, type StopTime, type StopTimeUpdate, type TableNames, type Timeframe, type Timetable, type TimetableNote, type TimetableNotesReference, type TimetablePage, type TimetableStopOrder, type Transfer, type Translation, type Trip, type TripCapacity, type TripUpdate, type TripsDatedVehicleJourney, type UnixTimestamp, type VehiclePosition, advancedQuery, closeDb, deleteDb, exportGtfs, formatGtfsError, generateFolderName, getAgencies, getAreas, getAttributions, getBoardAlights, getBookingRules, getCalendarAttributes, getCalendarDates, getCalendars, getDeadheadTimes, getDeadheads, getDirections, getFareAttributes, getFareLegRules, getFareMedia, getFareProducts, getFareRules, getFareTransferRules, getFeedInfo, getFrequencies, getLevels, getLocationGroupStops, getLocationGroups, getLocations, getNetworks, getOpsLocations, getPathways, getRideFeedInfo, getRiderCategories, getRiderTrips, getRidership, getRouteAttributes, getRouteNetworks, getRoutes, getRunEvents, getRunsPieces, getServiceAlerts, getServiceIdsByDate, getShapes, getShapesAsGeoJSON, getStopAreas, getStopAttributes, getStopTimeUpdates, getStops, getStopsAsGeoJSON, getStoptimes, getTimeframes, getTimetableNotes, getTimetableNotesReferences, getTimetablePages, getTimetableStopOrders, getTimetables, getTransfers, getTranslations, getTripCapacities, getTripUpdates, getTrips, getTripsDatedVehicleJourneys, getVehiclePositions, importGtfs, isGtfsError, isGtfsValidationError, openDb, prepDirectory, untildify, unzip, updateGtfsRealtime };
1010
+ export { type Agency, type Area, type Attribution, type BoardAlight, type BookingRule, type Calendar, type CalendarAttribute, type CalendarDate, type Config, type ConfigAgency, type Deadhead, type DeadheadTime, type Direction, type FareAttribute, type FareLegRule, type FareMedia, type FareProduct, type FareRule, type FareTransferRule, type FeedInfo, type Frequency, GtfsError, GtfsErrorCategory, GtfsErrorCode, type GtfsWarning, GtfsWarningCode, type ImportReport, type JoinOptions, type Level, type Location, type LocationGroup, type LocationGroupStop, type Model, type ModelColumn, type Network, type OpsLocation, type Pathway, type QueryOptions, type QueryResult, type RideFeedInfo, type RiderCategory, type RiderTrip, type Ridership, type Route, type RouteAttribute, type RouteNetwork, type RunEvent, type RunPiece, type ServiceAlert, type ServiceAlertInformedEntity, type Shape, type SqlOrderBy, type SqlValue, type SqlWhere, type Stop, type StopArea, type StopAttribute, type StopTime, type StopTimeUpdate, type TableNames, type Timeframe, type Timetable, type TimetableNote, type TimetableNotesReference, type TimetablePage, type TimetableStopOrder, type Transfer, type Translation, type Trip, type TripCapacity, type TripUpdate, type TripsDatedVehicleJourney, type UnixTimestamp, type VehiclePosition, advancedQuery, closeDb, deleteDb, exportGtfs, formatGtfsError, generateFolderName, getAgencies, getAreas, getAttributions, getBoardAlights, getBookingRules, getCalendarAttributes, getCalendarDates, getCalendars, getDeadheadTimes, getDeadheads, getDirections, getFareAttributes, getFareLegRules, getFareMedia, getFareProducts, getFareRules, getFareTransferRules, getFeedInfo, getFrequencies, getLevels, getLocationGroupStops, getLocationGroups, getLocations, getNetworks, getOpsLocations, getPathways, getRideFeedInfo, getRiderCategories, getRiderTrips, getRidership, getRouteAttributes, getRouteNetworks, getRoutes, getRunEvents, getRunsPieces, getServiceAlertInformedEntities, getServiceAlerts, getServiceIdsByDate, getShapes, getShapesAsGeoJSON, getStopAreas, getStopAttributes, getStopTimeUpdates, getStops, getStopsAsGeoJSON, getStoptimes, getTimeframes, getTimetableNotes, getTimetableNotesReferences, getTimetablePages, getTimetableStopOrders, getTimetables, getTransfers, getTranslations, getTripCapacities, getTripUpdates, getTrips, getTripsDatedVehicleJourneys, getVehiclePositions, importGtfs, isGtfsError, isGtfsValidationError, openDb, prepDirectory, untildify, unzip, updateGtfsRealtime };
package/dist/index.js CHANGED
@@ -1006,6 +1006,7 @@ var routes = {
1006
1006
  {
1007
1007
  name: "agency_id",
1008
1008
  type: "text",
1009
+ index: true,
1009
1010
  prefix: true
1010
1011
  },
1011
1012
  {
@@ -1258,7 +1259,8 @@ var stops = {
1258
1259
  },
1259
1260
  {
1260
1261
  name: "stop_code",
1261
- type: "text"
1262
+ type: "text",
1263
+ index: true
1262
1264
  },
1263
1265
  {
1264
1266
  name: "stop_name",
@@ -2760,16 +2762,14 @@ var serviceAlerts = {
2760
2762
  {
2761
2763
  name: "start_time",
2762
2764
  type: "text",
2763
- required: true,
2764
2765
  source: "alert.activePeriod[0].start",
2765
- default: ""
2766
+ default: null
2766
2767
  },
2767
2768
  {
2768
2769
  name: "end_time",
2769
2770
  type: "text",
2770
- required: true,
2771
2771
  source: "alert.activePeriod[0].end",
2772
- default: ""
2772
+ default: null
2773
2773
  },
2774
2774
  {
2775
2775
  name: "header_text",
@@ -2829,7 +2829,7 @@ var serviceAlertInformedEntities = {
2829
2829
  {
2830
2830
  name: "stop_id",
2831
2831
  type: "text",
2832
- index: true,
2832
+ primary: true,
2833
2833
  source: "stopId",
2834
2834
  default: null,
2835
2835
  prefix: true
@@ -2837,7 +2837,7 @@ var serviceAlertInformedEntities = {
2837
2837
  {
2838
2838
  name: "route_id",
2839
2839
  type: "text",
2840
- index: true,
2840
+ primary: true,
2841
2841
  source: "routeId",
2842
2842
  default: null,
2843
2843
  prefix: true
@@ -2845,14 +2845,14 @@ var serviceAlertInformedEntities = {
2845
2845
  {
2846
2846
  name: "route_type",
2847
2847
  type: "integer",
2848
- index: true,
2848
+ primary: true,
2849
2849
  source: "routeType",
2850
2850
  default: null
2851
2851
  },
2852
2852
  {
2853
2853
  name: "trip_id",
2854
2854
  type: "text",
2855
- index: true,
2855
+ primary: true,
2856
2856
  source: "trip.tripId",
2857
2857
  default: null,
2858
2858
  prefix: true
@@ -2860,7 +2860,7 @@ var serviceAlertInformedEntities = {
2860
2860
  {
2861
2861
  name: "direction_id",
2862
2862
  type: "integer",
2863
- index: true,
2863
+ primary: true,
2864
2864
  source: "directionId",
2865
2865
  default: null
2866
2866
  },
@@ -3377,7 +3377,8 @@ var passengerEvents = {
3377
3377
  {
3378
3378
  name: "trip_stop_sequence",
3379
3379
  type: "integer",
3380
- min: 1
3380
+ min: 1,
3381
+ required: true
3381
3382
  },
3382
3383
  {
3383
3384
  name: "scheduled_stop_sequence",
@@ -3603,7 +3604,8 @@ var stopVisits = {
3603
3604
  },
3604
3605
  {
3605
3606
  name: "ramp_deployed_time",
3606
- type: "text"
3607
+ type: "real",
3608
+ min: 0
3607
3609
  },
3608
3610
  {
3609
3611
  name: "ramp_failure",
@@ -3611,12 +3613,12 @@ var stopVisits = {
3611
3613
  },
3612
3614
  {
3613
3615
  name: "kneel_deployed_time",
3614
- type: "integer",
3616
+ type: "real",
3615
3617
  min: 0
3616
3618
  },
3617
3619
  {
3618
3620
  name: "lift_deployed_time",
3619
- type: "integer",
3621
+ type: "real",
3620
3622
  min: 0
3621
3623
  },
3622
3624
  {
@@ -4278,7 +4280,9 @@ function deleteDb(db = null) {
4278
4280
  db = dbs[Object.keys(dbs)[0]];
4279
4281
  }
4280
4282
  db.close();
4281
- fs.unlinkSync(db.name);
4283
+ if (db.name !== ":memory:") {
4284
+ fs.unlinkSync(db.name);
4285
+ }
4282
4286
  delete dbs[db.name];
4283
4287
  }
4284
4288
 
@@ -4588,7 +4592,7 @@ function getTimestampColumnName(columnName) {
4588
4592
  return columnName.endsWith("time") ? `${columnName}stamp` : `${columnName}_timestamp`;
4589
4593
  }
4590
4594
  function applyPrefixToValue(value, columnShouldBePrefixed, prefix) {
4591
- if (!columnShouldBePrefixed || prefix === void 0 || value === null) {
4595
+ if (!columnShouldBePrefixed || prefix === void 0 || value === null || value === void 0) {
4592
4596
  return value;
4593
4597
  }
4594
4598
  return `${prefix}${value}`;
@@ -4651,13 +4655,15 @@ async function fetchGtfsRealtimeData(type, task) {
4651
4655
  try {
4652
4656
  const response = await fetch(urlConfig.url, {
4653
4657
  method: "GET",
4658
+ redirect: "follow",
4654
4659
  headers: {
4660
+ "User-Agent": "node-gtfs",
4655
4661
  ...urlConfig.headers ?? {},
4656
4662
  "Accept-Encoding": "gzip"
4657
4663
  },
4658
4664
  signal: task.downloadTimeout ? AbortSignal.timeout(task.downloadTimeout) : void 0
4659
4665
  });
4660
- if (response.status !== 200) {
4666
+ if (!response.ok) {
4661
4667
  throw new GtfsError(`HTTP ${response.status}: ${response.statusText}`, {
4662
4668
  code: "GTFS_DOWNLOAD_HTTP" /* GTFS_DOWNLOAD_HTTP */,
4663
4669
  category: "download" /* DOWNLOAD */,
@@ -4730,12 +4736,17 @@ function createServiceAlertsProcessor(db, task) {
4730
4736
  db,
4731
4737
  serviceAlertInformedEntities
4732
4738
  );
4739
+ const deleteInformedEntitiesStmt = db.prepare(
4740
+ `DELETE FROM ${serviceAlertInformedEntities.filenameBase} WHERE alert_id = ?`
4741
+ );
4733
4742
  return async (batch) => {
4734
4743
  let recordCount = 0;
4735
4744
  let errorCount = 0;
4736
4745
  db.transaction(() => {
4737
4746
  for (const entity of batch) {
4738
4747
  try {
4748
+ const alertId = applyPrefixToValue(entity.id, true, task.prefix);
4749
+ deleteInformedEntitiesStmt.run(alertId);
4739
4750
  const alertValues = serviceAlerts.schema.map((column) => prepareRealtimeFieldValue(entity, column, task));
4740
4751
  alertStmt.run(alertValues);
4741
4752
  recordCount++;
@@ -4768,6 +4779,9 @@ function createTripUpdatesProcessor(db, task) {
4768
4779
  db,
4769
4780
  stopTimeUpdates
4770
4781
  );
4782
+ const deleteStopTimesByTripStmt = db.prepare(
4783
+ `DELETE FROM ${stopTimeUpdates.filenameBase} WHERE trip_id = ? AND trip_start_time IS ?`
4784
+ );
4771
4785
  return async (batch) => {
4772
4786
  let recordCount = 0;
4773
4787
  let errorCount = 0;
@@ -4778,6 +4792,15 @@ function createTripUpdatesProcessor(db, task) {
4778
4792
  tripUpdateStmt.run(tripUpdateValues);
4779
4793
  recordCount++;
4780
4794
  if (entity.tripUpdate?.stopTimeUpdate?.length) {
4795
+ const tripId = applyPrefixToValue(
4796
+ entity.tripUpdate?.trip?.tripId ?? null,
4797
+ true,
4798
+ task.prefix
4799
+ );
4800
+ const tripStartTime = entity.tripUpdate?.trip?.startTime ?? null;
4801
+ if (tripId !== null) {
4802
+ deleteStopTimesByTripStmt.run(tripId, tripStartTime);
4803
+ }
4781
4804
  for (const stopTimeUpdate of entity.tripUpdate.stopTimeUpdate) {
4782
4805
  stopTimeUpdate.parent = entity;
4783
4806
  const stopTimeValues = stopTimeUpdates.schema.map(
@@ -4857,41 +4880,30 @@ async function updateGtfsRealtimeData(task) {
4857
4880
  tripupdates: 0,
4858
4881
  vehiclepositions: 0
4859
4882
  };
4860
- const processingPromises = [];
4861
4883
  if (alertsData?.entity?.length) {
4862
- processingPromises.push(
4863
- processBatch(
4864
- alertsData.entity,
4865
- BATCH_SIZE,
4866
- createServiceAlertsProcessor(db, task)
4867
- ).then((result) => {
4868
- recordCounts.alerts = result.recordCount;
4869
- })
4884
+ const result = await processBatch(
4885
+ alertsData.entity,
4886
+ BATCH_SIZE,
4887
+ createServiceAlertsProcessor(db, task)
4870
4888
  );
4889
+ recordCounts.alerts = result.recordCount;
4871
4890
  }
4872
4891
  if (tripUpdatesData?.entity?.length) {
4873
- processingPromises.push(
4874
- processBatch(
4875
- tripUpdatesData.entity,
4876
- BATCH_SIZE,
4877
- createTripUpdatesProcessor(db, task)
4878
- ).then((result) => {
4879
- recordCounts.tripupdates = result.recordCount;
4880
- })
4892
+ const result = await processBatch(
4893
+ tripUpdatesData.entity,
4894
+ BATCH_SIZE,
4895
+ createTripUpdatesProcessor(db, task)
4881
4896
  );
4897
+ recordCounts.tripupdates = result.recordCount;
4882
4898
  }
4883
4899
  if (vehiclePositionsData?.entity?.length) {
4884
- processingPromises.push(
4885
- processBatch(
4886
- vehiclePositionsData.entity,
4887
- BATCH_SIZE,
4888
- createVehiclePositionsProcessor(db, task)
4889
- ).then((result) => {
4890
- recordCounts.vehiclepositions = result.recordCount;
4891
- })
4900
+ const result = await processBatch(
4901
+ vehiclePositionsData.entity,
4902
+ BATCH_SIZE,
4903
+ createVehiclePositionsProcessor(db, task)
4892
4904
  );
4905
+ recordCounts.vehiclepositions = result.recordCount;
4893
4906
  }
4894
- await Promise.all(processingPromises);
4895
4907
  task.log(
4896
4908
  `GTFS-Realtime import complete: ${recordCounts.alerts} alerts, ${recordCounts.tripupdates} trip updates, ${recordCounts.vehiclepositions} vehicle positions`
4897
4909
  );
@@ -5000,10 +5012,14 @@ var downloadGtfsFiles = async (task) => {
5000
5012
  try {
5001
5013
  const response = await fetch(task.url, {
5002
5014
  method: "GET",
5003
- headers: task.headers || {},
5015
+ redirect: "follow",
5016
+ headers: {
5017
+ "User-Agent": "node-gtfs",
5018
+ ...task.headers
5019
+ },
5004
5020
  signal: task.downloadTimeout ? AbortSignal.timeout(task.downloadTimeout) : void 0
5005
5021
  });
5006
- if (response.status !== 200) {
5022
+ if (!response.ok) {
5007
5023
  throw new GtfsError(
5008
5024
  `Unable to download GTFS from ${task.url}. Got status ${response.status}.`,
5009
5025
  {
@@ -5116,18 +5132,18 @@ var extractGtfsFiles = async (task) => {
5116
5132
  var createGtfsTables = (db) => {
5117
5133
  for (const model of Object.values(models_exports)) {
5118
5134
  if (!model.schema) {
5119
- return;
5135
+ continue;
5120
5136
  }
5121
5137
  const sqlColumnCreateStatements = [];
5122
5138
  for (const column of model.schema) {
5123
5139
  const checks = [];
5124
- if (column.min !== void 0 && column.max) {
5140
+ if (column.min !== void 0 && column.max !== void 0) {
5125
5141
  checks.push(
5126
5142
  `${column.name} >= ${column.min} AND ${column.name} <= ${column.max}`
5127
5143
  );
5128
- } else if (column.min) {
5144
+ } else if (column.min !== void 0) {
5129
5145
  checks.push(`${column.name} >= ${column.min}`);
5130
- } else if (column.max) {
5146
+ } else if (column.max !== void 0) {
5131
5147
  checks.push(`${column.name} <= ${column.max}`);
5132
5148
  }
5133
5149
  if (column.type === "integer") {
@@ -5176,7 +5192,7 @@ var createGtfsTables = (db) => {
5176
5192
  var createGtfsIndexes = (db) => {
5177
5193
  for (const model of Object.values(models_exports)) {
5178
5194
  if (!model.schema) {
5179
- return;
5195
+ continue;
5180
5196
  }
5181
5197
  for (const column of model.schema) {
5182
5198
  if (column.index) {
@@ -6308,7 +6324,7 @@ function getStopsAsGeoJSON(query = {}, options = {}) {
6308
6324
  routes2,
6309
6325
  (route) => route?.route_short_name ? Number.parseInt(route.route_short_name, 10) : 0
6310
6326
  ),
6311
- agency_name: agencies[0].agency_name
6327
+ agency_name: agencies[0]?.agency_name ?? null
6312
6328
  };
6313
6329
  });
6314
6330
  const filteredStops = preparedStops.filter((stop) => stop.routes.length > 0);
@@ -6637,15 +6653,66 @@ function getVehiclePositions(query = {}, fields = [], orderBy2 = [], options = {
6637
6653
  }
6638
6654
 
6639
6655
  // src/lib/gtfs-realtime/service-alerts.ts
6656
+ var ENTITY_COLUMNS = /* @__PURE__ */ new Set([
6657
+ "alert_id",
6658
+ "stop_id",
6659
+ "route_id",
6660
+ "route_type",
6661
+ "trip_id",
6662
+ "direction_id"
6663
+ ]);
6640
6664
  function getServiceAlerts(query = {}, fields = [], orderBy2 = [], options = {}) {
6641
6665
  const db = options.db ?? openDb();
6642
6666
  const tableName = "service_alerts";
6643
6667
  const joinTableName = "service_alert_informed_entities";
6644
6668
  const selectClause = formatSelectClause(fields);
6669
+ const orderByClause = formatOrderByClause(orderBy2);
6670
+ const alertQuery = {};
6671
+ const entityQuery = {};
6672
+ for (const [key, value] of Object.entries(query)) {
6673
+ if (ENTITY_COLUMNS.has(key)) {
6674
+ entityQuery[key] = value;
6675
+ } else {
6676
+ alertQuery[key] = value;
6677
+ }
6678
+ }
6679
+ const whereClause = formatWhereClauses(alertQuery);
6680
+ const alerts = db.prepare(
6681
+ `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
6682
+ ).all();
6683
+ const alertIds = alerts.map((alert) => alert.id);
6684
+ if (alertIds.length === 0) {
6685
+ return [];
6686
+ }
6687
+ const alertIdPlaceholders = alertIds.map(() => "?").join(", ");
6688
+ const entityFilterClause = formatWhereClauses(entityQuery);
6689
+ const entityWhereClause = entityFilterClause ? `${entityFilterClause} AND alert_id IN (${alertIdPlaceholders})` : `WHERE alert_id IN (${alertIdPlaceholders})`;
6690
+ const entities = db.prepare(`SELECT * FROM ${joinTableName} ${entityWhereClause};`).all(...alertIds);
6691
+ const entitiesByAlertId = /* @__PURE__ */ new Map();
6692
+ for (const entity of entities) {
6693
+ const group = entitiesByAlertId.get(entity.alert_id);
6694
+ if (group) {
6695
+ group.push(entity);
6696
+ } else {
6697
+ entitiesByAlertId.set(entity.alert_id, [entity]);
6698
+ }
6699
+ }
6700
+ const matchedAlerts = Object.keys(entityQuery).length > 0 ? alerts.filter((alert) => entitiesByAlertId.has(alert.id)) : alerts;
6701
+ return matchedAlerts.map((alert) => ({
6702
+ ...alert,
6703
+ informed_entities: entitiesByAlertId.get(alert.id) ?? []
6704
+ }));
6705
+ }
6706
+
6707
+ // src/lib/gtfs-realtime/service-alert-informed-entities.ts
6708
+ function getServiceAlertInformedEntities(query = {}, fields = [], orderBy2 = [], options = {}) {
6709
+ const db = options.db ?? openDb();
6710
+ const tableName = "service_alert_informed_entities";
6711
+ const selectClause = formatSelectClause(fields);
6645
6712
  const whereClause = formatWhereClauses(query);
6646
6713
  const orderByClause = formatOrderByClause(orderBy2);
6647
6714
  return db.prepare(
6648
- `${selectClause} FROM ${tableName} INNER JOIN ${joinTableName} ON ${tableName}.id=${joinTableName}.alert_id ${whereClause} ${orderByClause};`
6715
+ `${selectClause} FROM ${tableName} ${whereClause} ${orderByClause};`
6649
6716
  ).all();
6650
6717
  }
6651
6718
 
@@ -6754,6 +6821,7 @@ export {
6754
6821
  getRoutes,
6755
6822
  getRunEvents,
6756
6823
  getRunsPieces,
6824
+ getServiceAlertInformedEntities,
6757
6825
  getServiceAlerts,
6758
6826
  getServiceIdsByDate,
6759
6827
  getShapes,