[{"data":1,"prerenderedAt":729},["Reactive",2],{"navigation-list":3,"page-/examples/routes/preferred-operator-navigation-name":460,"page-/examples/routes/preferred-operator":461},{"api-reference":4,"basics":312,"examples":353,"tree":440},{"asideHeader":5,"sectionList":6,"mainHeader":311},"API reference",[7,29,50,95,120,142,155,188,217,249,270],{"label":8,"navigation":-1,"to":9,"icon":10,"itemList":11},"API","/api-reference/api","medium/products/api",[12,17,21,25],{"label":13,"navigation":14,"to":15,"icon":-1,"itemList":16},"Quick setup guide","api-reference","/api-reference/api/quick-setup-guide",[],{"label":18,"navigation":14,"to":19,"icon":-1,"itemList":20},"Pagination","/api-reference/api/pagination",[],{"label":22,"navigation":14,"to":23,"icon":-1,"itemList":24},"API lifecycle","/api-reference/api/api-lifecycle",[],{"label":26,"navigation":14,"to":27,"icon":-1,"itemList":28},"Beta features","/api-reference/api/beta-features",[],{"label":30,"navigation":-1,"to":31,"icon":32,"itemList":33},"Vehicles","/api-reference/vehicle","medium/products/vehicle",[34,38,42,46],{"label":35,"navigation":14,"to":36,"icon":-1,"itemList":37},"Vehicle introduction","/api-reference/vehicle/introduction",[],{"label":39,"navigation":14,"to":40,"icon":-1,"itemList":41},"Query vehicles","/api-reference/vehicle/query-vehicles",[],{"label":43,"navigation":14,"to":44,"icon":-1,"itemList":45},"Query vehicle details","/api-reference/vehicle/query-vehicle-details",[],{"label":47,"navigation":14,"to":48,"icon":-1,"itemList":49},"Query premium vehicle details","/api-reference/vehicle/query-premium-vehicle-details",[],{"label":51,"navigation":-1,"to":52,"icon":53,"itemList":54},"Stations","/api-reference/stations","medium/products/charge-station",[55,59,63,67,71,75,79,83,87,91],{"label":56,"navigation":14,"to":57,"icon":-1,"itemList":58},"Station introduction","/api-reference/stations/introduction",[],{"label":60,"navigation":14,"to":61,"icon":-1,"itemList":62},"Query station details","/api-reference/stations/query-station-details",[],{"label":64,"navigation":14,"to":65,"icon":-1,"itemList":66},"Query stations around a GeoJSON point","/api-reference/stations/query-stations-around",[],{"label":68,"navigation":14,"to":69,"icon":-1,"itemList":70},"Query station reviews","/api-reference/stations/query-stations-reviews",[],{"label":72,"navigation":14,"to":73,"icon":-1,"itemList":74},"Mutate to create a station review","/api-reference/stations/mutate-station-reviews",[],{"label":76,"navigation":14,"to":77,"icon":-1,"itemList":78},"Query station operators","/api-reference/stations/query-station-operators",[],{"label":80,"navigation":14,"to":81,"icon":-1,"itemList":82},"Query station operator details","/api-reference/stations/query-station-operator-details",[],{"label":84,"navigation":14,"to":85,"icon":-1,"itemList":86},"Query station tariffs","/api-reference/stations/query-station-tariffs",[],{"label":88,"navigation":14,"to":89,"icon":-1,"itemList":90},"Query station tariff details","/api-reference/stations/query-station-tariff-details",[],{"label":92,"navigation":14,"to":93,"icon":-1,"itemList":94},"Query station amenities","/api-reference/stations/query-station-amenities",[],{"label":96,"navigation":-1,"to":97,"icon":98,"itemList":99},"Legacy | Routes","/api-reference/routes-legacy","medium/products/route",[100,104,108,112,116],{"label":101,"navigation":14,"to":102,"icon":-1,"itemList":103},"Route legacy introduction","/api-reference/routes-legacy/introduction",[],{"label":105,"navigation":14,"to":106,"icon":-1,"itemList":107},"Mutate to create a new legacy route","/api-reference/routes-legacy/mutate-route",[],{"label":109,"navigation":14,"to":110,"icon":-1,"itemList":111},"Subscribe to route updates","/api-reference/routes-legacy/subscribe-to-route-updates",[],{"label":113,"navigation":14,"to":114,"icon":-1,"itemList":115},"Query route details","/api-reference/routes-legacy/query-route-details",[],{"label":117,"navigation":14,"to":118,"icon":-1,"itemList":119},"Query route path","/api-reference/routes-legacy/query-route-path",[],{"label":121,"navigation":-1,"to":122,"icon":98,"itemList":123},"Routes","/api-reference/routes",[124,128,132,136,139],{"label":125,"navigation":14,"to":126,"icon":-1,"itemList":127},"Route introduction","/api-reference/routes/introduction",[],{"label":129,"navigation":14,"to":130,"icon":-1,"itemList":131},"Migration from Route Legacy","/api-reference/routes/migration",[],{"label":133,"navigation":14,"to":134,"icon":-1,"itemList":135},"Mutate to create a new route","/api-reference/routes/mutate-route",[],{"label":109,"navigation":14,"to":137,"icon":-1,"itemList":138},"/api-reference/routes/subscribe-to-route-updates",[],{"label":113,"navigation":14,"to":140,"icon":-1,"itemList":141},"/api-reference/routes/query-route-details",[],{"label":143,"navigation":-1,"to":144,"icon":145,"itemList":146},"Emissions","/api-reference/route-emissions","medium/content/leaf",[147,151],{"label":148,"navigation":14,"to":149,"icon":-1,"itemList":150},"Route emissions introduction","/api-reference/route-emissions/introduction",[],{"label":152,"navigation":14,"to":153,"icon":-1,"itemList":154},"Query route emissions","/api-reference/route-emissions/query-route-emissions",[],{"label":156,"navigation":-1,"to":157,"icon":158,"itemList":159},"Navigation","/api-reference/navigation","medium/products/navigation",[160,164,168,172,176,180,184],{"label":161,"navigation":14,"to":162,"icon":-1,"itemList":163},"Navigation introduction","/api-reference/navigation/introduction",[],{"label":165,"navigation":14,"to":166,"icon":-1,"itemList":167},"Mutate to start a new navigation session","/api-reference/navigation/mutate-start-navigation",[],{"label":169,"navigation":14,"to":170,"icon":-1,"itemList":171},"Subscribe to navigation updates","/api-reference/navigation/subscribe-to-navigation-updates",[],{"label":173,"navigation":14,"to":174,"icon":-1,"itemList":175},"Query navigation session","/api-reference/navigation/query-a-navigation-session",[],{"label":177,"navigation":14,"to":178,"icon":-1,"itemList":179},"Mutate to update a navigation session","/api-reference/navigation/mutate-update-navigation",[],{"label":181,"navigation":14,"to":182,"icon":-1,"itemList":183},"Mutate to recalculate navigation","/api-reference/navigation/mutate-recalculate-navigation",[],{"label":185,"navigation":14,"to":186,"icon":-1,"itemList":187},"Mutate to finish navigation","/api-reference/navigation/mutate-to-finish-navigation",[],{"label":189,"navigation":-1,"to":190,"icon":191,"itemList":192},"Legacy | Tile service","/api-reference/tile-service-legacy","medium/products/tile-set",[193,197,201,205,209,213],{"label":194,"navigation":14,"to":195,"icon":-1,"itemList":196},"Legacy | Tile service introduction","/api-reference/tile-service-legacy/introduction",[],{"label":198,"navigation":14,"to":199,"icon":-1,"itemList":200},"Legacy | Mapbox Vector Tile","/api-reference/tile-service-legacy/mvt",[],{"label":202,"navigation":14,"to":203,"icon":-1,"itemList":204},"Legacy | JSON Tile","/api-reference/tile-service-legacy/json",[],{"label":206,"navigation":14,"to":207,"icon":-1,"itemList":208},"Legacy | Filters","/api-reference/tile-service-legacy/filters",[],{"label":210,"navigation":14,"to":211,"icon":-1,"itemList":212},"Legacy | Selectors","/api-reference/tile-service-legacy/selectors",[],{"label":214,"navigation":14,"to":215,"icon":-1,"itemList":216},"Legacy | Integration","/api-reference/tile-service-legacy/integration",[],{"label":218,"navigation":-1,"to":219,"icon":191,"itemList":220},"Tile service","/api-reference/tile-service",[221,225,229,233,237,241,245],{"label":222,"navigation":14,"to":223,"icon":-1,"itemList":224},"Tile service introduction","/api-reference/tile-service/introduction",[],{"label":226,"navigation":14,"to":227,"icon":-1,"itemList":228},"Mapbox Vector Tile","/api-reference/tile-service/mvt",[],{"label":230,"navigation":14,"to":231,"icon":-1,"itemList":232},"JSON Tile","/api-reference/tile-service/json",[],{"label":234,"navigation":14,"to":235,"icon":-1,"itemList":236},"Filters","/api-reference/tile-service/filters",[],{"label":238,"navigation":14,"to":239,"icon":-1,"itemList":240},"Selectors","/api-reference/tile-service/selectors",[],{"label":242,"navigation":14,"to":243,"icon":-1,"itemList":244},"Station count","/api-reference/tile-service/count",[],{"label":246,"navigation":14,"to":247,"icon":-1,"itemList":248},"Integration","/api-reference/tile-service/integration",[],{"label":250,"navigation":-1,"to":251,"icon":252,"itemList":253},"Isolines","/api-reference/isolines","medium/products/isoline",[254,258,262,266],{"label":255,"navigation":14,"to":256,"icon":-1,"itemList":257},"Isoline introduction","/api-reference/isolines/introduction",[],{"label":259,"navigation":14,"to":260,"icon":-1,"itemList":261},"Mutation to create an isoline","/api-reference/isolines/mutate-isoline",[],{"label":263,"navigation":14,"to":264,"icon":-1,"itemList":265},"Subscribe to isoline details","/api-reference/isolines/subscribe-to-isoline",[],{"label":267,"navigation":14,"to":268,"icon":-1,"itemList":269},"Query isoline details","/api-reference/isolines/query-isoline",[],{"label":271,"navigation":-1,"to":272,"icon":273,"itemList":274},"Vehicle connectivity","/api-reference/vehicle-connectivity","medium/products/connectivity",[275,279,283,287,291,295,299,303,307],{"label":276,"navigation":14,"to":277,"icon":-1,"itemList":278},"Introduction","/api-reference/vehicle-connectivity/introduction",[],{"label":280,"navigation":14,"to":281,"icon":-1,"itemList":282},"Mutate to create a new connected vehicle","/api-reference/vehicle-connectivity/mutate-create-connected-vehicle",[],{"label":284,"navigation":14,"to":285,"icon":-1,"itemList":286},"Subscribe to a connected vehicle","/api-reference/vehicle-connectivity/subscribe-connected-vehicle",[],{"label":288,"navigation":14,"to":289,"icon":-1,"itemList":290},"Mutate to authorize a connected vehicle","/api-reference/vehicle-connectivity/mutate-authorize-connected-vehicle",[],{"label":292,"navigation":14,"to":293,"icon":-1,"itemList":294},"Query connected vehicle list","/api-reference/vehicle-connectivity/query-connected-vehicle-list",[],{"label":296,"navigation":14,"to":297,"icon":-1,"itemList":298},"Query data from vehicle","/api-reference/vehicle-connectivity/query-connected-vehicle-data",[],{"label":300,"navigation":14,"to":301,"icon":-1,"itemList":302},"Query connected vehicle","/api-reference/vehicle-connectivity/query-connected-vehicle",[],{"label":304,"navigation":14,"to":305,"icon":-1,"itemList":306},"Mutate to update a connected vehicle","/api-reference/vehicle-connectivity/mutate-update-connected-vehicle",[],{"label":308,"navigation":14,"to":309,"icon":-1,"itemList":310},"Mutate to remove a connected vehicle","/api-reference/vehicle-connectivity/mutate-remove-connected-vehicle",[],"Sections",{"asideHeader":313,"sectionList":314,"mainHeader":311},"Basics",[315,341],{"label":316,"navigation":-1,"to":317,"icon":318,"itemList":319},"API Basics","/basics/api-basics","medium/code/code",[320,325,329,333,337],{"label":321,"navigation":322,"to":323,"icon":-1,"itemList":324},"Getting started","basics","/basics/api-basics/getting-started",[],{"label":326,"navigation":322,"to":327,"icon":-1,"itemList":328},"Authorization","/basics/api-basics/authorization",[],{"label":330,"navigation":322,"to":331,"icon":-1,"itemList":332},"Security","/basics/api-basics/security",[],{"label":334,"navigation":322,"to":335,"icon":-1,"itemList":336},"Status & error codes","/basics/api-basics/status-and-error-codes",[],{"label":338,"navigation":322,"to":339,"icon":-1,"itemList":340},"Subscriptions","/basics/api-basics/subscriptions",[],{"label":342,"navigation":-1,"to":343,"icon":318,"itemList":344},"Learn more","/basics/other-basics",[345,349],{"label":346,"navigation":322,"to":347,"icon":-1,"itemList":348},"GraphQL Basics","/basics/other-basics/graphql-basics",[],{"label":350,"navigation":322,"to":351,"icon":-1,"itemList":352},"EV basics","/basics/other-basics/ev-basics",[],{"asideHeader":354,"sectionList":355,"mainHeader":439},"API Section",[356,369,380,420,432],{"label":30,"navigation":-1,"to":357,"icon":358,"itemList":359},"/examples/vehicles","car",[360,365],{"label":361,"navigation":362,"to":363,"icon":-1,"itemList":364},"Vehicle list","examples","/examples/vehicles/vehicle-list",[],{"label":366,"navigation":362,"to":367,"icon":-1,"itemList":368},"Vehicle details","/examples/vehicles/vehicle-details",[],{"label":51,"navigation":-1,"to":370,"icon":371,"itemList":372},"/examples/stations","charge-stations",[373,376],{"label":51,"navigation":362,"to":374,"icon":-1,"itemList":375},"/examples/stations/station-list",[],{"label":377,"navigation":362,"to":378,"icon":-1,"itemList":379},"Station details","/examples/stations/station-info",[],{"label":121,"navigation":-1,"to":381,"icon":382,"itemList":383},"/examples/routes","route",[384,388,392,396,400,404,408,412,416],{"label":385,"navigation":362,"to":386,"icon":-1,"itemList":387},"Route","/examples/routes/route",[],{"label":389,"navigation":362,"to":390,"icon":-1,"itemList":391},"Route (NEW)","/examples/routes/route-new",[],{"label":393,"navigation":362,"to":394,"icon":-1,"itemList":395},"Alternative routes","/examples/routes/alternative-routes",[],{"label":397,"navigation":362,"to":398,"icon":-1,"itemList":399},"Alternative stations","/examples/routes/stations-along-route",[],{"label":401,"navigation":362,"to":402,"icon":-1,"itemList":403},"Operator preference","/examples/routes/preferred-operator",[],{"label":405,"navigation":362,"to":406,"icon":-1,"itemList":407},"Elevation plot","/examples/routes/elevation-plot",[],{"label":409,"navigation":362,"to":410,"icon":-1,"itemList":411},"Battery capacity","/examples/routes/battery-capacity",[],{"label":413,"navigation":362,"to":414,"icon":-1,"itemList":415},"State of charge","/examples/routes/state-of-charge",[],{"label":417,"navigation":362,"to":418,"icon":-1,"itemList":419},"Toll roads and Ferries","/examples/routes/tolls-and-ferries",[],{"label":218,"navigation":-1,"to":421,"icon":422,"itemList":423},"/examples/tile-service","layers",[424,428],{"label":425,"navigation":362,"to":426,"icon":-1,"itemList":427},"Mapbox Vector Tiles","/examples/tile-service/tile-server",[],{"label":429,"navigation":362,"to":430,"icon":-1,"itemList":431},"GeoJSON tiles","/examples/tile-service/tile-json",[],{"label":250,"navigation":-1,"to":433,"icon":434,"itemList":435},"/examples/isolines","isoline",[436],{"label":250,"navigation":362,"to":437,"icon":-1,"itemList":438},"/examples/isolines/isoline",[],"Examples",[441,445,447,452,457],{"label":313,"navigation":442,"to":443,"icon":444,"itemList":314},"main","/basics","medium/content/bookmark",{"label":5,"navigation":442,"to":446,"icon":318,"itemList":6},"/api-reference",{"label":448,"navigation":442,"to":449,"icon":450,"itemList":451},"Release notes","/release-notes","medium/content/megaphone",[],{"label":453,"navigation":442,"to":454,"icon":455,"itemList":456},"Deprecations","/deprecations","medium/content/shredded",[],{"label":439,"navigation":442,"to":458,"icon":459,"itemList":355},"/examples","code",{"navigation":362},{"_path":402,"_dir":462,"_draft":463,"_partial":463,"_locale":464,"title":401,"description":465,"img":466,"background":467,"navigation":362,"body":468,"_type":724,"_id":725,"_source":726,"_file":727,"_extension":728},"routes",false,"","Plot a route where that takes into account operator preferences or exclusions","/examples/routes/preferred-operator.png","accent",{"type":469,"children":470,"toc":721},"root",[471,490],{"type":472,"tag":473,"props":474,"children":477},"element","ct-section",{"className":475},[476],"!pt-6",[478],{"type":472,"tag":479,"props":480,"children":489},"ct-iframe-wrapper",{"className":481,"src":488},[482,483,484,485,486,487],"w-full","h-[640px]","relative","overflow-hidden","rounded-lg","shadow-sm","https://examples.chargetrip.com/preferred-operator/",[],{"type":472,"tag":491,"props":492,"children":493},"ct-grid-section",{},[494,708],{"type":472,"tag":495,"props":496,"children":499},"ct-content",{"className":497},[498],"col-span-6",[500,508,514,527,534,577,583,697,703],{"type":472,"tag":501,"props":502,"children":504},"h1",{"id":503},"mutate-to-use-preferred-operators-while-routing",[505],{"type":506,"value":507},"text","Mutate to use preferred operators while routing",{"type":472,"tag":509,"props":510,"children":511},"p",{},[512],{"type":506,"value":513},"Operators are different. Think about payment methods, locations, charger experience. To take care of this, operators can be ranked and excluded. Either in the dashboard or in the API. In this example, the API approach will be demonstrated.",{"type":472,"tag":515,"props":516,"children":521},"ct-button",{":is-rounded":517,"href":518,"icon-right":519,"type":520},"true","https://github.com/chargetrip/examples/tree/main/examples/3.routes/5.preferred-operator","IconName.MD_NAVIGATION_ARROW_UP_RIGHT","primary",[522],{"type":472,"tag":509,"props":523,"children":524},{},[525],{"type":506,"value":526},"View on Github",{"type":472,"tag":528,"props":529,"children":531},"h2",{"id":530},"requirements",[532],{"type":506,"value":533},"Requirements",{"type":472,"tag":535,"props":536,"children":537},"ul",{},[538,553,565],{"type":472,"tag":539,"props":540,"children":541},"li",{},[542,551],{"type":472,"tag":543,"props":544,"children":548},"a",{"href":545,"rel":546},"https://account.chargetrip.com",[547],"nofollow",[549],{"type":506,"value":550},"Chargetrip API key",{"type":506,"value":552}," - to plot routes outside this region",{"type":472,"tag":539,"props":554,"children":555},{},[556,563],{"type":472,"tag":543,"props":557,"children":560},{"href":558,"rel":559},"https://www.mapbox.com",[547],[561],{"type":506,"value":562},"Mapbox API key",{"type":506,"value":564}," - to display the map",{"type":472,"tag":539,"props":566,"children":567},{},[568,575],{"type":472,"tag":543,"props":569,"children":572},{"href":570,"rel":571},"https://formidable.com/open-source/urql/",[547],[573],{"type":506,"value":574},"URQL",{"type":506,"value":576}," - a lightweight graphQL client",{"type":472,"tag":528,"props":578,"children":580},{"id":579},"steps-to-take",[581],{"type":506,"value":582},"Steps to take",{"type":472,"tag":584,"props":585,"children":586},"ol",{},[587,640,660],{"type":472,"tag":539,"props":588,"children":589},{},[590,592,598,600,606,608,614,616,622,624,630,632,638],{"type":506,"value":591},"Plotting a route with preferred operators starts by executing the ",{"type":472,"tag":459,"props":593,"children":595},{"className":594},[],[596],{"type":506,"value":597},"newRoute",{"type":506,"value":599}," mutation. This mutation requires information about the car, origin and destination. To use preferred operators the ",{"type":472,"tag":459,"props":601,"children":603},{"className":602},[],[604],{"type":506,"value":605},"operators",{"type":506,"value":607}," argument needs to be configured. The ",{"type":472,"tag":459,"props":609,"children":611},{"className":610},[],[612],{"type":506,"value":613},"type",{"type":506,"value":615}," needs to be set as well as the ",{"type":472,"tag":459,"props":617,"children":619},{"className":618},[],[620],{"type":506,"value":621},"ranking",{"type":506,"value":623}," or ",{"type":472,"tag":459,"props":625,"children":627},{"className":626},[],[628],{"type":506,"value":629},"excluding",{"type":506,"value":631},". After the mutation is finished executing a route ",{"type":472,"tag":459,"props":633,"children":635},{"className":634},[],[636],{"type":506,"value":637},"id",{"type":506,"value":639}," will be returned.",{"type":472,"tag":539,"props":641,"children":642},{},[643,645,650,652,658],{"type":506,"value":644},"This ",{"type":472,"tag":459,"props":646,"children":648},{"className":647},[],[649],{"type":506,"value":637},{"type":506,"value":651}," can be used to request route updates through the ",{"type":472,"tag":459,"props":653,"children":655},{"className":654},[],[656],{"type":506,"value":657},"routeUpdatedById",{"type":506,"value":659}," subscription. This subscription receives dynamic updates.",{"type":472,"tag":539,"props":661,"children":662},{},[663,665,671,673,679,681,687,689,695],{"type":506,"value":664},"After the subscription returns ",{"type":472,"tag":459,"props":666,"children":668},{"className":667},[],[669],{"type":506,"value":670},"done",{"type":506,"value":672}," as status, a route with preferred operators will be returned. If there are no operator preferred stations available it will fallback on stations from other operators. If all stations on a segment are ",{"type":472,"tag":459,"props":674,"children":676},{"className":675},[],[677],{"type":506,"value":678},"excluded",{"type":506,"value":680}," a route can fail to compute. The ",{"type":472,"tag":459,"props":682,"children":684},{"className":683},[],[685],{"type":506,"value":686},"polyline",{"type":506,"value":688}," and ",{"type":472,"tag":459,"props":690,"children":692},{"className":691},[],[693],{"type":506,"value":694},"legs",{"type":506,"value":696}," object can be used to display the route and charge stations on the map. Additional data such as distance, duration and consumption are also available.",{"type":472,"tag":528,"props":698,"children":700},{"id":699},"next-steps",[701],{"type":506,"value":702},"Next steps",{"type":472,"tag":509,"props":704,"children":705},{},[706],{"type":506,"value":707},"To take routes a step further, elevation plots and dynamic variables will be introduced. Let's head over to that.",{"type":472,"tag":709,"props":710,"children":712},"div",{"className":711},[498],[713],{"type":472,"tag":714,"props":715,"children":720},"ct-code-tabs",{":codeList":716,":is-inversed":517,"className":717},"[{\"label\":\"client.js\",\"code\":\"import { createClient, createRequest, defaultExchanges, subscriptionExchange } from '@urql/core';\\nimport { pipe, subscribe } from 'wonka';\\nimport { SubscriptionClient } from 'subscriptions-transport-ws';\\nimport { searchOperatorListQuery, createRouteQuery, routeUpdateSubscription } from './queries.js';\\n\\n/**\\n * For the purpose of this example we use urql - lightweights GraphQL client.\\n * To establish a connection with Chargetrip GraphQL API you need to have an API key.\\n * The key in this example is a public one and gives an access only to a part of our extensive database.\\n * You need a registered `x-client-id` to access the full database.\\n * Read more about an authorisation in our documentation (https://docs.chargetrip.com/#authorisation).\\n */\\nconst headers = {\\n  //Replace this x-client-id and app-id with your own to get access to more cars\\n  'x-client-id': '5ed1175bad06853b3aa1e492',\\n  'x-app-id': '623998b2c35130073829b2d2',\\n};\\n\\nconst subscriptionClient = new SubscriptionClient('wss://api.chargetrip.io/graphql', {\\n  reconnect: true,\\n  connectionParams: headers,\\n});\\n\\nconst client = createClient({\\n  url: 'https://api.chargetrip.io/graphql',\\n  fetchOptions: {\\n    method: 'POST',\\n    headers,\\n  },\\n  exchanges: [\\n    ...defaultExchanges,\\n    subscriptionExchange({\\n      forwardSubscription(operation) {\\n        return subscriptionClient.request(operation);\\n      },\\n    }),\\n  ],\\n});\\n\\n/**\\n * Searches through our operator list with pagination and various arguments.\\n * @param { Object } - Object that manages the page, size and search to be send towards our request\\n * @param { number } page - Number of the page we are on\\n * @param { number } size - Number of operators that we should fetch in one request\\n * @param { string } search - The keywords that we should filter our operator list on\\n * @param { function } callback - As soon as our asynchronous call is finished we do a callback to update our UI.\\n */\\nexport const fetchOperatorList = ({ page, size = 10, search = '', countries = [] }, callback) => {\\n  client\\n    .query(searchOperatorListQuery, { page, size, search, countries })\\n    .toPromise()\\n    .then(response => {\\n      callback(response.data.operatorList);\\n    });\\n};\\n/**\\n * Creates a route based on operator preference\\n * @param { Object } - Object that manages the operator preference\\n * @param { string } type - The type of operator preference. Can be either none, preferred or required.\\n * @param { string } [level1] - The first level of operator preference. The higher the more preferred an operator is.\\n * @param { string } [level2] - The second level of operator preference.\\n * @param { string } [level3] - The third level of operator preference.\\n * @param { string } [excluded] - The excluded level of operator preference. These operators won't be used when calculating the route.\\n */\\nexport const createRoute = ({ type = 'none', level1 = [], level2 = [], level3 = [], exclude = [] }, callback) => {\\n  client\\n    .mutation(createRouteQuery, { type, level1, level2, level3, exclude })\\n    .toPromise()\\n    .then(response => {\\n      const routeId = response.data.newRoute;\\n      if (!routeId) return Promise.reject('Could not retrieve Route ID. The response is not valid.');\\n\\n      const { unsubscribe } = pipe(\\n        client.executeSubscription(createRequest(routeUpdateSubscription, { id: routeId })),\\n        subscribe(result => {\\n          const { status, route } = result.data.routeUpdatedById;\\n\\n          if (status === 'done' && route) {\\n            unsubscribe();\\n            callback(route);\\n          } else if (status === 'not_found') {\\n            callback();\\n          }\\n        }),\\n      );\\n    })\\n    .catch(error => console.log(error));\\n};\\n\"},{\"label\":\"index.js\",\"code\":\"import { createRoute, fetchOperatorList } from './client';\\nimport { attachEventListeners, parseRouteResponse, renderOperators } from './interface';\\n\\n/**\\n * This project shows you how to fetch a car list and render the car details\\n * The project structure contains;\\n *\\n *    - client.js - All networking requests\\n *    - interface.js - All interface rendering\\n *    - map.js - All map rendering (including routes and waypoints)\\n *    - queries.js - The GraphQL queries used in the networking requests\\n */\\n\\nconst loadingToast = document.getElementById('loading-toast');\\nconst recalculateButton = document.getElementById('recalculate');\\n\\nloadingToast.style.transform = `translateY(0)`;\\nrecalculateButton.disabled = true;\\n\\ncreateRoute({}, route => {\\n  parseRouteResponse(route);\\n});\\n\\nfetchOperatorList({ page: 0 }, renderOperators);\\nattachEventListeners();\\n\"},{\"label\":\"interface.js\",\"code\":\"import { debounce } from '../../../utils';\\nimport { createRoute, fetchOperatorList } from './client';\\nimport { drawRoutePolyline } from './map';\\n\\n// Keeps track of priority levels\\nlet priorities = new Map([]);\\n\\n// Keeps track of the current selected operator\\nlet selectedOperator;\\n\\n// Keeps track of the active search keyword. This way we always fetch the right results when using pagination.\\nlet searchKeyword = '';\\n\\n// Keeps track of the filters and refetches the list\\nlet countryFilters = [];\\n\\n// Keeps track of which page of cars we are currently on.\\nlet currentPage = 0;\\n\\nconst loadingToast = document.getElementById('loading-toast');\\n\\n/**\\n * A small helper function that renders the UI for every operator coming from the Chargetrip API.\\n * @param { Object } operators - All operators that we fetched from the Chargetrip API\\n */\\nexport const renderOperators = operators => {\\n  operators.forEach(operator => {\\n    // Check if our operator ID has been assigned a different priority level than no priority.\\n    // If so we need to render a different UI.\\n    // This is required for when you start searching and go back to the full overview.\\n    const priority = priorities.has(operator.id) ? priorities.get(operator.id) : null;\\n\\n    document.getElementById('operator-list').insertAdjacentHTML(\\n      'beforeend',\\n      `\u003Cli data-id=${operator.id} class=\\\"priority-list-element\\\">\\n            \u003Cdiv class=\\\"priority-list-icon ${priority ? priority.color : ''}\\\">\\n                \u003Cimg \\n                    alt=\\\"${priority ? priority.label : 'No priority'} icon\\\" \\n                    src=\\\"images/${priority ? priority.icon : 'light-no-priority'}.svg\\\" \\n                />\\n            \u003C/div>\\n            \u003Cdiv class=\\\"priority-list-data\\\">\\n                \u003Cp>\u003Cstrong>${operator.name}\u003C/strong>\u003C/p>\\n                \u003Cp class=\\\"priority-label\\\">${priority ? priority.label : 'No priority'}\u003C/p>\\n            \u003C/div>\\n            \u003Cdiv class=\\\"priority-menu-action\\\">\\n                \u003Cimg src=\\\"images/open-menu.svg\\\" />\\n            \u003C/div>\\n        \u003C/li>`,\\n    );\\n  });\\n\\n  // We are using pagination by using an intersection observer.\\n  // If we get a new set of data we validate whether our observer is still required.\\n  handleObserving(operators);\\n};\\n\\n/**\\n * Small helper function that assigns all event listeners to the UI\\n */\\nexport const attachEventListeners = () => {\\n  attachMenuEventListener();\\n  attachMenuItemEventListeners();\\n  attachButtonEventListeners();\\n  attachTagEventListeners();\\n};\\n\\n/**\\n * Event listener which registers a trigger for the priority menu.\\n * We assign the event listener on the body so you can click anywhere outside the menu to dismiss.\\n */\\nconst attachMenuEventListener = () => {\\n  document.body.addEventListener('click', didToggleMenu, false);\\n};\\n\\n/**\\n * Event listener that handles the click on any of the items inside the priority menu\\n */\\nconst attachMenuItemEventListeners = () => {\\n  [...document.querySelectorAll('.priority-action')].forEach((action, index) => {\\n    action.addEventListener('click', () => {\\n      closeMenu();\\n      setPriority(index);\\n    });\\n  });\\n};\\n\\n/**\\n * Event listener on the recalculate button.\\n * This way you can first set your priorities and after that we recalculate the route.\\n * This prevents unnecessary calls to our API.\\n */\\nconst attachButtonEventListeners = () => {\\n  document.getElementById('recalculate').addEventListener('click', recalculateRoute, false);\\n};\\n\\n/**\\n * Event listener to handle clicks on country tags\\n * By clicking a country we refresh the list and only get operators from that country\\n */\\nconst attachTagEventListeners = () => {\\n  [...document.querySelectorAll('.country-tag')].forEach(tag => {\\n    tag.addEventListener('click', didToggleTag, false);\\n  });\\n};\\n\\n/**\\n * a\\n * @param { Event } event - the click event\\n */\\nconst didToggleTag = event => {\\n  const countryCode = event.target.dataset.countryCode;\\n  const countryIdx = countryFilters.indexOf(countryCode);\\n\\n  event.target.classList.toggle('active');\\n\\n  if (countryIdx > -1) {\\n    countryFilters.splice(countryIdx, 1);\\n  } else {\\n    countryFilters.push(countryCode);\\n  }\\n\\n  // Resets our current page param to 0 so we don't miss any filter results\\n  currentPage = 0;\\n\\n  // Empties our current operator list so we can replace it with the filter results\\n  document.getElementById('operator-list').textContent = '';\\n\\n  fetchOperatorList({ page: currentPage, size: 10, search: searchKeyword, countries: countryFilters }, renderOperators);\\n};\\n\\n/**\\n * Function that toggles the menu from open to close and vice-versa\\n * @param { Event } event - The click event.\\n */\\nconst didToggleMenu = event => {\\n  const menu = document.getElementById('priority-menu');\\n  // When clicking the button we traverse up the dom to get to the actual button.\\n  const menuButton = event.target.parentNode;\\n\\n  // Check if we click the menu button and if the menu is already open.\\n  // If the menu is already open we close it, otherwise open the menu.\\n  // If we click anywhere else and our menu is open, we close it.\\n  if (menuButton.classList.contains('priority-menu-action') && !menu.classList.contains('active')) {\\n    openMenu(menuButton);\\n    return;\\n  } else if (menu.classList.contains('active')) {\\n    closeMenu();\\n    return;\\n  }\\n};\\n\\n/**\\n * Opens and positions the priority menu\\n * @param { Element } menuButton - the menu button that has been clicked\\n */\\nconst openMenu = menuButton => {\\n  const menu = document.getElementById('priority-menu');\\n\\n  // Set the menu on the correct offset and open it\\n  // We use the scroll area to compute the offset of the item that was clicked\\n  menu.classList.add('active');\\n  menu.style.top = `${menuButton.offsetTop}px`;\\n  menu.style.left = `${menuButton.offsetLeft - menu.clientWidth}px`;\\n\\n  // Keep the button that was clicked in view, so the user has a visual queue to close the menu.\\n  menuButton.classList.add('active');\\n\\n  // Get the operator element that was clicked and assign that to the current selected operator\\n  selectedOperator = menuButton.parentNode;\\n};\\n\\n/**\\n * Closes the priority menu\\n */\\nconst closeMenu = () => {\\n  const menu = document.getElementById('priority-menu');\\n  const menuAction = document.querySelector('.priority-menu-action.active');\\n\\n  menuAction.classList.remove('active');\\n  menu.classList.remove('active');\\n};\\n\\n/**\\n * Set the priority of the operator that was clicked to any of the items that was clicked inside the menu\\n * @param { number } index - The index of the item that was clicked inside the menu\\n */\\nconst setPriority = index => {\\n  switch (index) {\\n    case 0:\\n      // Unset the priority\\n      priorities.delete(selectedOperator.dataset.id);\\n      break;\\n    case 1:\\n      // Set the priority to high\\n      priorities.set(selectedOperator.dataset.id, {\\n        priority: 'high',\\n        color: 'priority',\\n        icon: 'light-high-priority',\\n        label: 'High priority',\\n      });\\n      break;\\n    case 2:\\n      // Set the priority to medium\\n      priorities.set(selectedOperator.dataset.id, {\\n        priority: 'medium',\\n        color: 'priority',\\n        icon: 'light-medium-priority',\\n        label: 'Medium priority',\\n      });\\n      break;\\n    case 3:\\n      // Set the priority to low\\n      priorities.set(selectedOperator.dataset.id, {\\n        priority: 'low',\\n        color: 'priority',\\n        icon: 'light-low-priority',\\n        label: 'Low priority',\\n      });\\n      break;\\n    default:\\n      // Set the priority to excluded\\n      priorities.set(selectedOperator.dataset.id, {\\n        priority: 'excluded',\\n        color: 'excluded',\\n        icon: 'light-exclude-priority',\\n        label: 'Excluded priority',\\n      });\\n      break;\\n  }\\n\\n  // When we changed the priority we let the UI reflect it by calling this function\\n  setPriorityStyling();\\n};\\n\\n/**\\n * Sets the correct styling based on the priority that was selected inside the priority menu.\\n */\\nconst setPriorityStyling = () => {\\n  const priority = priorities.get(selectedOperator.dataset.id);\\n\\n  /* eslint-disable */\\n  selectedOperator.querySelector('.priority-list-icon').className = `priority-list-icon ${\\n    priority ? priority.color : ''\\n  }`;\\n  selectedOperator.querySelector('.priority-list-icon img').src = `images/${\\n    priority ? priority.icon : 'light-no-priority'\\n  }.svg`;\\n  selectedOperator.querySelector('.priority-label').innerHTML = `${priority ? priority.label : 'No priority'}`;\\n  /* eslint-enable */\\n};\\n\\n/**\\n * This recalculates the route based upon the new operator selection.\\n * It extracts the priorities that were set in the list and formats them to how our API is expecting the data\\n * If there are no priorities it just calculates a regular route.\\n */\\nconst recalculateRoute = event => {\\n  event.target.disabled = true;\\n  loadingToast.style.transform = `translateY(0)`;\\n\\n  if (priorities.size > 0) {\\n    const level1 = [];\\n    const level2 = [];\\n    const level3 = [];\\n    const exclude = [];\\n\\n    // eslint-disable-next-line no-unused-vars\\n    for (const [id, { priority }] of priorities.entries()) {\\n      switch (priority) {\\n        case 'high':\\n          level1.push(id);\\n          break;\\n        case 'medium':\\n          level2.push(id);\\n          break;\\n        case 'low':\\n          level3.push(id);\\n          break;\\n        case 'excluded':\\n          exclude.push(id);\\n          break;\\n        default:\\n          break;\\n      }\\n    }\\n\\n    /**\\n     * So by default our operator preference is set to none.\\n     * Whenever you add a preferred operator you will have to tell our API how you would like to use them; preferred or required.\\n     * Preferred will prefer the operator ranking when calculating routes\\n     * Required will require the operator ranking when calculating routes, excluded operators will be ignored\\n     *\\n     * Our example only uses level 1 to 3. Our API has 10 levels available for if you want to be more specific.\\n     * Using a lower level (such as level 7) for the lowest priority makes it less likely for the operator to be used.\\n     *\\n     * NOTE: If you try to calculate a route with preferred operators while your type is set to none, you will get no route back.\\n     * NOTE 2: If you calculate a route with only excluded, set your type to 'none'. Otherwise no route will be returned.\\n     *\\n     * More information can be found in our documentation; https://docs.chargetrip.com/API-Reference/Routes/mutate-route#mutation\\n     */\\n    createRoute(\\n      {\\n        type: level1.length > 0 || level2.length > 0 || level3.length > 0 ? 'preferred' : 'none',\\n        level1: level1,\\n        level2: level2,\\n        level3: level3,\\n        exclude: exclude,\\n      },\\n      route => parseRouteResponse(route),\\n    );\\n  } else {\\n    createRoute({}, route => parseRouteResponse(route));\\n  }\\n};\\n\\nexport const parseRouteResponse = route => {\\n  if (route) {\\n    drawRoutePolyline(route);\\n  } else {\\n    renderErrorToast();\\n  }\\n\\n  document.getElementById('recalculate').disabled = false;\\n  loadingToast.style.transform = `translateY(100%)`;\\n};\\n\\nexport const renderErrorToast = () => {\\n  const errorToast = document.getElementById('error-toast');\\n  errorToast.style.transform = `translateY(0)`;\\n\\n  setTimeout(() => {\\n    errorToast.style.transform = `translateY(100%)`;\\n  }, 3500);\\n};\\n\\n/**\\n * Intersection observer that checks if we have more pages or that we reached the end.\\n * If the end is reached we disconnect the intersection observer.\\n * @param { Array\u003CObject> } operators - Set of operators that is being returned from the Chargetrip API\\n */\\nconst handleObserving = operators => {\\n  let targets = [...document.querySelectorAll('.priority-list-element')];\\n  let offset = 3;\\n\\n  // Unobserve when there are less than 10 results or we reach the end of the list\\n  if (operators.length \u003C 10) {\\n    observer.disconnect();\\n  } else {\\n    observer.observe(targets[targets.length - offset]);\\n  }\\n};\\n\\n/**\\n * The callback of the intersection observer that fetches the new data for us when we reach the end\\n * @param { Element } entries - An array of elements that are being observed by our observer\\n */\\nconst loadNextPage = entries => {\\n  entries.forEach(entry => {\\n    if (entry.isIntersecting) {\\n      currentPage += 1;\\n\\n      fetchOperatorList({ page: currentPage, size: 10, search: searchKeyword }, renderOperators);\\n    }\\n  });\\n};\\n\\n// Initialize a new intersection observer with the following options\\nconst options = {\\n  root: document.getElementById('scroll-area'),\\n  rootMargin: '0px',\\n  threshold: 1.0,\\n};\\n\\n// Intersection observer that handles pagination on the operator list\\nconst observer = new IntersectionObserver(loadNextPage, options);\\n\\n/**\\n * Search\\n * The following code takes care of searching for operators\\n *\\n * 1. Attaches an event listener to our search inputfield\\n * 2. Adds a debounce handler so we don't create too much API calls and view refreshes when the users searches\\n * 3. Executes our search request with the page set to 0, size set to 10 and the new search keyword.\\n */\\ndocument.getElementById('search-area').addEventListener(\\n  'input',\\n  debounce(e => {\\n    // Updates our searchKeyword to reflect our inputfield\\n    searchKeyword = e.target.value;\\n\\n    // Resets our current page param to 0 so we don't miss any search results\\n    currentPage = 0;\\n\\n    // Empties our current car-list so we can replace it with the search results\\n    document.getElementById('operator-list').textContent = '';\\n\\n    fetchOperatorList(\\n      { page: currentPage, size: 10, search: searchKeyword, countries: countryFilters },\\n      renderOperators,\\n    );\\n  }, 250),\\n);\\n\"},{\"label\":\"map.js\",\"code\":\"import mapboxgl from 'mapbox-gl';\\nimport * as mapboxPolyline from '@mapbox/polyline';\\nimport { getDurationString } from '../../../utils';\\n\\n/**\\n * More information on how a route can be drawn can be found in our route example.\\n * Route example: https://examples.chargetrip.com/route\\n */\\n\\nlet popups = [];\\n\\nmapboxgl.accessToken = 'pk.eyJ1IjoiY2hhcmdldHJpcCIsImEiOiJjazhpaG8ydTIwNWNpM21ud29xeXc2amhlIn0.rGKgR3JfG9Z5dCWjUI_oGA';\\n\\nconst map = new mapboxgl.Map({\\n  cooperativeGestures: true,\\n  container: 'map',\\n  style: 'mapbox://styles/chargetrip/ckgcbf3kz0h8819qki8uwhe0k',\\n  zoom: 6,\\n  center: [9.1320104, 54.9758916],\\n});\\n\\nexport const drawRoutePolyline = data => {\\n  const decodedData = mapboxPolyline.decode(data.polyline);\\n  const reversed = decodedData.map(item => item.reverse());\\n\\n  drawRoute(reversed, data.legs, data.duration);\\n};\\n\\nexport const drawRoute = (coordinates, legs, duration) => {\\n  if (map.loaded()) {\\n    drawPolyline(coordinates);\\n    drawPopUps(legs, duration);\\n    showLegs(legs);\\n  } else {\\n    map.on('load', () => {\\n      drawPolyline(coordinates);\\n      drawPopUps(legs, duration);\\n      showLegs(legs);\\n    });\\n  }\\n};\\n\\nconst drawPopUps = (legs, duration) => {\\n  popups.forEach(popup => {\\n    popup.remove();\\n  });\\n\\n  legs.forEach((leg, index) => {\\n    const popup = new mapboxgl.Popup({ closeOnClick: false })\\n      .setLngLat(leg.destination.geometry.coordinates)\\n      .setHTML(`\u003Csmall>${index == legs.length - 1 ? getDurationString(duration) : leg.name}\u003C/small>`)\\n      .addTo(map);\\n\\n    popups.push(popup);\\n  });\\n};\\n\\nconst drawPolyline = coordinates => {\\n  if (map.getLayer('polyline')) map.removeLayer('polyline');\\n  if (map.getSource('polyline-source')) map.removeSource('polyline-source');\\n\\n  const geojson = {\\n    type: 'FeatureCollection',\\n    features: [\\n      {\\n        type: 'Feature',\\n        geometry: {\\n          type: 'LineString',\\n          properties: {},\\n          coordinates,\\n        },\\n      },\\n    ],\\n  };\\n\\n  map.addSource('polyline-source', {\\n    type: 'geojson',\\n    lineMetrics: true,\\n    data: geojson,\\n  });\\n\\n  map.addLayer({\\n    id: 'polyline',\\n    type: 'line',\\n    options: 'beforeLayer',\\n    source: 'polyline-source',\\n    layout: {\\n      'line-join': 'round',\\n      'line-cap': 'round',\\n    },\\n    paint: {\\n      'line-color': '#0078FF',\\n      'line-width': 3,\\n    },\\n  });\\n};\\n\\nconst showLegs = legs => {\\n  if (map.getLayer('legs')) map.removeLayer('legs');\\n  if (map.getSource('legs')) map.removeSource('legs');\\n  if (legs.length === 0) return;\\n\\n  let points = [];\\n\\n  points.push({\\n    type: 'Feature',\\n    properties: {\\n      icon: 'location_big',\\n    },\\n    geometry: legs[0].origin?.geometry,\\n  });\\n\\n  legs.map((leg, index) => {\\n    if (index !== legs.length - 1) {\\n      points.push({\\n        type: 'Feature',\\n        properties: {\\n          description: `${getDurationString(leg.chargeTime)}`,\\n          icon: 'unknown-turbo',\\n        },\\n        geometry: leg.destination?.geometry,\\n      });\\n    } else {\\n      points.push({\\n        type: 'Feature',\\n        properties: {\\n          icon: 'arrival',\\n        },\\n        geometry: leg.destination?.geometry,\\n      });\\n    }\\n  });\\n\\n  map.addLayer({\\n    id: 'legs',\\n    type: 'symbol',\\n    layout: {\\n      'icon-image': '{icon}',\\n      'icon-allow-overlap': true,\\n      'icon-offset': ['case', ['==', ['get', 'icon'], 'location_big'], ['literal', [0, 0]], ['literal', [0, -15]]],\\n    },\\n    source: {\\n      type: 'geojson',\\n      data: {\\n        type: 'FeatureCollection',\\n        features: points,\\n      },\\n    },\\n  });\\n};\\n\"},{\"label\":\"queries.js\",\"code\":\"import qql from 'graphql-tag';\\n\\n/*\\n * In this example we request a route from Hanover, Germany to Nørresundby, Denmark\\n * Your origin and destination are required fields. You also need to select an EV.\\n * Only the EV ID here is mandatory, all other fields are optional and when not specified will use the default values.\\n * The changing conditions are:\\n *   - full battery at Amsterdam, Netherlands\\n *   - EV can charge at CHAdeMO changers\\n *   - should use climate (temperature and weather conditions)\\n *   - min power of chargers is 43 kWh. This is the default setting\\n *   - one passenger in the car (drive alone)\\n *   - optionally a preferred operator selection which is used to compute a route aligned with the operator ranking\\n */\\nexport const createRouteQuery = qql`\\nmutation newRoute($type: RouteOperatorsType, $level1: [ID], $level2: [ID], $level3: [ID], $exclude: [ID]) {\\n    newRoute(\\n      input: {\\n        ev: {\\n          id: \\\"5d161be5c9eef46132d9d20a\\\"\\n          plugs: { chargingPower: 150, standard: TESLA_S }\\n          adapters: [\\n            { chargingPower: 150, standard: IEC_62196_T2_COMBO }\\n            { chargingPower: 150, standard: CHADEMO }\\n          ]\\n          climate: true\\n          numberOfPassengers: 1\\n        }\\n        routeRequest: {\\n          operators:{ \\n            type: $type \\n            ranking: { \\n              level1: $level1\\n              level2: $level2\\n              level3: $level3\\n            }\\n            exclude: $exclude\\n          }\\n          origin: {\\n            type: Feature\\n            geometry: { type: Point, coordinates: [9.732625731357011, 52.3806314590276] }\\n            properties: { name: \\\"Hanover, Germany\\\" }\\n\\n          }\\n          destination: {\\n            type: Feature\\n            geometry: { type: Point, coordinates: [9.922192327081783, 57.046057998779176] }\\n            properties: { name: \\\"Aalborg, Denmark\\\" }\\n          }\\n        }\\n      }\\n    )\\n  }\\n`;\\n\\nexport const routeUpdateSubscription = qql`\\nsubscription routeUpdatedById($id: ID!){\\n  routeUpdatedById(id: $id) {\\n    status\\n    route {\\n      duration\\n      polyline\\n      legs{\\n        name\\n        origin{\\n          geometry{\\n            type\\n            coordinates\\n          }\\n          properties\\n        }\\n        destination{\\n          geometry\\n          {\\n            type\\n            coordinates\\n          }\\n          properties\\n        }\\n      }\\n    }\\n  }\\n}\\n`;\\n\\nexport const searchOperatorListQuery = qql`\\nquery operatorList($page: Int, $size: Int, $search: String, $countries: [CountryCodeAlpha2!]) {\\n    operatorList(\\n        page: $page, \\n        size: $size,\\n        search: $search,\\n        filter: {\\n          countries: $countries\\n        }\\n    ) {\\n      id\\n      name\\n    }\\n}\\n`;\\n\"}]",[718,719],"stick","top-6",[],{"title":464,"searchDepth":722,"depth":722,"links":723},2,[],"markdown","content:5.examples:3.routes:5.preferred-operator.md","content","5.examples/3.routes/5.preferred-operator.md","md",1775054263153]