diff --git a/p/db/dynamicProfileData.json b/p/db/dynamicProfileData.json deleted file mode 100644 index 36743eb9..00000000 --- a/p/db/dynamicProfileData.json +++ /dev/null @@ -1,80 +0,0 @@ -{ - "journeys": { - "profileName": "dbnav", - "profileMethods": [ - { - "methodName": "formatJourneysReq", - "moduleName": "journeys-req.js" - } - ], - "baseKeys": ["journeysEndpoint"] - }, - "refreshJourneys": { - "profileName": "dbnav", - "profileMethods": [ - { - "methodName": "formatRefreshJourneyReq", - "moduleName": "journeys-req.js" - } - ], - "baseKeys": ["refreshJourneysEndpointTickets", "refreshJourneysEndpointPolyline"] - }, - "locations": { - "profileName": "dbnav", - "profileMethods": [ - { - "methodName": "formatLocationFilter", - "moduleName": "location-filter.js" - }, - { - "methodName": "formatLocationsReq", - "moduleName": "locations-req.js" - } - ], - "baseKeys": ["locationsEndpoint"] - }, - "stop": { - "profileName": "dbnav", - "profileMethods": [ - { - "methodName": "formatStopReq", - "moduleName": "stop-req.js" - }, - { - "methodName": "parseStop", - "moduleName": "parse-stop.js" - } - ], - "baseKeys": ["stopEndpoint"] - }, - "nearby": { - "profileName": "dbnav", - "profileMethods": [ - { - "methodName": "formatNearbyReq", - "moduleName": "nearby-req.js" - } - ], - "baseKeys": ["nearbyEndpoint"] - }, - "trip": { - "profileName": "db", - "profileMethods": [ - { - "methodName": "formatTripReq", - "moduleName": "trip-req.js" - } - ], - "baseKeys": ["tripEndpoint"] - }, - "board": { - "profileName": "dbregioguide", - "profileMethods": [ - { - "methodName": "formatStationBoardReq", - "moduleName": "station-board-req.js" - } - ], - "baseKeys": ["boardEndpoint"] - } -} diff --git a/p/db/index.js b/p/db/index.js index dd6210a4..af5cdb5d 100644 --- a/p/db/index.js +++ b/p/db/index.js @@ -1,50 +1,66 @@ import {createRequire} from 'module'; const require = createRequire(import.meta.url); -const dynamicProfileData = require('./dynamicProfileData.json'); const dbnavBase = require('../dbnav/base.json'); const dbregioguideBase = require('../dbregioguide/base.json'); -const dbwebBase = require('../dbweb/base.json'); import {products} from '../../lib/products.js'; +// journeys() +import {formatJourneysReq} from '../dbnav/journeys-req.js'; +const {journeysEndpoint} = dbnavBase; + +// refreshJourneys() +import {formatRefreshJourneyReq} from '../dbnav/journeys-req.js'; +const {refreshJourneysEndpointTickets, refreshJourneysEndpointPolyline} = dbnavBase; + +// locations() +import {formatLocationsReq} from '../dbnav/locations-req.js'; +import {formatLocationFilter} from '../dbnav/location-filter.js'; +const {locationsEndpoint} = dbnavBase; + +// stop() +import {formatStopReq} from '../dbnav/stop-req.js'; +import {parseStop} from '../dbnav/parse-stop.js'; +const {stopEndpoint} = dbnavBase; + +// nearby() +import {formatNearbyReq} from '../dbnav/nearby-req.js'; +const {nearbyEndpoint} = dbnavBase; + +// trip() +import {formatTripReq} from './trip-req.js'; +const tripEndpoint_dbnav = dbnavBase.tripEndpoint; +const tripEndpoint_dbregioguide = dbregioguideBase.tripEndpoint; + +// arrivals(), departures() +const {boardEndpoint} = dbregioguideBase; + const profile = { locale: 'de-DE', timezone: 'Europe/Berlin', products, + + formatJourneysReq, + journeysEndpoint, + + formatRefreshJourneyReq, + refreshJourneysEndpointTickets, refreshJourneysEndpointPolyline, + + formatLocationsReq, formatLocationFilter, + locationsEndpoint, + + formatStopReq, parseStop, + stopEndpoint, + + formatNearbyReq, + nearbyEndpoint, + + formatTripReq, + tripEndpoint_dbnav, tripEndpoint_dbregioguide, + + boardEndpoint, }; -// add profile methods -for (const {profileName, profileMethods} of Object.values(dynamicProfileData)) { - for (const {methodName, moduleName} of profileMethods) { - try { - // TODO use `import()` with top-level await once updated to es2022 - profile[methodName] = require(`../${profileName}/${moduleName}`)[methodName]; - } catch { /* use implementation from default profile if module doesn't exist */ } - } -} - -const bases = { - dbnav: dbnavBase, - dbregioguide: dbregioguideBase, - dbweb: dbwebBase, -}; - -// add endpoint bases -for (const {profileName, baseKeys} of Object.values(dynamicProfileData)) { - if (profileName !== 'db') { // only add endpoint(s) from specified profile - for (const baseKey of baseKeys) { - profile[baseKey] = bases[profileName][baseKey]; - } - continue; - } - - // add endpoints from all profiles with the profile names as key suffixes and dynamically decide which to use later - for (const [profileName, profileBases] of Object.entries(bases)) { - for (const baseKey of baseKeys) { - profile[`${baseKey}_${profileName}`] = profileBases[baseKey]; - } - } -} export { profile, diff --git a/test/db-dynamic-handling.js b/test/db-dynamic-handling.js deleted file mode 100644 index 5b05c3b7..00000000 --- a/test/db-dynamic-handling.js +++ /dev/null @@ -1,60 +0,0 @@ -import {createRequire} from 'module'; -const require = createRequire(import.meta.url); - -import {createClient} from '../index.js'; -import {profile as rawProfile} from '../p/db/index.js'; -const dynamicProfileData = require('../p/db/dynamicProfileData.json'); -const dbnavBase = require('../p/dbnav/base.json'); -const dbwebBase = require('../p/dbweb/base.json'); -const dbregioguideBase = require('../p/dbregioguide/base.json'); - -import tap from 'tap'; - -const client = createClient(rawProfile, 'public-transport/hafas-client:test'); - -tap.test('db: determine base urls', (t) => { - const fqdns = { - dbnav: 'app.vendo.noncd.db.de', - dbregioguide: 'regio-guide.de', - dbweb: 'int.bahn.de', - }; - - for (const {profileName, baseKeys} of Object.values(dynamicProfileData)) { - if (profileName !== 'db') { // endpoint(s) is(/are) static. Check if correct fqdn is contained in base(s) - for (const baseKey of baseKeys) { - t.ok(client.profile[baseKey].includes(fqdns[profileName]), [`base url for ${profileName} profile should include ${fqdns[profileName]}`]); - } - continue; - } - - // endpoint(s) is(/are) dynamic. Check if actual base key does not exist yet. Also check, if bases for all profiles are properly stored in other aux entries for later use - for (const baseKey of baseKeys) { - for (const [profileName, fqdn] of Object.entries(fqdns)) { - t.notHas(client.profile, baseKey, [`db profile should not contain the key ${baseKey}, since it is dynamically dispatched at runtime`]); - t.ok(client.profile[`${baseKey}_${profileName}`].includes(fqdn), [`key ${baseKey}_${profileName} of db profile should include ${fqdns[profileName]}`]); - } - } - } - t.end(); -}); - -tap.test('db: dynamic client method', async (t) => { - t.equal(dynamicProfileData.trip.profileName, 'db', ['if this fails, check a different client method in this test']); - - t.equal(client.profile.formatTripReq, (await import('../p/db/trip-req.js')).formatTripReq); - t.notHas(client.profile, 'tripEndpoint'); - t.equal(client.profile.tripEndpoint_dbnav, dbnavBase.tripEndpoint); - t.equal(client.profile.tripEndpoint_dbweb, dbwebBase.tripEndpoint); - t.equal(client.profile.tripEndpoint_dbregioguide, dbregioguideBase.tripEndpoint); - - t.end(); -}); - -tap.test('db: static client method', async (t) => { - t.equal(dynamicProfileData.nearby.profileName, 'dbnav', ['if this fails, check a different client method in this test']); - - t.equal(client.profile.formatNearbyReq, (await import('../p/dbnav/nearby-req.js')).formatNearbyReq); - t.equal(client.profile.nearbyEndpoint, dbnavBase.nearbyEndpoint); - - t.end(); -}); diff --git a/test/format/db-trip.js b/test/format/db-trip.js new file mode 100644 index 00000000..e220c04a --- /dev/null +++ b/test/format/db-trip.js @@ -0,0 +1,47 @@ +import tap from 'tap'; + +import {profile as rawProfile} from '../../p/db/index.js'; +import {createClient} from '../../index.js'; + +const client = createClient(rawProfile, 'public-transport/hafas-client:test', {enrichStations: false}); +const {profile} = client; + +const opt = { + stopovers: true, + polyline: false, + remarks: true, + language: 'en', +}; + +const tripIdHafas = '2|#VN#1#ST#1738783727#PI#0#ZI#222242#TA#0#DA#70225#1S#8000237#1T#1317#LS#8000261#LT#2002#PU#80#RT#1#CA#ICE#ZE#1007#ZB#ICE 1007#PC#0#FR#8000237#FT#1317#TO#8000261#TT#2002#'; +const tripIdRis = '20250207-e6b2807e-bb48-39f9-89eb-8491ebc4b32c'; + +const reqDbNavExpected = { + endpoint: 'https://app.vendo.noncd.db.de/mob/zuglauf/', + path: '2%7C%23VN%231%23ST%231738783727%23PI%230%23ZI%23222242%23TA%230%23DA%2370225%231S%238000237%231T%231317%23LS%238000261%23LT%232002%23PU%2380%23RT%231%23CA%23ICE%23ZE%231007%23ZB%23ICE%201007%23PC%230%23FR%238000237%23FT%231317%23TO%238000261%23TT%232002%23', + headers: { + 'Accept': 'application/x.db.vendo.mob.zuglauf.v2+json', + 'Content-Type': 'application/x.db.vendo.mob.zuglauf.v2+json', + }, + method: 'get', +}; + +const reqDbRegioGuideExpected = { + endpoint: 'https://regio-guide.de/@prd/zupo-travel-information/api/public/ri/journey/', + path: '20250207-e6b2807e-bb48-39f9-89eb-8491ebc4b32c', + method: 'get', +}; + +tap.test('db trip(): dynamic request formatting', (t) => { + const ctx = {profile, opt}; + t.notHas(client.profile, 'tripEndpoint'); + + const reqDbNav = profile.formatTripReq(ctx, tripIdHafas); + delete reqDbNav.headers['X-Correlation-ID']; + const reqDbRegioGuide = profile.formatTripReq(ctx, tripIdRis); + + t.same(reqDbNav, reqDbNavExpected); + t.same(reqDbRegioGuide, reqDbRegioGuideExpected); + + t.end(); +});