Skip to content

Commit

Permalink
feat: fetchScript
Browse files Browse the repository at this point in the history
closes #171
  • Loading branch information
raveclassic committed Dec 12, 2019
1 parent 58faec4 commit 3dc8534
Show file tree
Hide file tree
Showing 5 changed files with 252 additions and 2 deletions.
2 changes: 1 addition & 1 deletion packages/utils/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
{
"extends": "../lint/.eslintrc"
"extends": "../lint/.eslintrc.json"
}
165 changes: 165 additions & 0 deletions packages/utils/src/dom/fetch-script.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
import { HKT, Kind, Kind2, Kind3, URIS, URIS2, URIS3 } from 'fp-ts/lib/HKT';
import {
MonadObservable,
MonadObservable1,
MonadObservable2,
MonadObservable2C,
MonadObservable3,
} from '../typeclasses/monad-observable/monad-observable';
import { MonadThrow, MonadThrow1, MonadThrow2, MonadThrow2C, MonadThrow3 } from 'fp-ts/lib/MonadThrow';
import {
fromProgressEvent,
MonadProgress,
MonadProgress1,
MonadProgress2,
MonadProgress2C,
MonadProgress3,
} from '../typeclasses/monad-progress/monad-progress';

export type FetchScriptConfig = {
shouldRemoveOnDispose?: boolean;
shouldTrackProgress?: boolean;
};

export function fetchScript<O extends URIS3, A extends URIS3>(
O: MonadObservable3<O>,
A: MonadThrow3<A> & MonadProgress3<A>,
): <OR, OE, AR, AE>(src: string, config?: FetchScriptConfig) => Kind3<O, OR, OE, Kind3<A, AR, AE, void>>;
export function fetchScript<O extends URIS3, A extends URIS2, AE>(
O: MonadObservable3<O>,
A: MonadThrow2C<A, AE> & MonadProgress2C<A, AE>,
): <OR, OE>(src: string, config?: FetchScriptConfig) => Kind3<O, OR, OE, Kind2<A, AE, void>>;
export function fetchScript<O extends URIS3, A extends URIS2>(
O: MonadObservable3<O>,
A: MonadThrow2<A> & MonadProgress2<A>,
): <OR, OE, AE>(src: string, config?: FetchScriptConfig) => Kind3<O, OR, OE, Kind2<A, AE, void>>;
export function fetchScript<O extends URIS3, A extends URIS>(
O: MonadObservable3<O>,
A: MonadThrow1<A> & MonadProgress1<A>,
): <OR, OE>(src: string, config?: FetchScriptConfig) => Kind3<O, OR, OE, Kind<A, void>>;
export function fetchScript<O extends URIS3, A>(
O: MonadObservable3<O>,
A: MonadThrow<A> & MonadProgress<A>,
): <OR, OE>(src: string, config?: FetchScriptConfig) => Kind3<O, OR, OE, HKT<A, void>>;

export function fetchScript<O extends URIS2, A extends URIS3, OE>(
O: MonadObservable2C<O, OE>,
A: MonadThrow3<A> & MonadProgress3<A>,
): <AR, AE>(src: string, config?: FetchScriptConfig) => Kind2<O, OE, Kind3<A, AR, AE, void>>;
export function fetchScript<O extends URIS2, A extends URIS2, OE, AE>(
O: MonadObservable2C<O, OE>,
A: MonadThrow2C<A, AE> & MonadProgress2C<A, AE>,
): (src: string, config?: FetchScriptConfig) => Kind2<O, OE, Kind2<A, AE, void>>;
export function fetchScript<O extends URIS2, A extends URIS2, OE>(
O: MonadObservable2C<O, OE>,
A: MonadThrow2<A> & MonadProgress2<A>,
): <AE>(src: string, config?: FetchScriptConfig) => Kind2<O, OE, Kind2<A, AE, void>>;
export function fetchScript<O extends URIS2, A extends URIS, OE>(
O: MonadObservable2C<O, OE>,
A: MonadThrow1<A> & MonadProgress1<A>,
): (src: string, config?: FetchScriptConfig) => Kind2<O, OE, Kind<A, void>>;
export function fetchScript<O extends URIS2, A, OE>(
O: MonadObservable2C<O, OE>,
A: MonadThrow<A> & MonadProgress<A>,
): (src: string, config?: FetchScriptConfig) => Kind2<O, OE, HKT<A, void>>;

