Skip to content

Commit

Permalink
chore: generate types from JsDoc
Browse files Browse the repository at this point in the history
chore: add pipe types
  • Loading branch information
david-luna committed May 4, 2024
1 parent 81b7bf4 commit 4266f6c
Show file tree
Hide file tree
Showing 60 changed files with 1,195 additions and 291 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ node_modules

# test artifacts
test-report-*

# build artifacts
build
42 changes: 38 additions & 4 deletions lib/factories/combineLatest.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createObsevable } from '../observable.js';

/**
* @typedef {Object} ValueSlot
* @property {import('../types').Subscription} subscription
* @property {import('../observable').Subscription} subscription
* @property {unknown} [value]
*/

Expand All @@ -16,16 +16,50 @@ function withValue(o) {
}

/**
* @param {...import('../types').Observable<any>} observables
* @returns {import('../types').Observable<any>}
* @template A,B
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @returns {import('../observable').Observable<[A,B]>}
*/
/**
* @template A,B,C
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @param {import('../observable').Observable<C>} c
* @returns {import('../observable').Observable<[A,B,C]>}
*/
/**
* @template A,B,C,D
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @param {import('../observable').Observable<C>} c
* @param {import('../observable').Observable<D>} d
* @returns {import('../observable').Observable<[A,B,C,D]>}
*/
/**
* @template A,B,C,D,E
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @param {import('../observable').Observable<C>} c
* @param {import('../observable').Observable<D>} d
* @param {import('../observable').Observable<E>} e
* @returns {import('../observable').Observable<[A,B,C,D,E]>}
*/
/**
* @param {...import('../observable').Observable<any>} observables
* @returns {import('../observable').Observable<any>}
*/
export function combineLatest(...observables) {
return createObsevable((observer) => {
/** @type {ValueSlot[]} */
const slots = [];
let completedSubscriptions = 0;

/** @type {(i: number) => import('../types').Observer<any>} */
/** @type {(i: number) => import('../observable').Observer<any>} */
const indexedObserver = (index) => ({
next: (value) => {
slots[index].value = value;
Expand Down
40 changes: 37 additions & 3 deletions lib/factories/concat.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,46 @@
import { createObsevable } from '../observable.js';

/**
* @param {...import('../types').Observable<any>} observables
* @returns {import('../types').Observable<any>}
* @template A,B
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @returns {import('../observable').Observable<A|B>}
*/
/**
* @template A,B,C
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @param {import('../observable').Observable<C>} c
* @returns {import('../observable').Observable<A|B|C>}
*/
/**
* @template A,B,C,D
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @param {import('../observable').Observable<C>} c
* @param {import('../observable').Observable<D>} d
* @returns {import('../observable').Observable<A|B|C|D>}
*/
/**
* @template A,B,C,D,E
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @param {import('../observable').Observable<C>} c
* @param {import('../observable').Observable<D>} d
* @param {import('../observable').Observable<E>} e
* @returns {import('../observable').Observable<A|B|C|D|E>}
*/
/**
* @param {...import('../observable').Observable<any>} observables
* @returns {import('../observable').Observable<any>}
*/
export function concat(...observables) {
return createObsevable((observer) => {
/** @type {import('../types').Observer<any>} */
/** @type {import('../observable').Observer<any>} */
const innerObserver = {
next: (value) => {
observer.next(value);
Expand Down
8 changes: 4 additions & 4 deletions lib/factories/from.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ function isObservable(target) {
/**
* @template T
* @param {PromiseLike<T>} promise
* @returns {import('../types').Observable<T>}
* @returns {import('../observable').Observable<T>}
*/
function fromPromise(promise) {
return new Observable((observer) => {
Expand All @@ -32,7 +32,7 @@ function fromPromise(promise) {
/**
* @template T
* @param {ArrayLike<T>} array
* @returns {import('../types').Observable<T>}
* @returns {import('../observable').Observable<T>}
*/
function fromArray(array) {
return new Observable((observer) => {
Expand All @@ -45,8 +45,8 @@ function fromArray(array) {

/**
* @template T
* @param {import('../types').ObservableInput<T>} input
* @returns {import('../types').Observable<T>}
* @param {import('../observable').ObservableInput<T>} input
* @returns {import('../observable').Observable<T>}
*/
export function from(input) {
if (isPromiseLike(input)) {
Expand Down
103 changes: 89 additions & 14 deletions lib/factories/fromEvent.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,81 @@
// // NOTE: to mimic browser's CustomEvent
// type NodeOrBrowserEvent = Event | Event & { detail: any };
// export interface EventTargetLike<T extends NodeOrBrowserEvent> {
// addEventListener(
// type: string,
// listener: ((e: T) => void) | { handleEvent: (e: T) => void } | null,
// options?: any
// ): void;
// removeEventListener(
// type: string,
// listener: ((e: T) => void) | { handleEvent: (e: T) => void } | null,
// options?: any,
// ): void;
// }


// export interface EventEmitterLike<T extends (...args: any[]) => void> {
// addListener(
// type: string,
// listener: T,
// options?: any
// ): void;
// removeListener(
// type: string,
// listener: T,
// options?: any,
// ): void;
// }



import { createObsevable } from '../observable.js';

/**
* @param {import('../types').EventTargetLike<any>} target
* NOTE: to mimic browser's CustomEvent
* @typedef {Event | Event & { detail: any }} NodeOrBrowserEvent
*/
/**
* @template {NodeOrBrowserEvent} T
* @callback EventListenerFn
* @param {string} type
* @param {((e: T) => void) | { handleEvent: (e: T) => void } | null} listener
* @param {any} [options]
*/
/**
* @template {NodeOrBrowserEvent} T
* @typedef {Object} EventTargetLike<T>
* @property {EventListenerFn<T>} addEventListener
* @property {EventListenerFn<T>} removeEventListener
*/
/**
* @template {(...args: any[]) => void} T
* @callback ListenerFn
* @param {string} type
* @param {T} listener
* @param {any} [options]
*/
/**
* @template {(...args: any[]) => void} T
* @typedef {Object} EventEmitterLike<T>
* @property {ListenerFn<T>} addListener
* @property {ListenerFn<T>} removeListener
*/
/**
* @template T
* @typedef {T extends EventTargetLike<infer E> ? E : never} EventParam<T>
*/
/**
* @template T
* @typedef {T extends EventEmitterLike<infer F> ? Parameters<F> : EventParam<T>} EventOrParams<T>
*/



/**
* @param {EventTargetLike<any>} target
* @param {string} eventName
* @returns {import('../types').Observable<any>}
* @returns {import('../observable').Observable<any>}
*/
function fromEventTarget(target, eventName) {
return createObsevable((observer) => {
Expand All @@ -17,9 +89,9 @@ function fromEventTarget(target, eventName) {
}

/**
* @param {import('../types').EventEmitterLike<any>} target
* @param {EventEmitterLike<any>} target
* @param {string} eventName
* @returns {import('../types').Observable<any>}
* @returns {import('../observable').Observable<any>}
*/
function fromEventEmitter(target, eventName) {
return createObsevable((observer) => {
Expand All @@ -32,17 +104,20 @@ function fromEventEmitter(target, eventName) {
});
}

// /**
// * Returns an observable from
// * @param {any} target
// * @param {string} eventName
// * @returns {import('../types').Observable<any>}
// */
/**
* @template {EventTargetLike<any> | EventEmitterLike<any>} T
* @param {T} target
* @param {string} eventName
* @returns {import('../observable').Observable<EventOrParams<T>>}
*/
export function fromEvent(target, eventName) {
if (typeof target.addEventListener === 'function') {
return fromEventTarget(target, eventName);
} else if (typeof target.addListener === 'function') {
return fromEventEmitter(target, eventName);
/** @type {any} */
const t = target;

if (typeof t.addEventListener === 'function') {
return fromEventTarget(t, eventName);
} else if (typeof t.addListener === 'function') {
return fromEventEmitter(t, eventName);
}

throw new Error('cannot create an observable for the given input');
Expand Down
2 changes: 1 addition & 1 deletion lib/factories/fromEventPattern.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import { createObsevable } from '../observable.js';
* @param {(handler: EventHandlerLike) => unknown} addHandler
* @param {(handler: EventHandlerLike, signal: unknown) => unknown} removeHandler
* @param {(...args: any[]) => T} [project]
* @returns {import('../types').Observable<T>}
* @returns {import('../observable').Observable<T>}
*/
export function fromEventPattern(addHandler, removeHandler, project) {
return createObsevable((observer) => {
Expand Down
2 changes: 1 addition & 1 deletion lib/factories/interval.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createObsevable } from '../observable.js';

/**
* @param {number} period
* @returns {import('../types').Observable<number>}
* @returns {import('../observable').Observable<number>}
*/
export function interval(period) {
return createObsevable((observer) => {
Expand Down
42 changes: 38 additions & 4 deletions lib/factories/merge.js
Original file line number Diff line number Diff line change
@@ -1,16 +1,50 @@
import { createObsevable } from '../observable.js';

/**
* @param {...import('../types').Observable<any>} observables
* @returns {import('../types').Observable<any>}
* @template A,B
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @returns {import('../observable').Observable<A|B>}
*/
/**
* @template A,B,C
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @param {import('../observable').Observable<C>} c
* @returns {import('../observable').Observable<A|B|C>}
*/
/**
* @template A,B,C,D
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @param {import('../observable').Observable<C>} c
* @param {import('../observable').Observable<D>} d
* @returns {import('../observable').Observable<A|B|C|D>}
*/
/**
* @template A,B,C,D,E
* @overload
* @param {import('../observable').Observable<A>} a
* @param {import('../observable').Observable<B>} b
* @param {import('../observable').Observable<C>} c
* @param {import('../observable').Observable<D>} d
* @param {import('../observable').Observable<E>} e
* @returns {import('../observable').Observable<A|B|C|D|E>}
*/
/**
* @param {...import('../observable').Observable<any>} observables
* @returns {import('../observable').Observable<any>}
*/
export function merge(...observables) {
return createObsevable((observer) => {
/** @type {import('../types').Subscription[]} */
/** @type {import('../observable').Subscription[]} */
const innerSubscriptions = [];
let completedSubscriptions = 0;

/** @type {import('../types').Observer<any>} */
/** @type {import('../observable').Observer<any>} */
const innerObserver = {
next: (value) => {
observer.next(value);
Expand Down
2 changes: 1 addition & 1 deletion lib/factories/of.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createObsevable } from '../observable.js';

/**
* @param {Array<unknown>} inputs
* @returns {import('../types').Observable<unknown>}
* @returns {import('../observable').Observable<unknown>}
*/
export function of(...inputs) {
return createObsevable((observer) => {
Expand Down
2 changes: 1 addition & 1 deletion lib/factories/sequence.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { createObsevable } from '../observable.js';
* @template T
* @param {number} period
* @param {(index: number) => T} factory
* @returns {import('../types').Observable<T>}
* @returns {import('../observable').Observable<T>}
*/
// @ts-ignore -- skip the check for default factory
export function sequence(period = 0, factory = (x) => x) {
Expand Down
2 changes: 1 addition & 1 deletion lib/factories/timer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { createObsevable } from '../observable.js';

/**
* @param {number | Date} due
* @returns {import('../types').Observable<void>}
* @returns {import('../observable').Observable<void>}
*/
export function timer(due) {
return createObsevable((observer) => {
Expand Down
Loading

0 comments on commit 4266f6c

Please sign in to comment.