@furystack/shades
Version:
Google Authentication Provider for FuryStack
118 lines • 6.16 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { Injectable } from '@furystack/inject';
import { deserializeQueryString as defaultDeserializeQueryString, serializeToQueryString as defaultSerializeToQueryString, } from '@furystack/rest';
import { ObservableValue } from '@furystack/utils';
let LocationService = class LocationService {
serializeToQueryString;
deserializeQueryString;
constructor(serializeToQueryString = defaultSerializeToQueryString, deserializeQueryString = defaultDeserializeQueryString) {
this.serializeToQueryString = serializeToQueryString;
this.deserializeQueryString = deserializeQueryString;
window.addEventListener('popstate', this.popStateListener);
window.addEventListener('hashchange', this.hashChangeListener);
this.onDeserializedLocationSearchChanged = new ObservableValue(this.deserializeQueryString(location.search));
this.originalPushState = window.history.pushState.bind(window.history);
window.history.pushState = ((...args) => {
this.originalPushState(...args);
this.updateState();
}).bind(this);
this.originalReplaceState = window.history.replaceState.bind(window.history);
window.history.replaceState = ((...args) => {
this.originalReplaceState(...args);
this.updateState();
}).bind(this);
}
originalPushState;
originalReplaceState;
[Symbol.dispose]() {
window.removeEventListener('popstate', this.popStateListener);
window.removeEventListener('hashchange', this.hashChangeListener);
this.onLocationPathChanged[Symbol.dispose]();
this.onLocationSearchChanged[Symbol.dispose]();
this.onDeserializedLocationSearchChanged[Symbol.dispose]();
this.locationDeserializerObserver[Symbol.dispose]();
window.history.pushState = this.originalPushState;
window.history.replaceState = this.originalReplaceState;
}
/**
* Observable value that will be updated when the location pathname (e.g. /page/1) changes
*/
onLocationPathChanged = new ObservableValue(new URL(location.href).pathname);
/**
* Observable value that will be updated when the location hash (e.g. #hash) changes
*/
onLocationHashChanged = new ObservableValue(location.hash.replace('#', ''));
/**
* Observable value that will be updated when the location search (e.g. ?search=1) changes
*/
onLocationSearchChanged = new ObservableValue(location.search);
onDeserializedLocationSearchChanged;
locationDeserializerObserver = this.onLocationSearchChanged.subscribe((search) => {
this.onDeserializedLocationSearchChanged.setValue(this.deserializeQueryString(search));
});
updateState = (() => {
this.onLocationPathChanged.setValue(location.pathname);
this.onLocationHashChanged.setValue(location.hash.replace('#', ''));
this.onLocationSearchChanged.setValue(location.search);
}).bind(this);
searchParamObservables = new Map();
/**
*
* @param key The search param key (e.g. ?search=1 -> search)
* @param defaultValue The default value if not provided
* @returns An observable with the current value (or default value) of the search param
*/
useSearchParam(key, defaultValue) {
const existing = this.searchParamObservables.get(key);
if (!existing) {
const currentDeserialized = this.onDeserializedLocationSearchChanged.getValue();
const actualValue = Object.prototype.hasOwnProperty.call(currentDeserialized, key)
? currentDeserialized[key]
: defaultValue;
const newObservable = new ObservableValue(actualValue);
this.searchParamObservables.set(key, newObservable);
newObservable.subscribe((value) => {
const currentQueryStringObject = this.onDeserializedLocationSearchChanged.getValue();
if (currentQueryStringObject[key] !== value) {
const params = this.serializeToQueryString({ ...currentQueryStringObject, [key]: value });
const newUrl = `${location.pathname}?${params}`;
history.pushState({}, '', newUrl);
}
});
this.onDeserializedLocationSearchChanged.subscribe((search) => {
const value = search[key] ?? defaultValue;
this.searchParamObservables.get(key)?.setValue(value);
});
return newObservable;
}
return existing;
}
popStateListener = (_ev) => {
this.updateState();
};
hashChangeListener = ((_ev) => {
this.updateState();
}).bind(this);
};
LocationService = __decorate([
Injectable({ lifetime: 'singleton' }),
__metadata("design:paramtypes", [Object, Object])
], LocationService);
export { LocationService };
export const useCustomSearchStateSerializer = (injector, serialize, deserialize) => {
if (injector.cachedSingletons.has(LocationService)) {
throw new Error('useCustomSearchStateSerializer must be called before the LocationService is instantiated');
}
const locationService = new LocationService(serialize, deserialize);
injector.setExplicitInstance(locationService, LocationService);
};
//# sourceMappingURL=location-service.js.map