export function fetchScript<O extends URIS2, A extends URIS3>(
O: MonadObservable2<O>,
A: MonadThrow3<A> & MonadProgress3<A>,
): <OE, AR, AE>(src: string, config?: FetchScriptConfig) => Kind2<O, OE, Kind3<A, AR, AE, void>>;
export function fetchScript<O extends URIS2, A extends URIS2, AE>(
O: MonadObservable2<O>,
A: MonadThrow2C<A, AE> & MonadProgress2C<A, AE>,
): <OE>(src: string, config?: FetchScriptConfig) => Kind2<O, OE, Kind2<A, AE, void>>;
export function fetchScript<O extends URIS2, A extends URIS2>(
O: MonadObservable2<O>,
A: MonadThrow2<A> & MonadProgress2<A>,
): <OE, AE>(src: string, config?: FetchScriptConfig) => Kind2<O, OE, Kind2<A, AE, void>>;
export function fetchScript<O extends URIS2, A extends URIS>(
O: MonadObservable2<O>,
A: MonadThrow1<A> & MonadProgress1<A>,
): <OE>(src: string, config?: FetchScriptConfig) => Kind2<O, OE, Kind<A, void>>;
export function fetchScript<O extends URIS2, A>(
O: MonadObservable2<O>,
A: MonadThrow<A> & MonadProgress<A>,
): <OE>(src: string, config?: FetchScriptConfig) => Kind2<O, OE, HKT<A, void>>;

export function fetchScript<O extends URIS, A extends URIS3>(
O: MonadObservable1<O>,
A: MonadThrow3<A> & MonadProgress3<A>,
): <AR, AE>(src: string, config?: FetchScriptConfig) => Kind<O, Kind3<A, AR, AE, void>>;
export function fetchScript<O extends URIS, A extends URIS2, AE>(
O: MonadObservable1<O>,
A: MonadThrow2C<A, AE> & MonadProgress2C<A, AE>,
): (src: string, config?: FetchScriptConfig) => Kind<O, Kind2<A, AE, void>>;
export function fetchScript<O extends URIS, A extends URIS2>(
O: MonadObservable1<O>,
A: MonadThrow2<A> & MonadProgress2<A>,
): <AE>(src: string, config?: FetchScriptConfig) => Kind<O, Kind2<A, AE, void>>;
export function fetchScript<O extends URIS, A extends URIS>(
O: MonadObservable1<O>,
A: MonadThrow1<A> & MonadProgress1<A>,
): (src: string, config?: FetchScriptConfig) => Kind<O, Kind<A, void>>;
export function fetchScript<O extends URIS, A>(
O: MonadObservable1<O>,
A: MonadThrow<A> & MonadProgress<A>,
): (src: string, config?: FetchScriptConfig) => Kind<O, HKT<A, void>>;

