minotor 1.0.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/.cspell.json +43 -0
- package/.czrc +3 -0
- package/.editorconfig +10 -0
- package/.github/ISSUE_TEMPLATE/bug_report.md +32 -0
- package/.github/ISSUE_TEMPLATE/config.yml +5 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +29 -0
- package/.github/PULL_REQUEST_TEMPLATE.md +4 -0
- package/.github/workflows/minotor.yml +85 -0
- package/.prettierrc +7 -0
- package/.releaserc.json +27 -0
- package/CHANGELOG.md +6 -0
- package/LICENSE +21 -0
- package/README.md +166 -0
- package/dist/bundle.cjs.js +16507 -0
- package/dist/bundle.cjs.js.map +1 -0
- package/dist/bundle.esm.js +16496 -0
- package/dist/bundle.esm.js.map +1 -0
- package/dist/bundle.umd.js +2 -0
- package/dist/bundle.umd.js.map +1 -0
- package/dist/cli/__tests__/minotor.test.d.ts +1 -0
- package/dist/cli/minotor.d.ts +5 -0
- package/dist/cli/repl.d.ts +1 -0
- package/dist/cli/utils.d.ts +3 -0
- package/dist/cli.mjs +20504 -0
- package/dist/cli.mjs.map +1 -0
- package/dist/gtfs/__tests__/parser.test.d.ts +1 -0
- package/dist/gtfs/__tests__/routes.test.d.ts +1 -0
- package/dist/gtfs/__tests__/services.test.d.ts +1 -0
- package/dist/gtfs/__tests__/stops.test.d.ts +1 -0
- package/dist/gtfs/__tests__/time.test.d.ts +1 -0
- package/dist/gtfs/__tests__/transfers.test.d.ts +1 -0
- package/dist/gtfs/__tests__/trips.test.d.ts +1 -0
- package/dist/gtfs/__tests__/utils.test.d.ts +1 -0
- package/dist/gtfs/parser.d.ts +34 -0
- package/dist/gtfs/profiles/__tests__/ch.test.d.ts +1 -0
- package/dist/gtfs/profiles/ch.d.ts +2 -0
- package/dist/gtfs/profiles/standard.d.ts +2 -0
- package/dist/gtfs/routes.d.ts +11 -0
- package/dist/gtfs/services.d.ts +19 -0
- package/dist/gtfs/stops.d.ts +20 -0
- package/dist/gtfs/time.d.ts +17 -0
- package/dist/gtfs/transfers.d.ts +22 -0
- package/dist/gtfs/trips.d.ts +26 -0
- package/dist/gtfs/utils.d.ts +21 -0
- package/dist/index.d.ts +11 -0
- package/dist/routing/__tests__/router.test.d.ts +1 -0
- package/dist/routing/plotter.d.ts +11 -0
- package/dist/routing/query.d.ts +35 -0
- package/dist/routing/result.d.ts +28 -0
- package/dist/routing/route.d.ts +25 -0
- package/dist/routing/router.d.ts +33 -0
- package/dist/stops/__tests__/io.test.d.ts +1 -0
- package/dist/stops/__tests__/stopFinder.test.d.ts +1 -0
- package/dist/stops/i18n.d.ts +10 -0
- package/dist/stops/io.d.ts +4 -0
- package/dist/stops/proto/stops.d.ts +53 -0
- package/dist/stops/stops.d.ts +16 -0
- package/dist/stops/stopsIndex.d.ts +52 -0
- package/dist/timetable/__tests__/io.test.d.ts +1 -0
- package/dist/timetable/__tests__/timetable.test.d.ts +1 -0
- package/dist/timetable/duration.d.ts +51 -0
- package/dist/timetable/io.d.ts +8 -0
- package/dist/timetable/proto/timetable.d.ts +122 -0
- package/dist/timetable/time.d.ts +98 -0
- package/dist/timetable/timetable.d.ts +82 -0
- package/dist/umdIndex.d.ts +9 -0
- package/eslint.config.mjs +52 -0
- package/package.json +109 -0
- package/rollup.config.js +44 -0
- package/src/cli/__tests__/minotor.test.ts +23 -0
- package/src/cli/minotor.ts +112 -0
- package/src/cli/repl.ts +200 -0
- package/src/cli/utils.ts +36 -0
- package/src/gtfs/__tests__/parser.test.ts +591 -0
- package/src/gtfs/__tests__/resources/sample-feed/agency.txt +2 -0
- package/src/gtfs/__tests__/resources/sample-feed/calendar.txt +3 -0
- package/src/gtfs/__tests__/resources/sample-feed/calendar_dates.txt +2 -0
- package/src/gtfs/__tests__/resources/sample-feed/fare_attributes.txt +3 -0
- package/src/gtfs/__tests__/resources/sample-feed/fare_rules.txt +5 -0
- package/src/gtfs/__tests__/resources/sample-feed/frequencies.txt +12 -0
- package/src/gtfs/__tests__/resources/sample-feed/routes.txt +6 -0
- package/src/gtfs/__tests__/resources/sample-feed/sample-feed.zip +0 -0
- package/src/gtfs/__tests__/resources/sample-feed/shapes.txt +1 -0
- package/src/gtfs/__tests__/resources/sample-feed/stop_times.txt +34 -0
- package/src/gtfs/__tests__/resources/sample-feed/stops.txt +10 -0
- package/src/gtfs/__tests__/resources/sample-feed/trips.txt +13 -0
- package/src/gtfs/__tests__/resources/sample-feed.zip +0 -0
- package/src/gtfs/__tests__/routes.test.ts +63 -0
- package/src/gtfs/__tests__/services.test.ts +209 -0
- package/src/gtfs/__tests__/stops.test.ts +177 -0
- package/src/gtfs/__tests__/time.test.ts +27 -0
- package/src/gtfs/__tests__/transfers.test.ts +117 -0
- package/src/gtfs/__tests__/trips.test.ts +463 -0
- package/src/gtfs/__tests__/utils.test.ts +13 -0
- package/src/gtfs/parser.ts +154 -0
- package/src/gtfs/profiles/__tests__/ch.test.ts +43 -0
- package/src/gtfs/profiles/ch.ts +70 -0
- package/src/gtfs/profiles/standard.ts +39 -0
- package/src/gtfs/routes.ts +48 -0
- package/src/gtfs/services.ts +98 -0
- package/src/gtfs/stops.ts +112 -0
- package/src/gtfs/time.ts +33 -0
- package/src/gtfs/transfers.ts +102 -0
- package/src/gtfs/trips.ts +228 -0
- package/src/gtfs/utils.ts +42 -0
- package/src/index.ts +28 -0
- package/src/routing/__tests__/router.test.ts +760 -0
- package/src/routing/plotter.ts +70 -0
- package/src/routing/query.ts +74 -0
- package/src/routing/result.ts +108 -0
- package/src/routing/route.ts +94 -0
- package/src/routing/router.ts +262 -0
- package/src/stops/__tests__/io.test.ts +43 -0
- package/src/stops/__tests__/stopFinder.test.ts +185 -0
- package/src/stops/i18n.ts +40 -0
- package/src/stops/io.ts +94 -0
- package/src/stops/proto/stops.proto +26 -0
- package/src/stops/proto/stops.ts +445 -0
- package/src/stops/stops.ts +24 -0
- package/src/stops/stopsIndex.ts +151 -0
- package/src/timetable/__tests__/io.test.ts +175 -0
- package/src/timetable/__tests__/timetable.test.ts +180 -0
- package/src/timetable/duration.ts +85 -0
- package/src/timetable/io.ts +265 -0
- package/src/timetable/proto/timetable.proto +76 -0
- package/src/timetable/proto/timetable.ts +1304 -0
- package/src/timetable/time.ts +192 -0
- package/src/timetable/timetable.ts +286 -0
- package/src/umdIndex.ts +14 -0
- package/tsconfig.build.json +4 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import { BinaryReader, BinaryWriter } from "@bufbuild/protobuf/wire";
|
|
2
|
+
export declare const protobufPackage = "minotor.timetable";
|
|
3
|
+
export declare enum PickUpDropOffType {
|
|
4
|
+
NOT_AVAILABLE = 0,
|
|
5
|
+
MUST_PHONE_AGENCY = 1,
|
|
6
|
+
MUST_COORDINATE_WITH_DRIVER = 2,
|
|
7
|
+
UNRECOGNIZED = -1
|
|
8
|
+
}
|
|
9
|
+
export declare function pickUpDropOffTypeFromJSON(object: any): PickUpDropOffType;
|
|
10
|
+
export declare function pickUpDropOffTypeToJSON(object: PickUpDropOffType): string;
|
|
11
|
+
export declare enum TransferType {
|
|
12
|
+
RECOMMENDED_TRANSFER_POINT = 0,
|
|
13
|
+
TIMED_TRANSFER = 1,
|
|
14
|
+
REQUIRES_MINIMAL_TIME = 2,
|
|
15
|
+
IN_SEAT_TRANSFER = 3,
|
|
16
|
+
UNRECOGNIZED = -1
|
|
17
|
+
}
|
|
18
|
+
export declare function transferTypeFromJSON(object: any): TransferType;
|
|
19
|
+
export declare function transferTypeToJSON(object: TransferType): string;
|
|
20
|
+
export declare enum RouteType {
|
|
21
|
+
TRAM = 0,
|
|
22
|
+
SUBWAY = 1,
|
|
23
|
+
RAIL = 2,
|
|
24
|
+
BUS = 3,
|
|
25
|
+
FERRY = 4,
|
|
26
|
+
CABLE_TRAM = 5,
|
|
27
|
+
AERIAL_LIFT = 6,
|
|
28
|
+
FUNICULAR = 7,
|
|
29
|
+
TROLLEYBUS = 8,
|
|
30
|
+
MONORAIL = 9,
|
|
31
|
+
UNRECOGNIZED = -1
|
|
32
|
+
}
|
|
33
|
+
export declare function routeTypeFromJSON(object: any): RouteType;
|
|
34
|
+
export declare function routeTypeToJSON(object: RouteType): string;
|
|
35
|
+
export interface StopTimes {
|
|
36
|
+
arrival: number;
|
|
37
|
+
departure: number;
|
|
38
|
+
pickUpType?: PickUpDropOffType | undefined;
|
|
39
|
+
dropOffType?: PickUpDropOffType | undefined;
|
|
40
|
+
}
|
|
41
|
+
export interface Route {
|
|
42
|
+
stopTimes: StopTimes[];
|
|
43
|
+
stops: string[];
|
|
44
|
+
serviceRouteId: string;
|
|
45
|
+
}
|
|
46
|
+
export interface RoutesAdjacency {
|
|
47
|
+
routes: {
|
|
48
|
+
[key: string]: Route;
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export interface RoutesAdjacency_RoutesEntry {
|
|
52
|
+
key: string;
|
|
53
|
+
value: Route | undefined;
|
|
54
|
+
}
|
|
55
|
+
export interface Transfer {
|
|
56
|
+
destination: string;
|
|
57
|
+
type: TransferType;
|
|
58
|
+
minTransferTime?: number | undefined;
|
|
59
|
+
}
|
|
60
|
+
export interface StopsAdjacency {
|
|
61
|
+
stops: {
|
|
62
|
+
[key: string]: StopsAdjacency_StopAdjacency;
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
export interface StopsAdjacency_StopAdjacency {
|
|
66
|
+
transfers: Transfer[];
|
|
67
|
+
routes: string[];
|
|
68
|
+
}
|
|
69
|
+
export interface StopsAdjacency_StopsEntry {
|
|
70
|
+
key: string;
|
|
71
|
+
value: StopsAdjacency_StopAdjacency | undefined;
|
|
72
|
+
}
|
|
73
|
+
export interface ServiceRoute {
|
|
74
|
+
type: RouteType;
|
|
75
|
+
name: string;
|
|
76
|
+
}
|
|
77
|
+
export interface ServiceRoutesMap {
|
|
78
|
+
routes: {
|
|
79
|
+
[key: string]: ServiceRoute;
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
export interface ServiceRoutesMap_RoutesEntry {
|
|
83
|
+
key: string;
|
|
84
|
+
value: ServiceRoute | undefined;
|
|
85
|
+
}
|
|
86
|
+
export interface Timetable {
|
|
87
|
+
version: string;
|
|
88
|
+
stopsAdjacency: StopsAdjacency | undefined;
|
|
89
|
+
routesAdjacency: RoutesAdjacency | undefined;
|
|
90
|
+
routes: ServiceRoutesMap | undefined;
|
|
91
|
+
}
|
|
92
|
+
export declare const StopTimes: MessageFns<StopTimes>;
|
|
93
|
+
export declare const Route: MessageFns<Route>;
|
|
94
|
+
export declare const RoutesAdjacency: MessageFns<RoutesAdjacency>;
|
|
95
|
+
export declare const RoutesAdjacency_RoutesEntry: MessageFns<RoutesAdjacency_RoutesEntry>;
|
|
96
|
+
export declare const Transfer: MessageFns<Transfer>;
|
|
97
|
+
export declare const StopsAdjacency: MessageFns<StopsAdjacency>;
|
|
98
|
+
export declare const StopsAdjacency_StopAdjacency: MessageFns<StopsAdjacency_StopAdjacency>;
|
|
99
|
+
export declare const StopsAdjacency_StopsEntry: MessageFns<StopsAdjacency_StopsEntry>;
|
|
100
|
+
export declare const ServiceRoute: MessageFns<ServiceRoute>;
|
|
101
|
+
export declare const ServiceRoutesMap: MessageFns<ServiceRoutesMap>;
|
|
102
|
+
export declare const ServiceRoutesMap_RoutesEntry: MessageFns<ServiceRoutesMap_RoutesEntry>;
|
|
103
|
+
export declare const Timetable: MessageFns<Timetable>;
|
|
104
|
+
type Builtin = Date | Function | Uint8Array | string | number | boolean | undefined;
|
|
105
|
+
export type DeepPartial<T> = T extends Builtin ? T : T extends globalThis.Array<infer U> ? globalThis.Array<DeepPartial<U>> : T extends ReadonlyArray<infer U> ? ReadonlyArray<DeepPartial<U>> : T extends {} ? {
|
|
106
|
+
[K in keyof T]?: DeepPartial<T[K]>;
|
|
107
|
+
} : Partial<T>;
|
|
108
|
+
type KeysOfUnion<T> = T extends T ? keyof T : never;
|
|
109
|
+
export type Exact<P, I extends P> = P extends Builtin ? P : P & {
|
|
110
|
+
[K in keyof P]: Exact<P[K], I[K]>;
|
|
111
|
+
} & {
|
|
112
|
+
[K in Exclude<keyof I, KeysOfUnion<P>>]: never;
|
|
113
|
+
};
|
|
114
|
+
export interface MessageFns<T> {
|
|
115
|
+
encode(message: T, writer?: BinaryWriter): BinaryWriter;
|
|
116
|
+
decode(input: BinaryReader | Uint8Array, length?: number): T;
|
|
117
|
+
fromJSON(object: any): T;
|
|
118
|
+
toJSON(message: T): unknown;
|
|
119
|
+
create<I extends Exact<DeepPartial<T>, I>>(base?: I): T;
|
|
120
|
+
fromPartial<I extends Exact<DeepPartial<T>, I>>(object: I): T;
|
|
121
|
+
}
|
|
122
|
+
export {};
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Duration } from './duration.js';
|
|
2
|
+
/**
|
|
3
|
+
* A class representing a time in hours, minutes, and seconds.
|
|
4
|
+
*/
|
|
5
|
+
export declare class Time {
|
|
6
|
+
private secondsSinceMidnight;
|
|
7
|
+
/**
|
|
8
|
+
* Gets the infinity time as a Time instance.
|
|
9
|
+
* This represents a time that is conceptually beyond any real possible time.
|
|
10
|
+
*
|
|
11
|
+
* @returns A Time instance representing an "infinity" time.
|
|
12
|
+
*/
|
|
13
|
+
static infinity(): Time;
|
|
14
|
+
/**
|
|
15
|
+
* Gets the midnight time as a Time instance.
|
|
16
|
+
*
|
|
17
|
+
* @returns A Time instance representing midnight (00:00:00).
|
|
18
|
+
*/
|
|
19
|
+
static origin(): Time;
|
|
20
|
+
private constructor();
|
|
21
|
+
/**
|
|
22
|
+
* Creates a Time instance from the number of seconds since midnight.
|
|
23
|
+
*
|
|
24
|
+
* @param seconds - The number of seconds since midnight.
|
|
25
|
+
* @returns A Time instance representing the specified time.
|
|
26
|
+
*/
|
|
27
|
+
static fromSeconds(seconds: number): Time;
|
|
28
|
+
/**
|
|
29
|
+
* Creates a Time instance from hours, minutes, and seconds.
|
|
30
|
+
*
|
|
31
|
+
* @param hours - The hours component of the time.
|
|
32
|
+
* @param minutes - The minutes component of the time.
|
|
33
|
+
* @param seconds - The seconds component of the time.
|
|
34
|
+
* @returns A Time instance representing the specified time.
|
|
35
|
+
*/
|
|
36
|
+
static fromHMS(hours: number, minutes: number, seconds: number): Time;
|
|
37
|
+
/**
|
|
38
|
+
* Parses a JavaScript Date object and creates a Time instance.
|
|
39
|
+
*
|
|
40
|
+
* @param date - A JavaScript Date object representing the time.
|
|
41
|
+
* @returns A Time instance representing the parsed time.
|
|
42
|
+
*/
|
|
43
|
+
static fromDate(date: Date): Time;
|
|
44
|
+
/**
|
|
45
|
+
* Parses a time string in the format "HH:MM:SS" or "HH:MM" and creates a Time instance.
|
|
46
|
+
*
|
|
47
|
+
* @param timeStr - A string representing the time in "HH:MM:SS" or "HH:MM" format.
|
|
48
|
+
* @returns A Time instance representing the parsed time.
|
|
49
|
+
*/
|
|
50
|
+
static fromString(timeStr: string): Time;
|
|
51
|
+
/**
|
|
52
|
+
* Converts the Time instance to a string in "HH:MM:SS" format.
|
|
53
|
+
*
|
|
54
|
+
* @returns A string representing the time.
|
|
55
|
+
*/
|
|
56
|
+
toString(): string;
|
|
57
|
+
/**
|
|
58
|
+
* Gets the time as the number of seconds since midnight.
|
|
59
|
+
*
|
|
60
|
+
* @returns The time in seconds since midnight.
|
|
61
|
+
*/
|
|
62
|
+
toSeconds(): number;
|
|
63
|
+
/**
|
|
64
|
+
* Adds a Duration to the current Time instance and returns a new Time instance.
|
|
65
|
+
*
|
|
66
|
+
* @param duration - A Duration instance representing the duration to add.
|
|
67
|
+
* @returns A new Time instance with the added duration.
|
|
68
|
+
*/
|
|
69
|
+
plus(duration: Duration): Time;
|
|
70
|
+
/**
|
|
71
|
+
* Subtracts a Duration from the current Time instance and returns a new Time instance.
|
|
72
|
+
*
|
|
73
|
+
* @param duration - A Duration instance representing the duration to subtract.
|
|
74
|
+
* @returns A new Time instance with the subtracted duration.
|
|
75
|
+
*/
|
|
76
|
+
minus(duration: Duration): Time;
|
|
77
|
+
/**
|
|
78
|
+
* Subtracts another Time instance from the current Time instance and returns the Duration.
|
|
79
|
+
*
|
|
80
|
+
* @param otherTime - A Time instance representing the time to subtract.
|
|
81
|
+
* @returns A Duration instance representing the time difference.
|
|
82
|
+
*/
|
|
83
|
+
diff(otherTime: Time): Duration;
|
|
84
|
+
/**
|
|
85
|
+
* Computes the maximum Time instance among the provided Time instances.
|
|
86
|
+
*
|
|
87
|
+
* @param times - An array of Time instances to compare.
|
|
88
|
+
* @returns A Time instance representing the maximum time.
|
|
89
|
+
*/
|
|
90
|
+
static max(...times: Time[]): Time;
|
|
91
|
+
/**
|
|
92
|
+
* Computes the minimum Time instance among the provided Time instances.
|
|
93
|
+
*
|
|
94
|
+
* @param times - An array of Time instances to compare.
|
|
95
|
+
* @returns A Time instance representing the minimum time.
|
|
96
|
+
*/
|
|
97
|
+
static min(...times: Time[]): Time;
|
|
98
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { StopId } from '../stops/stops.js';
|
|
2
|
+
import { Duration } from './duration.js';
|
|
3
|
+
import { Time } from './time.js';
|
|
4
|
+
export type PickUpDropOffType = 'REGULAR' | 'NOT_AVAILABLE' | 'MUST_PHONE_AGENCY' | 'MUST_COORDINATE_WITH_DRIVER';
|
|
5
|
+
export type StopTimes = {
|
|
6
|
+
arrival: Time;
|
|
7
|
+
departure: Time;
|
|
8
|
+
pickUpType: PickUpDropOffType;
|
|
9
|
+
dropOffType: PickUpDropOffType;
|
|
10
|
+
};
|
|
11
|
+
export type RouteId = string;
|
|
12
|
+
export type IndexedStopId = {
|
|
13
|
+
stopId: StopId;
|
|
14
|
+
index: number;
|
|
15
|
+
};
|
|
16
|
+
export type Route = {
|
|
17
|
+
stopTimes: StopTimes[];
|
|
18
|
+
stops: StopId[];
|
|
19
|
+
stopIndices: Map<StopId, number>;
|
|
20
|
+
serviceRouteId: ServiceRouteId;
|
|
21
|
+
};
|
|
22
|
+
export type RoutesAdjacency = Map<RouteId, Route>;
|
|
23
|
+
export type TransferType = 'RECOMMENDED' | 'GUARANTEED' | 'REQUIRES_MINIMAL_TIME' | 'IN_SEAT';
|
|
24
|
+
export type Transfer = {
|
|
25
|
+
destination: StopId;
|
|
26
|
+
type: TransferType;
|
|
27
|
+
minTransferTime?: Duration;
|
|
28
|
+
};
|
|
29
|
+
export type StopsAdjacency = Map<StopId, {
|
|
30
|
+
transfers: Transfer[];
|
|
31
|
+
routes: RouteId[];
|
|
32
|
+
}>;
|
|
33
|
+
export type ServiceRouteId = string;
|
|
34
|
+
export type RouteType = 'TRAM' | 'SUBWAY' | 'RAIL' | 'BUS' | 'FERRY' | 'CABLE_TRAM' | 'AERIAL_LIFT' | 'FUNICULAR' | 'TROLLEYBUS' | 'MONORAIL';
|
|
35
|
+
export type ServiceRoute = {
|
|
36
|
+
type: RouteType;
|
|
37
|
+
name: string;
|
|
38
|
+
};
|
|
39
|
+
export type ServiceRoutesMap = Map<ServiceRouteId, ServiceRoute>;
|
|
40
|
+
type TripIndex = number;
|
|
41
|
+
export declare const ALL_TRANSPORT_MODES: RouteType[];
|
|
42
|
+
export declare const CURRENT_VERSION = "0.0.1";
|
|
43
|
+
/**
|
|
44
|
+
* The internal transit timetable format
|
|
45
|
+
* reuses some GTFS concepts for the sake of simplicity for now.
|
|
46
|
+
*/
|
|
47
|
+
export declare class Timetable {
|
|
48
|
+
private readonly stopsAdjacency;
|
|
49
|
+
private readonly routesAdjacency;
|
|
50
|
+
private readonly routes;
|
|
51
|
+
constructor(stopsAdjacency: StopsAdjacency, routesAdjacency: RoutesAdjacency, routes: ServiceRoutesMap);
|
|
52
|
+
/**
|
|
53
|
+
* Serializes the Timetable into a binary protobuf.
|
|
54
|
+
*
|
|
55
|
+
* @returns {Uint8Array} - The serialized binary data.
|
|
56
|
+
*/
|
|
57
|
+
serialize(): Uint8Array;
|
|
58
|
+
/**
|
|
59
|
+
* Deserializes a binary protobuf into a Timetable object.
|
|
60
|
+
*
|
|
61
|
+
* @param {Uint8Array} data - The binary data to deserialize.
|
|
62
|
+
* @returns {Timetable} - The deserialized Timetable object.
|
|
63
|
+
*/
|
|
64
|
+
static fromData(data: Uint8Array): Timetable;
|
|
65
|
+
getRoute(routeId: RouteId): Route | undefined;
|
|
66
|
+
getTransfers(stopId: StopId): Transfer[];
|
|
67
|
+
/**
|
|
68
|
+
* Finds routes that are reachable from a set of stop IDs.
|
|
69
|
+
* Also identifies the first stop available to hop on each route among
|
|
70
|
+
* the input stops.
|
|
71
|
+
*/
|
|
72
|
+
findReachableRoutes(fromStops: Set<StopId>, transportModes?: RouteType[]): Map<RouteId, StopId>;
|
|
73
|
+
getServiceRouteFromRouteId(routeId: RouteId): ServiceRoute | undefined;
|
|
74
|
+
getServiceRoute(serviceRouteId: ServiceRouteId): ServiceRoute | undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Finds the earliest trip that can be taken from a specific stop on a given route,
|
|
77
|
+
* optionally constrained by a latest trip index and a time before which the trip
|
|
78
|
+
* should not depart.
|
|
79
|
+
*/
|
|
80
|
+
findEarliestTrip(route: Route, stopId: StopId, beforeTrip?: TripIndex, after?: Time): TripIndex | undefined;
|
|
81
|
+
}
|
|
82
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Plotter } from './routing/plotter.js';
|
|
2
|
+
import { Query } from './routing/query.js';
|
|
3
|
+
import { Result } from './routing/result.js';
|
|
4
|
+
import { Route } from './routing/route.js';
|
|
5
|
+
import { Router } from './routing/router.js';
|
|
6
|
+
import { StopsIndex } from './stops/stopsIndex.js';
|
|
7
|
+
import { Time } from './timetable/time.js';
|
|
8
|
+
import { Timetable } from './timetable/timetable.js';
|
|
9
|
+
export { Plotter, Query, Result, Route, Router, StopsIndex, Time, Timetable };
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import eslint from '@eslint/js';
|
|
2
|
+
import tseslint from 'typescript-eslint';
|
|
3
|
+
import prettierConfig from 'eslint-config-prettier';
|
|
4
|
+
import simpleImportSort from 'eslint-plugin-simple-import-sort';
|
|
5
|
+
|
|
6
|
+
export default tseslint.config(
|
|
7
|
+
eslint.configs.recommended,
|
|
8
|
+
...tseslint.configs.recommendedTypeChecked,
|
|
9
|
+
...tseslint.configs.strictTypeChecked,
|
|
10
|
+
prettierConfig,
|
|
11
|
+
{
|
|
12
|
+
ignores: ['scripts/*', 'rollup.config.js'],
|
|
13
|
+
},
|
|
14
|
+
{
|
|
15
|
+
files: ['**/*.ts'],
|
|
16
|
+
languageOptions: {
|
|
17
|
+
ecmaVersion: 2019,
|
|
18
|
+
sourceType: 'module',
|
|
19
|
+
parser: tseslint.parser,
|
|
20
|
+
parserOptions: {
|
|
21
|
+
project: './tsconfig.json',
|
|
22
|
+
projectService: true,
|
|
23
|
+
tsconfigRootDir: import.meta.dirname,
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
plugins: {
|
|
27
|
+
'simple-import-sort': simpleImportSort,
|
|
28
|
+
},
|
|
29
|
+
rules: {
|
|
30
|
+
'@typescript-eslint/no-unused-expressions': 'off', // Breaks the linting
|
|
31
|
+
'@typescript-eslint/restrict-template-expressions': [
|
|
32
|
+
'error',
|
|
33
|
+
{ allowNumber: true },
|
|
34
|
+
],
|
|
35
|
+
'simple-import-sort/imports': 'error',
|
|
36
|
+
'simple-import-sort/exports': 'error',
|
|
37
|
+
},
|
|
38
|
+
},
|
|
39
|
+
{
|
|
40
|
+
files: ['src/**/*.test.ts'],
|
|
41
|
+
rules: {
|
|
42
|
+
'@typescript-eslint/no-floating-promises': 'off',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
{
|
|
46
|
+
files: ['src/stops/proto/*.ts', 'src/timetable/proto/*.ts'],
|
|
47
|
+
rules: {
|
|
48
|
+
'eslint-comments/no-unlimited-disable': 'off',
|
|
49
|
+
'eslint-comments/disable-enable-pair': 'off',
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
);
|
package/package.json
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "minotor",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A lightweight client-side transit router.",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"minotor",
|
|
7
|
+
"raptor",
|
|
8
|
+
"transit",
|
|
9
|
+
"planner",
|
|
10
|
+
"transport",
|
|
11
|
+
"router",
|
|
12
|
+
"gtfs",
|
|
13
|
+
"trains",
|
|
14
|
+
"netex"
|
|
15
|
+
],
|
|
16
|
+
"homepage": "https://github.com/aubryio/minotor",
|
|
17
|
+
"bugs": "https://github.com/aubryio/minotor/issues",
|
|
18
|
+
"author": "Aubry Cholleton <aubry.cholleton@gmail.com>",
|
|
19
|
+
"license": "MIT",
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/aubryio/minotor.git"
|
|
23
|
+
},
|
|
24
|
+
"type": "module",
|
|
25
|
+
"main": "dist/bundle.cjs.js",
|
|
26
|
+
"module": "dist/bundle.esm.js",
|
|
27
|
+
"browser": "dist/bundle.umd.js",
|
|
28
|
+
"bin": {
|
|
29
|
+
"minotor": "./dist/cli.mjs"
|
|
30
|
+
},
|
|
31
|
+
"exports": {
|
|
32
|
+
".": {
|
|
33
|
+
"import": "./dist/bundle.esm.js",
|
|
34
|
+
"require": "./dist/bundle.cjs.js"
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"engines": {
|
|
39
|
+
"node": ">=21.1.0",
|
|
40
|
+
"npm": ">=10.9.1"
|
|
41
|
+
},
|
|
42
|
+
"volta": {
|
|
43
|
+
"node": "21.1.0",
|
|
44
|
+
"npm": "10.9.1"
|
|
45
|
+
},
|
|
46
|
+
"publishConfig": {
|
|
47
|
+
"access": "public"
|
|
48
|
+
},
|
|
49
|
+
"scripts": {
|
|
50
|
+
"build:proto": "protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. ./src/timetable/proto/timetable.proto; protoc --plugin=./node_modules/.bin/protoc-gen-ts_proto --ts_proto_out=. ./src/stops/proto/stops.proto",
|
|
51
|
+
"build": "npm run clean && npm run build:proto && npm run type:dts && npm run build:src",
|
|
52
|
+
"build:src": "rollup -c",
|
|
53
|
+
"clean": "rimraf build coverage",
|
|
54
|
+
"type:dts": "tsc --emitDeclarationOnly --project tsconfig.build.json",
|
|
55
|
+
"type:check": "tsc --noEmit",
|
|
56
|
+
"lint": "eslint src --fix",
|
|
57
|
+
"lint:check": "eslint src",
|
|
58
|
+
"format:check": "prettier . --check",
|
|
59
|
+
"format": "prettier --write .",
|
|
60
|
+
"test": "tsx --test src/**/*.test.ts",
|
|
61
|
+
"test:watch": "tsx --watch --test src/**/*.test.ts",
|
|
62
|
+
"test:coverage": "c8 -x 'src/**/proto/*.ts' -x 'src/**/__tests__/*.ts' --check-coverage --lines=85 tsx --test src/**/*.test.ts",
|
|
63
|
+
"spell:check": "cspell \"{README.md,.github/*.md,src/**/*.ts}\" -u",
|
|
64
|
+
"cz": "cz",
|
|
65
|
+
"semantic-release": "semantic-release"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@eslint/js": "^9.0.0",
|
|
69
|
+
"@rollup/plugin-commonjs": "^28.0.1",
|
|
70
|
+
"@rollup/plugin-node-resolve": "^15.3.0",
|
|
71
|
+
"@rollup/plugin-terser": "^0.4.4",
|
|
72
|
+
"@rollup/plugin-typescript": "^12.1.1",
|
|
73
|
+
"@ryansonshine/commitizen": "^4.2.8",
|
|
74
|
+
"@ryansonshine/cz-conventional-changelog": "^3.3.4",
|
|
75
|
+
"@semantic-release/changelog": "^6.0.3",
|
|
76
|
+
"@semantic-release/commit-analyzer": "^13.0.0",
|
|
77
|
+
"@semantic-release/github": "^11.0.1",
|
|
78
|
+
"@semantic-release/npm": "^12.0.1",
|
|
79
|
+
"@semantic-release/release-notes-generator": "^14.0.1",
|
|
80
|
+
"@types/eslint__js": "^8.42.3",
|
|
81
|
+
"@types/geokdbush": "^1.1.5",
|
|
82
|
+
"@types/luxon": "^3.4.2",
|
|
83
|
+
"@types/node": "^22.9.0",
|
|
84
|
+
"c8": "^10.1.2",
|
|
85
|
+
"cspell": "^8.16.0",
|
|
86
|
+
"eslint": "^9.15.0",
|
|
87
|
+
"eslint-config-prettier": "^9.1.0",
|
|
88
|
+
"eslint-plugin-simple-import-sort": "^12.1.1",
|
|
89
|
+
"prettier": "^3.3.3",
|
|
90
|
+
"rimraf": "^6.0.1",
|
|
91
|
+
"rollup": "^4.27.2",
|
|
92
|
+
"semantic-release": "^24.2.0",
|
|
93
|
+
"ts-proto": "^2.2.7",
|
|
94
|
+
"tsx": "^4.19.2",
|
|
95
|
+
"typescript": "^5.6.3",
|
|
96
|
+
"typescript-eslint": "^8.14.0"
|
|
97
|
+
},
|
|
98
|
+
"dependencies": {
|
|
99
|
+
"@bufbuild/protobuf": "^2.2.2",
|
|
100
|
+
"commander": "^12.1.0",
|
|
101
|
+
"csv-parse": "^5.5.6",
|
|
102
|
+
"geokdbush": "^2.0.1",
|
|
103
|
+
"kdbush": "^4.0.2",
|
|
104
|
+
"loglevel": "^1.9.2",
|
|
105
|
+
"luxon": "^3.5.0",
|
|
106
|
+
"node-stream-zip": "^1.15.0",
|
|
107
|
+
"slimsearch": "^2.2.1"
|
|
108
|
+
}
|
|
109
|
+
}
|
package/rollup.config.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import typescript from '@rollup/plugin-typescript';
|
|
2
|
+
import resolve from '@rollup/plugin-node-resolve';
|
|
3
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
4
|
+
import terser from '@rollup/plugin-terser';
|
|
5
|
+
|
|
6
|
+
export default [
|
|
7
|
+
{
|
|
8
|
+
input: 'src/umdIndex.ts',
|
|
9
|
+
output: {
|
|
10
|
+
file: 'dist/bundle.umd.js',
|
|
11
|
+
format: 'umd',
|
|
12
|
+
name: 'minotor',
|
|
13
|
+
sourcemap: true,
|
|
14
|
+
},
|
|
15
|
+
plugins: [resolve(), commonjs(), typescript(), terser()],
|
|
16
|
+
},
|
|
17
|
+
// CommonJS and ES module builds for Node.js and bundlers
|
|
18
|
+
{
|
|
19
|
+
input: 'src/index.ts',
|
|
20
|
+
output: [
|
|
21
|
+
{
|
|
22
|
+
file: 'dist/bundle.esm.js',
|
|
23
|
+
format: 'es',
|
|
24
|
+
sourcemap: true,
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
file: 'dist/bundle.cjs.js',
|
|
28
|
+
format: 'cjs',
|
|
29
|
+
sourcemap: true,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
plugins: [resolve(), commonjs(), typescript()],
|
|
33
|
+
},
|
|
34
|
+
{
|
|
35
|
+
input: 'src/cli/minotor.ts',
|
|
36
|
+
output: {
|
|
37
|
+
file: 'dist/cli.mjs',
|
|
38
|
+
format: 'es',
|
|
39
|
+
banner: '#!/usr/bin/env node',
|
|
40
|
+
sourcemap: true,
|
|
41
|
+
},
|
|
42
|
+
plugins: [resolve(), commonjs(), typescript()],
|
|
43
|
+
},
|
|
44
|
+
];
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import fs from 'node:fs';
|
|
2
|
+
import os from 'node:os';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
import { afterEach, beforeEach, describe } from 'node:test';
|
|
5
|
+
|
|
6
|
+
describe('timetable io', () => {
|
|
7
|
+
let tempDir: string;
|
|
8
|
+
let filePath: string;
|
|
9
|
+
|
|
10
|
+
beforeEach(() => {
|
|
11
|
+
tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'test-io-'));
|
|
12
|
+
filePath = path.join(tempDir, 'test-timetable.bin');
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
afterEach(() => {
|
|
16
|
+
if (fs.existsSync(filePath)) {
|
|
17
|
+
fs.unlinkSync(filePath);
|
|
18
|
+
}
|
|
19
|
+
if (fs.existsSync(tempDir)) {
|
|
20
|
+
fs.rmdirSync(tempDir);
|
|
21
|
+
}
|
|
22
|
+
});
|
|
23
|
+
});
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { Command } from 'commander';
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import log from 'loglevel';
|
|
4
|
+
import { DateTime } from 'luxon';
|
|
5
|
+
|
|
6
|
+
import { chGtfsProfile, GtfsParser, GtfsProfile } from '../index.js';
|
|
7
|
+
import { startRepl } from './repl.js';
|
|
8
|
+
|
|
9
|
+
const program = new Command();
|
|
10
|
+
|
|
11
|
+
export type GtfsVariant = string;
|
|
12
|
+
|
|
13
|
+
export type Config = {
|
|
14
|
+
[config: GtfsVariant]: GtfsProfile;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const profiles: Config = {
|
|
18
|
+
CH: chGtfsProfile,
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
program
|
|
22
|
+
.name('minotor')
|
|
23
|
+
.description('CLI for minotor route planner.')
|
|
24
|
+
.version('0.0.1');
|
|
25
|
+
|
|
26
|
+
program
|
|
27
|
+
.command('parse-gtfs')
|
|
28
|
+
.description('Parse a GTFS feed and output a timetable and stops file.')
|
|
29
|
+
.argument('<gtfsPath>', 'Path to GTFS data')
|
|
30
|
+
.option(
|
|
31
|
+
'-d, --date <date>',
|
|
32
|
+
'Date of the day to parse in yyyy-MM-dd format',
|
|
33
|
+
DateTime.now().toFormat('yyyy-MM-dd'),
|
|
34
|
+
)
|
|
35
|
+
.option(
|
|
36
|
+
'-t, --timetableOutputPath <path>',
|
|
37
|
+
'Path to output timetable file',
|
|
38
|
+
'/tmp/timetable',
|
|
39
|
+
)
|
|
40
|
+
.option(
|
|
41
|
+
'-s, --stopsOutputPath <path>',
|
|
42
|
+
'Path to output stops file',
|
|
43
|
+
'/tmp/stops',
|
|
44
|
+
)
|
|
45
|
+
.option('-p, --profileName <name>', 'Profile name for GTFS config', 'CH')
|
|
46
|
+
.option('-v, --verbose', 'Verbose mode', false)
|
|
47
|
+
.action(
|
|
48
|
+
async (
|
|
49
|
+
gtfsPath: string,
|
|
50
|
+
options: {
|
|
51
|
+
date: string;
|
|
52
|
+
timetableOutputPath: string;
|
|
53
|
+
stopsOutputPath: string;
|
|
54
|
+
profileName: string;
|
|
55
|
+
verbose: boolean;
|
|
56
|
+
},
|
|
57
|
+
) => {
|
|
58
|
+
if (options.verbose) {
|
|
59
|
+
log.setDefaultLevel(log.levels.INFO);
|
|
60
|
+
} else {
|
|
61
|
+
log.setDefaultLevel(log.levels.ERROR);
|
|
62
|
+
}
|
|
63
|
+
const parser = new GtfsParser(gtfsPath, profiles[options.profileName]);
|
|
64
|
+
const { timetable, stopsIndex } = await parser.parse(
|
|
65
|
+
new Date(options.date),
|
|
66
|
+
);
|
|
67
|
+
fs.writeFileSync(options.timetableOutputPath, timetable.serialize());
|
|
68
|
+
fs.writeFileSync(options.stopsOutputPath, stopsIndex.serialize());
|
|
69
|
+
},
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
program
|
|
73
|
+
.command('parse-stops')
|
|
74
|
+
.description('Parse a GTFS feed and output a timetable and stops file.')
|
|
75
|
+
.argument('<gtfsPath>', 'Path to GTFS data')
|
|
76
|
+
.option('-s, --outputPath <path>', 'Path to output stops file', '/tmp/stops')
|
|
77
|
+
.option('-p, --profileName <name>', 'Profile name for GTFS config', 'CH')
|
|
78
|
+
.option('-v, --verbose', 'Verbose mode', false)
|
|
79
|
+
.action(
|
|
80
|
+
async (
|
|
81
|
+
gtfsPath: string,
|
|
82
|
+
options: {
|
|
83
|
+
stopsOutputPath: string;
|
|
84
|
+
profileName: string;
|
|
85
|
+
verbose: boolean;
|
|
86
|
+
},
|
|
87
|
+
) => {
|
|
88
|
+
if (options.verbose) {
|
|
89
|
+
log.setDefaultLevel(log.levels.INFO);
|
|
90
|
+
} else {
|
|
91
|
+
log.setDefaultLevel(log.levels.ERROR);
|
|
92
|
+
}
|
|
93
|
+
const parser = new GtfsParser(gtfsPath, profiles[options.profileName]);
|
|
94
|
+
const stopsIndex = await parser.parseStops();
|
|
95
|
+
fs.writeFileSync(options.stopsOutputPath, stopsIndex.serialize());
|
|
96
|
+
},
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
program
|
|
100
|
+
.command('repl')
|
|
101
|
+
.description('Find stops matching a textual query')
|
|
102
|
+
.option('-s, --stopsPath <path>', 'Path to the stops file', '/tmp/stops')
|
|
103
|
+
.option(
|
|
104
|
+
'-t, --timetablePath <path>',
|
|
105
|
+
'Path to the timetable file',
|
|
106
|
+
'/tmp/timetable',
|
|
107
|
+
)
|
|
108
|
+
.action((options: { stopsPath: string; timetablePath: string }) => {
|
|
109
|
+
startRepl(options.stopsPath, options.timetablePath);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
program.parse(process.argv);
|