UNPKG

@any-routing/core

Version:

This library was generated with [Nx](https://nx.dev).

235 lines 9.84 kB
import { __awaiter } from "tslib"; import { Dispatcher } from './utils/dispatcher'; import { randomId } from './utils/random'; import { InternalWaypointC, } from './libre-routing.model'; import { featureCollection } from '@turf/helpers'; export class AnyRouting { get options() { return this._options; } get data() { return this._state.data; } get state() { return this._state; } get dataProvider() { return this.options.dataProvider; } get selectedRouteId() { return this._state.selectedRouteId; } get waypoints() { return this._state.waypoints; } constructor(options) { var _a; this.dispatcher = new Dispatcher(); this._plugins = []; this._initialState = { waypoints: [], data: undefined, loading: false, selectedRouteId: undefined, mode: 'default', routesShapeGeojson: undefined, }; this._state = Object.assign({}, this._initialState); this._options = Object.assign({ uniqueKey: randomId() }, options); this._plugins = (_a = options.plugins) !== null && _a !== void 0 ? _a : []; if (this.options.waypointsSyncStrategy === 'geocodeFirst' && !this.options.geocoder) { throw new Error('Geocoder is required when waypointsSyncStrategy is `geocodeFirst`'); } this.geocoder = this.options.geocoder && typeof this.options.geocoder === 'function' ? { geocode: this.options.geocoder } : this.options.geocoder; } initialize() { this.initPlugins(); } onRemove() { var _a; this.detachPlugins(); (_a = this.options.dataProvider) === null || _a === void 0 ? void 0 : _a.destroy(); } setMode(mode) { this._patchState({ mode }); } setWaypoints(waypoints) { const internalWaypoints = this.transformToInternalWaypoints(waypoints); this._patchState({ waypoints: internalWaypoints }); } getWaypoint(waypointId) { return this._state.waypoints[waypointId]; } recalculateRoute(opts = {}) { var _a; return __awaiter(this, void 0, void 0, function* () { if (this.waypoints.length < 2) return; if (!this.options.dataProvider) { throw new Error('No data provider'); } if (opts.dropPendingRequests) { yield this.options.dataProvider.abortAllRequests(); } let patchState = {}; if (!this._state.loading) { patchState = Object.assign(Object.assign({}, patchState), { loading: true }); } this.fire('calculationStarted', { mode: this.state.mode, waypoints: this.waypoints, recalculateOptions: opts, }); this._patchState(patchState); if ('loading' in patchState) { this.fire('loadingChanged', { loading: true }); } try { let patchState = {}; if (opts.syncWaypoints !== false && this.options.waypointsSyncStrategy === 'geocodeFirst') { const waypointsToSyncIds = this._state.waypoints.reduce((acc, w, index) => { if (!w.geocoded) { acc.push(index); } return acc; }, []); if (waypointsToSyncIds.length > 0) { const waypoints = yield this.geocodeWaypoints(this._state.waypoints); this._patchState({ waypoints }); waypointsToSyncIds.forEach((waypointId) => { this.fire('waypointGeocoded', { waypoint: waypoints[waypointId] }); }); } } const data = (yield this.options.dataProvider.request(this._state.waypoints, { mode: this.state.mode, })); patchState = Object.assign(Object.assign({}, patchState), { data, selectedRouteId: data.selectedRouteId, routesShapeGeojson: data.routesShapeGeojson }); if (opts.syncWaypoints !== false && this.options.waypointsSyncStrategy === 'toPath') { const syncedWaypoints = this.syncWaypointsPositions(data.routes[0].waypoints); patchState = Object.assign(Object.assign({}, patchState), { waypoints: syncedWaypoints }); } this._patchState(patchState); this.fire('routesFound', { mode: this.state.mode, waypoints: this._state.waypoints, data, recalculateOptions: opts, }); return this._state.data; } catch (e) { this.fire('calculationError', { error: e, recalculateOptions: opts }); throw e; } finally { if (this._state.loading && (((_a = this.data) === null || _a === void 0 ? void 0 : _a.latest) || !(yield this.dataProvider.hasPendingRequests()))) { this._patchState({ loading: false }); this.fire('loadingChanged', { loading: false }); } } }); } on(event, callback) { this.dispatcher.on(event, callback); } off(event, callback) { this.dispatcher.off(event, callback); } selectRoute(routeId) { if (!this.data) { return; } const features = this.data.routesShapeGeojson.features.map((feature) => { return Object.assign(Object.assign({}, feature), { properties: Object.assign(Object.assign({}, feature.properties), { selected: feature.properties.routeId === routeId }) }); }); this._patchState({ selectedRouteId: routeId, data: Object.assign(Object.assign({}, this._state.data), { routesShapeGeojson: featureCollection(features), selectedRouteId: routeId }), routesShapeGeojson: featureCollection(features), }); this.fire('routeSelected', { route: this.data.routes[routeId], routeId: routeId, }); } reset() { this._setState(Object.assign({}, this._initialState), 'external'); } getUniqueName(name) { return `${name}-${this.options.uniqueKey}`; } syncWaypointsPositions(waypoints) { const newWaypoints = waypoints.map((waypoint, index) => (Object.assign(Object.assign({}, this._state.waypoints[index]), { position: waypoint, originalPosition: this._state.waypoints[index].originalPosition || this._state.waypoints[index].position, properties: this._state.waypoints[index].properties }))); return newWaypoints; } setState({ waypoints, data, routesShapeGeojson, selectedRouteId, }) { let newState = Object.assign({}, this._state); if (waypoints) { const internalWaypoints = this.transformToInternalWaypoints(waypoints); newState = Object.assign(Object.assign({}, newState), { waypoints: internalWaypoints }); } if (routesShapeGeojson) { newState = Object.assign(Object.assign({}, newState), { routesShapeGeojson }); } if (data) { newState = Object.assign(Object.assign({}, newState), { data, routesShapeGeojson: data.routesShapeGeojson }); } if (selectedRouteId != null) { newState = Object.assign(Object.assign({}, newState), { selectedRouteId }); } if (data || waypoints || routesShapeGeojson || selectedRouteId != null) { this._setState(newState, 'external'); } } initPlugins() { this._plugins.forEach((plugin) => this.resolvePlugin(plugin).onAdd(this)); } detachPlugins() { this._plugins.forEach((plugin) => this.resolvePlugin(plugin).onRemove(this)); } resolvePlugin(plugin) { if (typeof plugin === 'function') { return new plugin({}); } return plugin; } _setState(newState, source = 'internal', updatedKeys) { this._state = newState; this.fire('stateUpdated', { source, updatedProperties: updatedKeys !== null && updatedKeys !== void 0 ? updatedKeys : Object.keys(this.state), }); } _patchState(patchState, source = 'internal') { if (Object.keys(patchState).length === 0) { return; } this._setState(Object.assign(Object.assign({}, this._state), patchState), source, Object.keys(patchState)); if ('waypoints' in patchState) { this.fire('waypointsChanged', { waypoints: this.state.waypoints }); } } transformToInternalWaypoints(waypoints) { return waypoints.map((waypoint, index) => InternalWaypointC.fromWaypoint(waypoint, { index, isFirst: index === 0, isLast: index === waypoints.length - 1 })); } fire(event, data) { //@ts-ignore this.dispatcher.fire(event, Object.assign(Object.assign({}, data), { state: this.state, eventName: event })); } geocodeWaypoints(waypoints) { const waypointGeocodes = waypoints.map((waypoint) => __awaiter(this, void 0, void 0, function* () { if (waypoint.geocoded) { return waypoint; } const geocodedWaypoint = yield this.geocoder.geocode(waypoint); geocodedWaypoint.geocoded = true; return geocodedWaypoint; })); return Promise.all(waypointGeocodes); } } //# sourceMappingURL=libre-routing.js.map