export function fetchScript<O, A extends URIS3>(
O: MonadObservable<O>,
A: MonadThrow3<A> & MonadProgress3<A>,
): <AR, AE>(src: string, config?: FetchScriptConfig) => HKT<O, Kind3<A, AR, AE, void>>;
export function fetchScript<O, A extends URIS2, AE>(
O: MonadObservable<O>,
A: MonadThrow2C<A, AE> & MonadProgress2C<A, AE>,
): (src: string, config?: FetchScriptConfig) => HKT<O, Kind2<A, AE, void>>;
export function fetchScript<O, A extends URIS2>(
O: MonadObservable<O>,
A: MonadThrow2<A> & MonadProgress2<A>,
): <AE>(src: string, config?: FetchScriptConfig) => HKT<O, Kind2<A, AE, void>>;
export function fetchScript<O, A extends URIS>(
O: MonadObservable<O>,
A: MonadThrow1<A> & MonadProgress1<A>,
): (src: string, config?: FetchScriptConfig) => HKT<O, Kind<A, void>>;
export function fetchScript<O, A>(
O: MonadObservable<O>,
A: MonadThrow<A> & MonadProgress<A>,
): (src: string, config?: FetchScriptConfig) => HKT<O, HKT<A, void>>;
export function fetchScript<O, A>(
O: MonadObservable<O>,
A: MonadThrow<A> & MonadProgress<A>,
): (src: string, config?: FetchScriptConfig) => HKT<O, HKT<A, void>> {
const fromProgressEventM = fromProgressEvent(A);
return (src, config = {}) =>
O.fromObservable({
subscribe: observer => {
const script = document.createElement('script');
script.async = true;
script.src = src;
script.async = true;
script.src = src;
script.onload = () => {
observer.next(A.of(undefined));
observer.end();
};
script.onerror = () => {
observer.next(A.throwError(new Error(`Cannot fetch script: ${src}`)));
observer.end();
};
if (config.shouldTrackProgress) {
script.onprogress = e => {
observer.next(fromProgressEventM(e));
};
}

document.body.appendChild(script);
return {
unsubscribe() {
if (config.shouldRemoveOnDispose) {
document.removeChild(script);
}
},
};
},
});
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { HKT, Kind, Kind2, Kind3, URIS, URIS2, URIS3 } from 'fp-ts/lib/HKT';
import { MonadTask, MonadTask1, MonadTask2, MonadTask2C, MonadTask3 } from 'fp-ts/lib/MonadTask';

export interface Subscription {
readonly unsubscribe: () => void;
}

export interface Observer<A> {
readonly next: (a: A) => void;
readonly end: () => void;
}

export interface Observable<A> {
readonly subscribe: (observer: Observer<A>) => Subscription;
}

export interface MonadObservable<M> extends MonadTask<M> {
readonly fromObservable: <A>(observable: Observable<A>) => HKT<M, A>;
}

export interface MonadObservable1<M extends URIS> extends MonadTask1<M> {
readonly fromObservable: <A>(observable: Observable<A>) => Kind<M, A>;
}

export interface MonadObservable2<M extends URIS2> extends MonadTask2<M> {
readonly fromObservable: <E, A>(observable: Observable<A>) => Kind2<M, E, A>;
}

export interface MonadObservable2C<M extends URIS2, E> extends MonadTask2C<M, E> {
readonly fromObservable: <A>(observable: Observable<A>) => Kind2<M, E, A>;
}

export interface MonadObservable3<M extends URIS3> extends MonadTask3<M> {
readonly fromObservable: <R, E, A>(observable: Observable<A>) => Kind3<M, R, E, A>;
}
47 changes: 47 additions & 0 deletions packages/utils/src/typeclasses/monad-progress/monad-progress.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
import { none, Option, some } from 'fp-ts/lib/Option';
import { HKT, Kind, Kind2, Kind3, URIS, URIS2, URIS3 } from 'fp-ts/lib/HKT';
import { Monad, Monad1, Monad2, Monad2C, Monad3 } from 'fp-ts/lib/Monad';

export interface Progress {
readonly loaded: number;
readonly total: Option<number>;
}

export interface MonadProgress<M> extends Monad<M> {
readonly fromProgress: <A>(progress: Progress) => HKT<M, A>;
}

export interface MonadProgress1<M extends URIS> extends Monad1<M> {
readonly fromProgress: <A>(progress: Progress) => Kind<M, A>;
}

export interface MonadProgress2<M extends URIS2> extends Monad2<M> {
readonly fromProgress: <E, A>(progress: Progress) => Kind2<M, E, A>;
}

export interface MonadProgress2C<M extends URIS2, E> extends Monad2C<M, E> {
readonly fromProgress: <A>(progress: Progress) => Kind2<M, E, A>;
}

export interface MonadProgress3<M extends URIS3> extends Monad3<M> {
readonly fromProgress: <R, E, A>(progress: Progress) => Kind3<M, R, E, A>;
}

export function fromProgressEvent<M extends URIS3>(
M: MonadProgress3<M>,
): <R, E, A>(event: ProgressEvent) => Kind3<M, R, E, A>;
export function fromProgressEvent<M extends URIS2, E>(
M: MonadProgress2C<M, E>,
): <A>(event: ProgressEvent) => Kind2<M, E, A>;
export function fromProgressEvent<M extends URIS2>(
M: MonadProgress2<M>,
): <E, A>(event: ProgressEvent) => Kind2<M, E, A>;
export function fromProgressEvent<M extends URIS>(M: MonadProgress1<M>): <A>(event: ProgressEvent) => Kind<M, A>;
export function fromProgressEvent<M>(M: MonadProgress<M>): <A>(event: ProgressEvent) => HKT<M, A>;
export function fromProgressEvent<M>(M: MonadProgress<M>): <A>(event: ProgressEvent) => HKT<M, A> {
return e =>
M.fromProgress({
loaded: e.loaded,
total: e.lengthComputable ? some(e.total) : none,
});
}
5 changes: 4 additions & 1 deletion packages/utils/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,8 @@
"es2016",
"dom"
]
}
},
"include": [
"src/**/*.ts"
]
}

0 comments on commit 3dc8534

Please sign in to comment.