@any-routing/core
Version:
This library was generated with [Nx](https://nx.dev).
235 lines • 9.84 kB
JavaScript
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