From 9d367f007be7b673c9cf08bc5d8657b3d66ecbcb Mon Sep 17 00:00:00 2001 From: Ulf Winkelvos Date: Thu, 23 Jan 2025 15:50:20 +0100 Subject: [PATCH] Add 2.3 typescript models (#157) * add 2.3 typescript models * update release version --- models/typescript/.gitignore | 2 + models/typescript/index.d.ts | 5 +- models/typescript/package.json | 7 +- models/typescript/tests/v2.3.spec.ts | 128 ++++++++++++++++++++ models/typescript/v2.3/index.d.ts | 15 +++ scripts/generate_typescript_models.sh | 2 +- testFixtures/v2.3/free_bike_status.json | 24 ++++ testFixtures/v2.3/gbfs.json | 59 +++++++++ testFixtures/v2.3/gbfs_versions.json | 13 ++ testFixtures/v2.3/geofencing_zones.json | 123 +++++++++++++++++++ testFixtures/v2.3/station_information.json | 27 +++++ testFixtures/v2.3/station_status.json | 67 ++++++++++ testFixtures/v2.3/system_alerts.json | 23 ++++ testFixtures/v2.3/system_calendar.json | 17 +++ testFixtures/v2.3/system_hours.json | 27 +++++ testFixtures/v2.3/system_information.json | 22 ++++ testFixtures/v2.3/system_pricing_plans.json | 24 ++++ testFixtures/v2.3/system_regions.json | 13 ++ testFixtures/v2.3/vehicle_types.json | 20 +++ 19 files changed, 612 insertions(+), 6 deletions(-) create mode 100644 models/typescript/tests/v2.3.spec.ts create mode 100644 models/typescript/v2.3/index.d.ts create mode 100644 testFixtures/v2.3/free_bike_status.json create mode 100644 testFixtures/v2.3/gbfs.json create mode 100644 testFixtures/v2.3/gbfs_versions.json create mode 100644 testFixtures/v2.3/geofencing_zones.json create mode 100644 testFixtures/v2.3/station_information.json create mode 100644 testFixtures/v2.3/station_status.json create mode 100644 testFixtures/v2.3/system_alerts.json create mode 100644 testFixtures/v2.3/system_calendar.json create mode 100644 testFixtures/v2.3/system_hours.json create mode 100644 testFixtures/v2.3/system_information.json create mode 100644 testFixtures/v2.3/system_pricing_plans.json create mode 100644 testFixtures/v2.3/system_regions.json create mode 100644 testFixtures/v2.3/vehicle_types.json diff --git a/models/typescript/.gitignore b/models/typescript/.gitignore index 76501a3..488573c 100644 --- a/models/typescript/.gitignore +++ b/models/typescript/.gitignore @@ -1,3 +1,5 @@ +v2.3/* +!v2.3/index.d.ts v3.0/* !v3.0/index.d.ts v3.1-RC/* diff --git a/models/typescript/index.d.ts b/models/typescript/index.d.ts index b1e8897..82a2477 100644 --- a/models/typescript/index.d.ts +++ b/models/typescript/index.d.ts @@ -1,2 +1,3 @@ -export * as v3 from './v3.0'; -export * as v31rc from './v3.1-RC'; +export * as v23 from "./v2.3"; +export * as v3 from "./v3.0"; +export * as v31rc from "./v3.1-RC"; diff --git a/models/typescript/package.json b/models/typescript/package.json index e700d59..de49cf3 100644 --- a/models/typescript/package.json +++ b/models/typescript/package.json @@ -1,6 +1,6 @@ { "name": "gbfs-typescript-types", - "version": "1.0.9", + "version": "1.0.10", "description": "Language Bindings for GBFS in Typescript.", "license": "Apache-2.0", "types": "index.d.ts", @@ -11,8 +11,9 @@ }, "files": [ "index.d.ts", - "v3.1-RC", - "v3.0" + "v2.3", + "v3.0", + "v3.1-RC" ], "devDependencies": { "@types/jest": "^29.5.12", diff --git a/models/typescript/tests/v2.3.spec.ts b/models/typescript/tests/v2.3.spec.ts new file mode 100644 index 0000000..28cfbed --- /dev/null +++ b/models/typescript/tests/v2.3.spec.ts @@ -0,0 +1,128 @@ +import { createCheckers } from "ts-interface-checker"; + +// checker model +import FreeBikeStatusTI from "../v2.3/test-type-checkers/free_bike_status-ti"; +import GbfsVersionsTI from "../v2.3/test-type-checkers/gbfs_versions-ti"; +import GbfsTI from "../v2.3/test-type-checkers/gbfs-ti"; +import GeofencingZonesTI from "../v2.3/test-type-checkers/geofencing_zones-ti"; +import StationsInformationTI from "../v2.3/test-type-checkers/station_information-ti"; +import StationStatusTI from "../v2.3/test-type-checkers/station_status-ti"; +import SystemAlertsTI from "../v2.3/test-type-checkers/system_alerts-ti"; +import SystemCalendarTI from "../v2.3/test-type-checkers/system_calendar-ti"; +import SystemHoursTI from "../v2.3/test-type-checkers/system_hours-ti"; +import SystemInformationTI from "../v2.3/test-type-checkers/system_information-ti"; +import SystemPricingPlansTI from "../v2.3/test-type-checkers/system_pricing_plans-ti"; +import SystemRegionsTI from "../v2.3/test-type-checkers/system_regions-ti"; +import VehicleTypesTI from "../v2.3/test-type-checkers/vehicle_types-ti"; + +// checkers +const { FreeBikeStatus } = createCheckers(FreeBikeStatusTI); +const { GbfsVersions } = createCheckers(GbfsVersionsTI); +const { Gbfs } = createCheckers(GbfsTI); +const { GeofencingZones } = createCheckers(GeofencingZonesTI); +const { StationInformation } = createCheckers(StationsInformationTI); +const { StationStatus } = createCheckers(StationStatusTI); +const { SystemAlerts } = createCheckers(SystemAlertsTI); +const { SystemCalendar } = createCheckers(SystemCalendarTI); +const { SystemHours } = createCheckers(SystemHoursTI); +const { SystemInformation } = createCheckers(SystemInformationTI); +const { SystemPricingPlans } = createCheckers(SystemPricingPlansTI); +const { SystemRegions } = createCheckers(SystemRegionsTI); +const { VehicleTypes } = createCheckers(VehicleTypesTI); + +// json test data: these are gbfs with no errors for v2.3 +import freeBikeStatusJson from "../../../testFixtures/v2.3/free_bike_status.json"; +import gbfsVersionsJson from "../../../testFixtures/v2.3/gbfs_versions.json"; +import gbfsJson from "../../../testFixtures/v2.3/gbfs.json"; +import geofencingZonesJson from "../../../testFixtures/v2.3/geofencing_zones.json"; +import stationInformationJson from "../../../testFixtures/v2.3/station_information.json"; +import stationStatusJson from "../../../testFixtures/v2.3/station_status.json"; +import systemAlertsJson from "../../../testFixtures/v2.3/system_alerts.json"; +import systemCalendarJson from "../../../testFixtures/v2.3/system_calendar.json"; +import systemHoursJson from "../../../testFixtures/v2.3/system_hours.json"; +import systemInformationJson from "../../../testFixtures/v2.3/system_information.json"; +import systemPricingPlansJson from "../../../testFixtures/v2.3/system_pricing_plans.json"; +import systemRegionsJson from "../../../testFixtures/v2.3/system_regions.json"; +import vehicleTypesJson from "../../../testFixtures/v2.3/vehicle_types.json"; + +// Date objects cannot be represented in JSON +// Manual checks for dates are required +describe("GBFS Validator v2.3", () => { + it("should check if gbfs_versions is valid", () => { + expect(() => { + GbfsVersions.check(gbfsVersionsJson); + }).not.toThrow(); + }); + + it("should check if gbfs is valid", () => { + expect(() => { + Gbfs.check(gbfsJson); + }).not.toThrow(); + }); + + it("should check if geofencing_zones is valid", () => { + expect(() => { + GeofencingZones.check(geofencingZonesJson); + }).not.toThrow(); + }); + + it("should check if station_information is valid", () => { + expect(() => { + StationInformation.check(stationInformationJson); + }).not.toThrow(); + }); + + it("should check if station_status is valid", () => { + expect(() => { + StationStatus.check(stationStatusJson); + }).not.toThrow(); + }); + + it("should check if system_alerts is valid", () => { + expect(() => { + SystemAlerts.check(systemAlertsJson); + }).not.toThrow(); + }); + + it("should check if system_information is valid", () => { + expect(() => { + SystemCalendar.check(systemCalendarJson); + }).not.toThrow(); + }); + + it("should check if system_information is valid", () => { + expect(() => { + SystemHours.check(systemHoursJson); + }).not.toThrow(); + }); + + it("should check if system_information is valid", () => { + expect(() => { + SystemInformation.check(systemInformationJson); + }).not.toThrow(); + }); + + it("should check if system_pricing_plans is valid", () => { + expect(() => { + SystemPricingPlans.check(systemPricingPlansJson); + }).not.toThrow(); + }); + + it("should check if system_regions is valid", () => { + expect(() => { + SystemRegions.check(systemRegionsJson); + }).not.toThrow(); + }); + + it("should check if vehicle_status is valida", () => { + expect(() => { + FreeBikeStatus.check(freeBikeStatusJson); + }).not.toThrow(); + }); + + it("should check if vehicle_types is valid", () => { + expect(() => { + VehicleTypes.check(vehicleTypesJson); + }).not.toThrow(); + }); +}); diff --git a/models/typescript/v2.3/index.d.ts b/models/typescript/v2.3/index.d.ts new file mode 100644 index 0000000..5b5a5a4 --- /dev/null +++ b/models/typescript/v2.3/index.d.ts @@ -0,0 +1,15 @@ +// Exports auto generated files + +export { FreeBikeStatus } from "./free_bike_status"; +export { GbfsVersions } from "./gbfs_versions"; +export { Gbfs } from "./gbfs"; +export { GeofencingZones } from "./geofencing_zones"; +export { StationInformation } from "./station_information"; +export { StationStatus } from "./station_status"; +export { SystemAlerts } from "./system_alerts"; +export { SystemCalendar } from "./system_calendar"; +export { SystemHours } from "./system_hours"; +export { SystemInformation } from "./system_information"; +export { SystemPricingPlans } from "./system_pricing_plans"; +export { SystemRegions } from "./system_regions"; +export { VehicleTypes } from "./vehicle_types"; diff --git a/scripts/generate_typescript_models.sh b/scripts/generate_typescript_models.sh index a37618a..a62a2df 100755 --- a/scripts/generate_typescript_models.sh +++ b/scripts/generate_typescript_models.sh @@ -10,7 +10,7 @@ gbfs_version="v$1" #$1 is the first argument passed to the script (the version n parent_dir="$(dirname "$(dirname "$0")")" copyright_file="$parent_dir/copyright.txt" -gbfs_versions=("v3.0" "v3.1-RC") +gbfs_versions=("v2.3" "v3.0" "v3.1-RC") for gbfs_version in "${gbfs_versions[@]}"; do echo "gbfs_version: $gbfs_version" diff --git a/testFixtures/v2.3/free_bike_status.json b/testFixtures/v2.3/free_bike_status.json new file mode 100644 index 0000000..f452447 --- /dev/null +++ b/testFixtures/v2.3/free_bike_status.json @@ -0,0 +1,24 @@ +{ + "last_updated": 1606857968, + "ttl": 300, + "version": "2.3", + "data": { + "bikes": [ + { + "bike_id": "TST:Scooter:1234", + "lat": 59.91465759277344, + "lon": 10.760470390319824, + "is_reserved": false, + "is_disabled": true, + "vehicle_type_id": "TST:VehicleType:Scooter", + "current_range_meters": 1431.2, + "pricing_plan_id": "TST:PricingPlan:Basic", + "rental_uris": { + "android": "test://rentme/TST:Scooter:1234", + "ios": "test://rentme/TST:Scooter:1234", + "web": "https://test.com/rentme/TST:Scooter:1234" + } + } + ] + } +} diff --git a/testFixtures/v2.3/gbfs.json b/testFixtures/v2.3/gbfs.json new file mode 100644 index 0000000..ce5b8cc --- /dev/null +++ b/testFixtures/v2.3/gbfs.json @@ -0,0 +1,59 @@ +{ + "last_updated": 1606727710, + "ttl": 300, + "version": "2.3", + "data": { + "en": { + "feeds": [ + { + "name": "gbfs_versions", + "url": "https://test.com/gbfs_versions" + }, + { + "name": "system_information", + "url": "https://test.com/system_information" + }, + { + "name": "vehicle_types", + "url": "https://test.com/vehicle_types" + }, + { + "name": "station_information", + "url": "https://test.com/station_information" + }, + { + "name": "station_status", + "url": "https://test.com/station_status" + }, + { + "name": "free_bike_status", + "url": "https://test.com/free_bike_status" + }, + { + "name": "system_regions", + "url": "https://test.com/system_regions" + }, + { + "name": "system_pricing_plans", + "url": "https://test.com/system_pricing_plans" + }, + { + "name": "system_hours", + "url": "https://test.com/system_hours" + }, + { + "name": "system_calendar", + "url": "https://test.com/system_calendar" + }, + { + "name": "system_alerts", + "url": "https://test.com/system_alerts" + }, + { + "name": "geofencing_zones", + "url": "https://test.com/geofencing_zones" + } + ] + } + } +} diff --git a/testFixtures/v2.3/gbfs_versions.json b/testFixtures/v2.3/gbfs_versions.json new file mode 100644 index 0000000..7352abc --- /dev/null +++ b/testFixtures/v2.3/gbfs_versions.json @@ -0,0 +1,13 @@ +{ + "last_updated": 1434054678, + "ttl": 0, + "version": "2.3", + "data": { + "versions": [ + { + "version": "2.2", + "url": "https://test.com/gbfs.json" + } + ] + } +} diff --git a/testFixtures/v2.3/geofencing_zones.json b/testFixtures/v2.3/geofencing_zones.json new file mode 100644 index 0000000..8c9374f --- /dev/null +++ b/testFixtures/v2.3/geofencing_zones.json @@ -0,0 +1,123 @@ +{ + "last_updated": 1434054678, + "ttl": 0, + "version": "2.3", + "data": { + "geofencing_zones": { + "type": "FeatureCollection", + "features": [ + { + "type": "Feature", + "properties": { + "name": "Nes", + "rules": [ + { + "vehicle_type_ids": ["TST:VehicleType:CityBike"], + "ride_allowed": true, + "ride_through_allowed": false, + "maximum_speed_kph": 20 + } + ] + }, + "geometry": { + "type": "MultiPolygon", + "coordinates": [ + [ + [ + [11.53037789067, 60.13740063434], + [11.53372523957, 60.13598476211], + [11.544177, 60.132072], + [11.555332, 60.126844], + [11.567186, 60.112231], + [11.56403794135, 60.10918526319], + [11.5629827195, 60.10773004658], + [11.559217, 60.101878], + [11.55869921547, 60.1018221676], + [11.55847, 60.101506], + [11.55581995556, 60.10123306033], + [11.555637, 60.101056], + [11.49821, 60.095299], + [11.46896, 60.07201], + [11.465957, 60.063589], + [11.476578, 60.059879], + [11.467241, 60.045013], + [11.436058, 60.032524], + [11.394385, 60.029916], + [11.38968940258, 60.03265856905], + [11.375861, 60.030292], + [11.365442, 60.024714], + [11.342163, 60.03279], + [11.325316, 60.033807], + [11.31339, 60.049798], + [11.294868, 60.063006], + [11.306277, 60.071862], + [11.325134, 60.077875], + [11.3179, 60.093846], + [11.33319, 60.108785], + [11.332603, 60.128479], + [11.347831, 60.138723], + [11.32735488653, 60.13999842085], + [11.32497308493, 60.14556400031], + [11.32493016958, 60.14790318539], + [11.3246405071, 60.14881370558], + [11.3217544502, 60.14920087268], + [11.32161497533, 60.15038904672], + [11.32253764987, 60.15125678982], + [11.32308482051, 60.15271988181], + [11.3271295917, 60.15647876853], + [11.32802007437, 60.1609739234], + [11.32733336449, 60.1687562641], + [11.31669035912, 60.17985540754], + [11.29737845421, 60.18267228561], + [11.30046835899, 60.19009744236], + [11.32081023216, 60.19607048737], + [11.32132521629, 60.19820345431], + [11.31720534325, 60.19944051162], + [11.31566039085, 60.20404707345], + [11.31428709984, 60.20660599502], + [11.30793562889, 60.21197908067], + [11.29720679283, 60.21342881013], + [11.29205695152, 60.22250948067], + [11.27961150169, 60.21641334548], + [11.25377646446, 60.25220658872], + [11.30664816856, 60.2682156618], + [11.31445876122, 60.2603824128], + [11.328425, 60.265399], + [11.344468, 60.265328], + [11.382948, 60.253896], + [11.415655, 60.237796], + [11.432291, 60.221773], + [11.437049, 60.22409], + [11.421506, 60.247612], + [11.437835, 60.261601], + [11.412849, 60.285637], + [11.417028, 60.305307], + [11.444868, 60.325789], + [11.515287, 60.304312], + [11.601261, 60.267216], + [11.598781, 60.244722], + [11.584431, 60.236376], + [11.58390281439, 60.20433493011], + [11.58154247046, 60.20230899341], + [11.58229348898, 60.20020828485], + [11.5798902297, 60.20017629332], + [11.5793537879, 60.19961110456], + [11.57785175085, 60.19900324918], + [11.57600639105, 60.19744623492], + [11.57697198629, 60.19644373459], + [11.560396, 60.179793], + [11.5646123457, 60.17349518201], + [11.57135005474, 60.17688886704], + [11.586852, 60.169218], + [11.58838, 60.162737], + [11.554175, 60.14945], + [11.53037789067, 60.13740063434] + ] + ] + ] + } + } + ] + } + } +} diff --git a/testFixtures/v2.3/station_information.json b/testFixtures/v2.3/station_information.json new file mode 100644 index 0000000..7c14289 --- /dev/null +++ b/testFixtures/v2.3/station_information.json @@ -0,0 +1,27 @@ +{ + "last_updated": 1434054678, + "ttl": 0, + "version": "2.3", + "data": { + "stations": [ + { + "station_id": "TST:Station:1", + "name": "Cool bikes", + "lat": 12.34, + "lon": 45.67, + "vehicle_type_capacity": { + "TST:VehicleType:CityBike": 7 + } + }, + { + "station_id": "TST:Station:2", + "name": "Cooler bikes", + "lat": 11.34, + "lon": 44.67, + "vehicle_type_capacity": { + "TST:VehicleType:CityBike": 12 + } + } + ] + } +} diff --git a/testFixtures/v2.3/station_status.json b/testFixtures/v2.3/station_status.json new file mode 100644 index 0000000..bc2771f --- /dev/null +++ b/testFixtures/v2.3/station_status.json @@ -0,0 +1,67 @@ +{ + "last_updated": 1434054678, + "ttl": 0, + "version": "2.3", + "data": { + "stations": [ + { + "station_id": "TST:Station:1", + "is_installed": true, + "is_renting": true, + "is_returning": true, + "last_reported": 1434054678, + "num_docks_available": 3, + "vehicle_docks_available": [ + { + "vehicle_type_ids": ["TST:VehicleType:Scooter"], + "count": 2 + }, + { + "vehicle_type_ids": ["TST:VehicleType:CityBike"], + "count": 1 + } + ], + "num_bikes_available": 1, + "vehicle_types_available": [ + { + "vehicle_type_id": "TST:VehicleType:Scooter", + "count": 1 + }, + { + "vehicle_type_id": "TST:VehicleType:CityBike", + "count": 0 + } + ] + }, + { + "station_id": "TST:Station:2", + "is_installed": true, + "is_renting": true, + "is_returning": true, + "last_reported": 1434054678, + "num_docks_available": 8, + "vehicle_docks_available": [ + { + "vehicle_type_ids": ["TST:VehicleType:Scooter"], + "count": 6 + }, + { + "vehicle_type_ids": ["TST:VehicleType:CityBike"], + "count": 2 + } + ], + "num_bikes_available": 6, + "vehicle_types_available": [ + { + "vehicle_type_id": "TST:VehicleType:Scooter", + "count": 2 + }, + { + "vehicle_type_id": "TST:VehicleType:CityBike", + "count": 4 + } + ] + } + ] + } +} diff --git a/testFixtures/v2.3/system_alerts.json b/testFixtures/v2.3/system_alerts.json new file mode 100644 index 0000000..e82f1d2 --- /dev/null +++ b/testFixtures/v2.3/system_alerts.json @@ -0,0 +1,23 @@ +{ + "last_updated": 1434054678, + "ttl": 0, + "version": "2.3", + "data": { + "alerts": [ + { + "alert_id": "TST:Alert:1", + "type": "station_closure", + "times": [ + { + "start": 1434054678, + "end": 1434054987 + } + ], + "station_ids": ["TST:Station:1"], + "summary": "Closed for maintenance", + "description": "Station is closed to install more docks.", + "last_updated": 1434054678 + } + ] + } +} diff --git a/testFixtures/v2.3/system_calendar.json b/testFixtures/v2.3/system_calendar.json new file mode 100644 index 0000000..14ec7cb --- /dev/null +++ b/testFixtures/v2.3/system_calendar.json @@ -0,0 +1,17 @@ +{ + "last_updated": 1434054678, + "ttl": 0, + "version": "2.3", + "data": { + "calendars": [ + { + "start_month": 1, + "start_day": 1, + "start_year": 2020, + "end_month": 12, + "end_day": 30, + "end_year": 2021 + } + ] + } +} diff --git a/testFixtures/v2.3/system_hours.json b/testFixtures/v2.3/system_hours.json new file mode 100644 index 0000000..1ec6a08 --- /dev/null +++ b/testFixtures/v2.3/system_hours.json @@ -0,0 +1,27 @@ +{ + "last_updated": 1434054678, + "ttl": 0, + "version": "2.3", + "data": { + "rental_hours": [ + { + "user_types": ["member"], + "days": ["sat", "sun"], + "start_time": "00:00:00", + "end_time": "23:59:59" + }, + { + "user_types": ["nonmember"], + "days": ["sat", "sun"], + "start_time": "05:00:00", + "end_time": "23:59:59" + }, + { + "user_types": ["member", "nonmember"], + "days": ["mon", "tue", "wed", "thu", "fri"], + "start_time": "00:00:00", + "end_time": "23:59:59" + } + ] + } +} diff --git a/testFixtures/v2.3/system_information.json b/testFixtures/v2.3/system_information.json new file mode 100644 index 0000000..1c19495 --- /dev/null +++ b/testFixtures/v2.3/system_information.json @@ -0,0 +1,22 @@ +{ + "last_updated": 1606830357, + "ttl": 300, + "version": "2.3", + "data": { + "system_id": "TST:System:Test", + "language": "en", + "name": "Test", + "url": "https://www.test.com/", + "timezone": "Europe/Oslo", + "rental_apps": { + "android": { + "store_uri": "https://play.google.com/store/apps/details?id=com.testrental.android", + "discovery_uri": "com.testrental.android://" + }, + "ios": { + "store_uri": "https://apps.apple.com/app/apple-store/id123456789", + "discovery_uri": "com.testrental.ios://" + } + } + } +} diff --git a/testFixtures/v2.3/system_pricing_plans.json b/testFixtures/v2.3/system_pricing_plans.json new file mode 100644 index 0000000..f597ff4 --- /dev/null +++ b/testFixtures/v2.3/system_pricing_plans.json @@ -0,0 +1,24 @@ +{ + "last_updated": 1606858558, + "ttl": 300, + "version": "2.3", + "data": { + "plans": [ + { + "plan_id": "TST:PricingPlan:Basic", + "name": "Basic", + "currency": "NOK", + "price": 0.0, + "is_taxable": false, + "description": "Start NOK 0, Per minute 3,50 NOK", + "per_min_pricing": [ + { + "start": 0, + "rate": 3.5, + "interval": 1 + } + ] + } + ] + } +} diff --git a/testFixtures/v2.3/system_regions.json b/testFixtures/v2.3/system_regions.json new file mode 100644 index 0000000..60997ba --- /dev/null +++ b/testFixtures/v2.3/system_regions.json @@ -0,0 +1,13 @@ +{ + "last_updated": 1606858379, + "ttl": 300, + "version": "2.3", + "data": { + "regions": [ + { + "region_id": "TST:Region:Sahara", + "name": "Sahara" + } + ] + } +} diff --git a/testFixtures/v2.3/vehicle_types.json b/testFixtures/v2.3/vehicle_types.json new file mode 100644 index 0000000..9937f1b --- /dev/null +++ b/testFixtures/v2.3/vehicle_types.json @@ -0,0 +1,20 @@ +{ + "last_updated": 1606830898, + "ttl": 300, + "version": "2.3", + "data": { + "vehicle_types": [ + { + "vehicle_type_id": "TST:VehicleType:Scooter", + "form_factor": "scooter", + "propulsion_type": "electric", + "max_range_meters": 0.0 + }, + { + "vehicle_type_id": "TST:VehicleType:CityBike", + "form_factor": "bicycle", + "propulsion_type": "human" + } + ] + } +}