gtfs 4.13.0 → 4.13.1
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/bin/gtfs-export.js +19 -20
- package/dist/bin/gtfs-export.js.map +1 -1
- package/dist/bin/gtfs-import.js +52 -55
- package/dist/bin/gtfs-import.js.map +1 -1
- package/dist/bin/gtfsrealtime-update.js +37 -39
- package/dist/bin/gtfsrealtime-update.js.map +1 -1
- package/dist/index.d.ts +4 -1
- package/dist/index.js +122 -125
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -43,7 +43,10 @@ declare function updateGtfsRealtime(initialConfig: IConfig): Promise<void>;
|
|
|
43
43
|
|
|
44
44
|
declare const exportGtfs: (initialConfig: IConfig) => Promise<void>;
|
|
45
45
|
|
|
46
|
-
declare function openDb(config?:
|
|
46
|
+
declare function openDb(config?: {
|
|
47
|
+
db?: Database.Database;
|
|
48
|
+
sqlitePath?: string;
|
|
49
|
+
} | null): Database.Database;
|
|
47
50
|
declare function closeDb(db?: Database.Database | null): void;
|
|
48
51
|
declare function deleteDb(db?: Database.Database | null): void;
|
|
49
52
|
|
package/dist/index.js
CHANGED
|
@@ -89,8 +89,6 @@ var model3 = {
|
|
|
89
89
|
{
|
|
90
90
|
name: "attribution_id",
|
|
91
91
|
type: "text",
|
|
92
|
-
primary: true,
|
|
93
|
-
required: true,
|
|
94
92
|
prefix: true
|
|
95
93
|
},
|
|
96
94
|
{
|
|
@@ -3151,124 +3149,6 @@ var models_default = models;
|
|
|
3151
3149
|
import fs from "fs";
|
|
3152
3150
|
import Database from "better-sqlite3";
|
|
3153
3151
|
import untildify from "untildify";
|
|
3154
|
-
|
|
3155
|
-
// src/lib/utils.ts
|
|
3156
|
-
import sqlString from "sqlstring-sqlite";
|
|
3157
|
-
import Long from "long";
|
|
3158
|
-
function validateConfigForImport(config) {
|
|
3159
|
-
if (!config.agencies || config.agencies.length === 0) {
|
|
3160
|
-
throw new Error("No `agencies` specified in config");
|
|
3161
|
-
}
|
|
3162
|
-
for (const [index, agency] of config.agencies.entries()) {
|
|
3163
|
-
if (!agency.path && !agency.url) {
|
|
3164
|
-
throw new Error(
|
|
3165
|
-
`No Agency \`url\` or \`path\` specified in config for agency index ${index}.`
|
|
3166
|
-
);
|
|
3167
|
-
}
|
|
3168
|
-
}
|
|
3169
|
-
return config;
|
|
3170
|
-
}
|
|
3171
|
-
function setDefaultConfig(initialConfig) {
|
|
3172
|
-
const defaults = {
|
|
3173
|
-
sqlitePath: ":memory:",
|
|
3174
|
-
ignoreDuplicates: false,
|
|
3175
|
-
gtfsRealtimeExpirationSeconds: 0
|
|
3176
|
-
};
|
|
3177
|
-
return {
|
|
3178
|
-
...defaults,
|
|
3179
|
-
...initialConfig
|
|
3180
|
-
};
|
|
3181
|
-
}
|
|
3182
|
-
function convertLongTimeToDate(longDate) {
|
|
3183
|
-
const { high, low, unsigned } = longDate;
|
|
3184
|
-
return new Date(new Long(low, high, unsigned).toInt() * 1e3).toISOString();
|
|
3185
|
-
}
|
|
3186
|
-
function calculateSecondsFromMidnight(time) {
|
|
3187
|
-
const split = time.split(":").map((d) => Number.parseInt(d, 10));
|
|
3188
|
-
if (split.length !== 3) {
|
|
3189
|
-
return null;
|
|
3190
|
-
}
|
|
3191
|
-
return split[0] * 3600 + split[1] * 60 + split[2];
|
|
3192
|
-
}
|
|
3193
|
-
function padLeadingZeros(time) {
|
|
3194
|
-
const split = time.split(":").map((d) => String(Number(d)).padStart(2, "0"));
|
|
3195
|
-
if (split.length !== 3) {
|
|
3196
|
-
return null;
|
|
3197
|
-
}
|
|
3198
|
-
return split.join(":");
|
|
3199
|
-
}
|
|
3200
|
-
function formatSelectClause(fields) {
|
|
3201
|
-
if (Array.isArray(fields)) {
|
|
3202
|
-
const selectItem2 = fields.length > 0 ? fields.map((fieldName) => sqlString.escapeId(fieldName)).join(", ") : "*";
|
|
3203
|
-
return `SELECT ${selectItem2}`;
|
|
3204
|
-
}
|
|
3205
|
-
const selectItem = Object.entries(fields).map(
|
|
3206
|
-
(key) => `${sqlString.escapeId(key[0])} AS ${sqlString.escapeId(key[1])}`
|
|
3207
|
-
).join(", ");
|
|
3208
|
-
return `SELECT ${selectItem}`;
|
|
3209
|
-
}
|
|
3210
|
-
function formatJoinClause(joinObject) {
|
|
3211
|
-
return joinObject.map(
|
|
3212
|
-
(data) => `${data.type ? data.type + " JOIN" : "INNER JOIN"} ${sqlString.escapeId(
|
|
3213
|
-
data.table
|
|
3214
|
-
)} ON ${data.on}`
|
|
3215
|
-
).join(" ");
|
|
3216
|
-
}
|
|
3217
|
-
function degree2radian(angle) {
|
|
3218
|
-
return angle * Math.PI / 180;
|
|
3219
|
-
}
|
|
3220
|
-
function radian2degree(angle) {
|
|
3221
|
-
return angle / Math.PI * 180;
|
|
3222
|
-
}
|
|
3223
|
-
function formatWhereClauseBoundingBox(latitudeDegree, longitudeDegree, boundingBoxSideMeters) {
|
|
3224
|
-
const earthRadius = 6371e3;
|
|
3225
|
-
latitudeDegree = typeof latitudeDegree === "string" ? parseFloat(latitudeDegree) : latitudeDegree;
|
|
3226
|
-
longitudeDegree = typeof longitudeDegree === "string" ? parseFloat(longitudeDegree) : longitudeDegree;
|
|
3227
|
-
const latitudeRadian = degree2radian(latitudeDegree);
|
|
3228
|
-
const radiusFromLatitude = Math.cos(latitudeRadian) * earthRadius;
|
|
3229
|
-
const deltaLatitude = radian2degree(boundingBoxSideMeters / 2 / earthRadius);
|
|
3230
|
-
const deltaLongitude = radian2degree(
|
|
3231
|
-
boundingBoxSideMeters / 2 / radiusFromLatitude
|
|
3232
|
-
);
|
|
3233
|
-
let query = `stop_lat BETWEEN ${latitudeDegree - deltaLatitude} AND ${latitudeDegree + deltaLatitude}`;
|
|
3234
|
-
query += ` AND stop_lon BETWEEN ${longitudeDegree - deltaLongitude} AND ${longitudeDegree + deltaLongitude}`;
|
|
3235
|
-
return query;
|
|
3236
|
-
}
|
|
3237
|
-
function formatWhereClause(key, value) {
|
|
3238
|
-
if (Array.isArray(value)) {
|
|
3239
|
-
let whereClause = `${sqlString.escapeId(key)} IN (${value.filter((v) => v !== null).map((v) => sqlString.escape(v)).join(", ")})`;
|
|
3240
|
-
if (value.includes(null)) {
|
|
3241
|
-
whereClause = `(${whereClause} OR ${sqlString.escapeId(key)} IS NULL)`;
|
|
3242
|
-
}
|
|
3243
|
-
return whereClause;
|
|
3244
|
-
}
|
|
3245
|
-
if (value === null) {
|
|
3246
|
-
return `${sqlString.escapeId(key)} IS NULL`;
|
|
3247
|
-
}
|
|
3248
|
-
return `${sqlString.escapeId(key)} = ${sqlString.escape(value)}`;
|
|
3249
|
-
}
|
|
3250
|
-
function formatWhereClauses(query) {
|
|
3251
|
-
if (Object.keys(query).length === 0) {
|
|
3252
|
-
return "";
|
|
3253
|
-
}
|
|
3254
|
-
const whereClauses = Object.entries(query).map(
|
|
3255
|
-
([key, value]) => formatWhereClause(key, value)
|
|
3256
|
-
);
|
|
3257
|
-
return `WHERE ${whereClauses.join(" AND ")}`;
|
|
3258
|
-
}
|
|
3259
|
-
function formatOrderByClause(orderBy2) {
|
|
3260
|
-
let orderByClause = "";
|
|
3261
|
-
if (orderBy2.length > 0) {
|
|
3262
|
-
orderByClause += "ORDER BY ";
|
|
3263
|
-
orderByClause += orderBy2.map(([key, value]) => {
|
|
3264
|
-
const direction = value === "DESC" ? "DESC" : "ASC";
|
|
3265
|
-
return `${sqlString.escapeId(key)} ${direction}`;
|
|
3266
|
-
}).join(", ");
|
|
3267
|
-
}
|
|
3268
|
-
return orderByClause;
|
|
3269
|
-
}
|
|
3270
|
-
|
|
3271
|
-
// src/lib/db.ts
|
|
3272
3152
|
var dbs = {};
|
|
3273
3153
|
function setupDb(sqlitePath) {
|
|
3274
3154
|
const db = new Database(untildify(sqlitePath));
|
|
@@ -3280,7 +3160,7 @@ function setupDb(sqlitePath) {
|
|
|
3280
3160
|
}
|
|
3281
3161
|
function openDb(config = null) {
|
|
3282
3162
|
if (config) {
|
|
3283
|
-
const { sqlitePath, db } =
|
|
3163
|
+
const { sqlitePath = ":memory:", db } = config;
|
|
3284
3164
|
if (db) {
|
|
3285
3165
|
return db;
|
|
3286
3166
|
}
|
|
@@ -3289,6 +3169,9 @@ function openDb(config = null) {
|
|
|
3289
3169
|
}
|
|
3290
3170
|
return setupDb(sqlitePath);
|
|
3291
3171
|
}
|
|
3172
|
+
if (Object.keys(dbs).length === 0) {
|
|
3173
|
+
return setupDb(":memory:");
|
|
3174
|
+
}
|
|
3292
3175
|
if (Object.keys(dbs).length === 1) {
|
|
3293
3176
|
const filename = Object.keys(dbs)[0];
|
|
3294
3177
|
return dbs[filename];
|
|
@@ -3524,6 +3407,122 @@ function formatError(error) {
|
|
|
3524
3407
|
return colors.red(errorMessage);
|
|
3525
3408
|
}
|
|
3526
3409
|
|
|
3410
|
+
// src/lib/utils.ts
|
|
3411
|
+
import sqlString from "sqlstring-sqlite";
|
|
3412
|
+
import Long from "long";
|
|
3413
|
+
function validateConfigForImport(config) {
|
|
3414
|
+
if (!config.agencies || config.agencies.length === 0) {
|
|
3415
|
+
throw new Error("No `agencies` specified in config");
|
|
3416
|
+
}
|
|
3417
|
+
for (const [index, agency] of config.agencies.entries()) {
|
|
3418
|
+
if (!agency.path && !agency.url) {
|
|
3419
|
+
throw new Error(
|
|
3420
|
+
`No Agency \`url\` or \`path\` specified in config for agency index ${index}.`
|
|
3421
|
+
);
|
|
3422
|
+
}
|
|
3423
|
+
}
|
|
3424
|
+
return config;
|
|
3425
|
+
}
|
|
3426
|
+
function setDefaultConfig(initialConfig) {
|
|
3427
|
+
const defaults = {
|
|
3428
|
+
sqlitePath: ":memory:",
|
|
3429
|
+
ignoreDuplicates: false,
|
|
3430
|
+
gtfsRealtimeExpirationSeconds: 0
|
|
3431
|
+
};
|
|
3432
|
+
return {
|
|
3433
|
+
...defaults,
|
|
3434
|
+
...initialConfig
|
|
3435
|
+
};
|
|
3436
|
+
}
|
|
3437
|
+
function convertLongTimeToDate(longDate) {
|
|
3438
|
+
const { high, low, unsigned } = longDate;
|
|
3439
|
+
return new Date(new Long(low, high, unsigned).toInt() * 1e3).toISOString();
|
|
3440
|
+
}
|
|
3441
|
+
function calculateSecondsFromMidnight(time) {
|
|
3442
|
+
const split = time.split(":").map((d) => Number.parseInt(d, 10));
|
|
3443
|
+
if (split.length !== 3) {
|
|
3444
|
+
return null;
|
|
3445
|
+
}
|
|
3446
|
+
return split[0] * 3600 + split[1] * 60 + split[2];
|
|
3447
|
+
}
|
|
3448
|
+
function padLeadingZeros(time) {
|
|
3449
|
+
const split = time.split(":").map((d) => String(Number(d)).padStart(2, "0"));
|
|
3450
|
+
if (split.length !== 3) {
|
|
3451
|
+
return null;
|
|
3452
|
+
}
|
|
3453
|
+
return split.join(":");
|
|
3454
|
+
}
|
|
3455
|
+
function formatSelectClause(fields) {
|
|
3456
|
+
if (Array.isArray(fields)) {
|
|
3457
|
+
const selectItem2 = fields.length > 0 ? fields.map((fieldName) => sqlString.escapeId(fieldName)).join(", ") : "*";
|
|
3458
|
+
return `SELECT ${selectItem2}`;
|
|
3459
|
+
}
|
|
3460
|
+
const selectItem = Object.entries(fields).map(
|
|
3461
|
+
(key) => `${sqlString.escapeId(key[0])} AS ${sqlString.escapeId(key[1])}`
|
|
3462
|
+
).join(", ");
|
|
3463
|
+
return `SELECT ${selectItem}`;
|
|
3464
|
+
}
|
|
3465
|
+
function formatJoinClause(joinObject) {
|
|
3466
|
+
return joinObject.map(
|
|
3467
|
+
(data) => `${data.type ? data.type + " JOIN" : "INNER JOIN"} ${sqlString.escapeId(
|
|
3468
|
+
data.table
|
|
3469
|
+
)} ON ${data.on}`
|
|
3470
|
+
).join(" ");
|
|
3471
|
+
}
|
|
3472
|
+
function degree2radian(angle) {
|
|
3473
|
+
return angle * Math.PI / 180;
|
|
3474
|
+
}
|
|
3475
|
+
function radian2degree(angle) {
|
|
3476
|
+
return angle / Math.PI * 180;
|
|
3477
|
+
}
|
|
3478
|
+
function formatWhereClauseBoundingBox(latitudeDegree, longitudeDegree, boundingBoxSideMeters) {
|
|
3479
|
+
const earthRadius = 6371e3;
|
|
3480
|
+
latitudeDegree = typeof latitudeDegree === "string" ? parseFloat(latitudeDegree) : latitudeDegree;
|
|
3481
|
+
longitudeDegree = typeof longitudeDegree === "string" ? parseFloat(longitudeDegree) : longitudeDegree;
|
|
3482
|
+
const latitudeRadian = degree2radian(latitudeDegree);
|
|
3483
|
+
const radiusFromLatitude = Math.cos(latitudeRadian) * earthRadius;
|
|
3484
|
+
const deltaLatitude = radian2degree(boundingBoxSideMeters / 2 / earthRadius);
|
|
3485
|
+
const deltaLongitude = radian2degree(
|
|
3486
|
+
boundingBoxSideMeters / 2 / radiusFromLatitude
|
|
3487
|
+
);
|
|
3488
|
+
let query = `stop_lat BETWEEN ${latitudeDegree - deltaLatitude} AND ${latitudeDegree + deltaLatitude}`;
|
|
3489
|
+
query += ` AND stop_lon BETWEEN ${longitudeDegree - deltaLongitude} AND ${longitudeDegree + deltaLongitude}`;
|
|
3490
|
+
return query;
|
|
3491
|
+
}
|
|
3492
|
+
function formatWhereClause(key, value) {
|
|
3493
|
+
if (Array.isArray(value)) {
|
|
3494
|
+
let whereClause = `${sqlString.escapeId(key)} IN (${value.filter((v) => v !== null).map((v) => sqlString.escape(v)).join(", ")})`;
|
|
3495
|
+
if (value.includes(null)) {
|
|
3496
|
+
whereClause = `(${whereClause} OR ${sqlString.escapeId(key)} IS NULL)`;
|
|
3497
|
+
}
|
|
3498
|
+
return whereClause;
|
|
3499
|
+
}
|
|
3500
|
+
if (value === null) {
|
|
3501
|
+
return `${sqlString.escapeId(key)} IS NULL`;
|
|
3502
|
+
}
|
|
3503
|
+
return `${sqlString.escapeId(key)} = ${sqlString.escape(value)}`;
|
|
3504
|
+
}
|
|
3505
|
+
function formatWhereClauses(query) {
|
|
3506
|
+
if (Object.keys(query).length === 0) {
|
|
3507
|
+
return "";
|
|
3508
|
+
}
|
|
3509
|
+
const whereClauses = Object.entries(query).map(
|
|
3510
|
+
([key, value]) => formatWhereClause(key, value)
|
|
3511
|
+
);
|
|
3512
|
+
return `WHERE ${whereClauses.join(" AND ")}`;
|
|
3513
|
+
}
|
|
3514
|
+
function formatOrderByClause(orderBy2) {
|
|
3515
|
+
let orderByClause = "";
|
|
3516
|
+
if (orderBy2.length > 0) {
|
|
3517
|
+
orderByClause += "ORDER BY ";
|
|
3518
|
+
orderByClause += orderBy2.map(([key, value]) => {
|
|
3519
|
+
const direction = value === "DESC" ? "DESC" : "ASC";
|
|
3520
|
+
return `${sqlString.escapeId(key)} ${direction}`;
|
|
3521
|
+
}).join(", ");
|
|
3522
|
+
}
|
|
3523
|
+
return orderByClause;
|
|
3524
|
+
}
|
|
3525
|
+
|
|
3527
3526
|
// src/lib/import.ts
|
|
3528
3527
|
var downloadFiles = async (task) => {
|
|
3529
3528
|
task.log(`Downloading GTFS from ${task.agency_url}`);
|
|
@@ -3635,8 +3634,7 @@ var updateRealtimeData = async (task) => {
|
|
|
3635
3634
|
return;
|
|
3636
3635
|
}
|
|
3637
3636
|
const db = openDb({
|
|
3638
|
-
sqlitePath: task.sqlitePath
|
|
3639
|
-
agencies: []
|
|
3637
|
+
sqlitePath: task.sqlitePath
|
|
3640
3638
|
});
|
|
3641
3639
|
const vehiclePositionsModel = models_default.find(
|
|
3642
3640
|
(x) => x.filenameBase === "vehicle_positions"
|
|
@@ -3877,8 +3875,7 @@ var formatLine = (line, model56, totalLineCount) => {
|
|
|
3877
3875
|
};
|
|
3878
3876
|
var importLines = (task, lines, model56, totalLineCount) => {
|
|
3879
3877
|
const db = openDb({
|
|
3880
|
-
sqlitePath: task.sqlitePath
|
|
3881
|
-
agencies: []
|
|
3878
|
+
sqlitePath: task.sqlitePath
|
|
3882
3879
|
});
|
|
3883
3880
|
if (lines.length === 0) {
|
|
3884
3881
|
return;
|