@helpers4/observable 2.0.1 → 2.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -14,6 +14,7 @@ A set of helpers for working with URLs.
14
14
  <!-- AUTOMATIC-METHODS -->
15
15
  - combine
16
16
  - combineLatest
17
+ - isObservable
17
18
  <!-- /AUTOMATIC-METHODS -->
18
19
 
19
20
  ## See
package/lib/index.d.ts CHANGED
@@ -38,4 +38,29 @@ declare function combineLatest<T extends Record<string, ObservableInput<unknown>
38
38
  [K in keyof T]: ObservedValueOf<T[K]>;
39
39
  }>;
40
40
 
41
- export { combine, combineLatest };
41
+ /**
42
+ * This file is part of helpers4.
43
+ * Copyright (C) 2025 baxyz
44
+ * SPDX-License-Identifier: LGPL-3.0-or-later
45
+ */
46
+
47
+ /**
48
+ * Checks if a value is an RxJS Observable or any compatible observable.
49
+ *
50
+ * Uses duck-typing: returns `true` for any object with both `.subscribe()` and
51
+ * `.pipe()` methods, covering `Observable`, `Subject`, `BehaviorSubject`,
52
+ * `ReplaySubject`, and any RxJS-compatible observable implementation.
53
+ *
54
+ * @param value - The value to check
55
+ * @returns `true` if value is observable-like
56
+ * @example
57
+ * import { Observable, Subject } from 'rxjs';
58
+ * isObservable(new Observable()) // => true
59
+ * isObservable(new Subject()) // => true
60
+ * isObservable(Promise.resolve()) // => false
61
+ * isObservable({}) // => false
62
+ * @since 2.0.3
63
+ */
64
+ declare function isObservable(value: unknown): value is Observable<unknown>;
65
+
66
+ export { combine, combineLatest, isObservable };
package/lib/index.js CHANGED
@@ -96,6 +96,28 @@ function combineLatest(input) {
96
96
  }
97
97
  }
98
98
  //#endregion
99
- export { combine, combineLatest };
99
+ //#region helpers/observable/isObservable.ts
100
+ /**
101
+ * Checks if a value is an RxJS Observable or any compatible observable.
102
+ *
103
+ * Uses duck-typing: returns `true` for any object with both `.subscribe()` and
104
+ * `.pipe()` methods, covering `Observable`, `Subject`, `BehaviorSubject`,
105
+ * `ReplaySubject`, and any RxJS-compatible observable implementation.
106
+ *
107
+ * @param value - The value to check
108
+ * @returns `true` if value is observable-like
109
+ * @example
110
+ * import { Observable, Subject } from 'rxjs';
111
+ * isObservable(new Observable()) // => true
112
+ * isObservable(new Subject()) // => true
113
+ * isObservable(Promise.resolve()) // => false
114
+ * isObservable({}) // => false
115
+ * @since 2.0.3
116
+ */
117
+ function isObservable(value) {
118
+ return value !== null && typeof value === "object" && typeof value["subscribe"] === "function" && typeof value["pipe"] === "function";
119
+ }
120
+ //#endregion
121
+ export { combine, combineLatest, isObservable };
100
122
 
101
123
  //# sourceMappingURL=index.js.map
package/lib/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../helpers/observable/combine.ts","../../../helpers/type/isDefined.ts","../../../helpers/observable/combineLatest.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/*\n * This program is under the terms of the GNU Lesser General Public License version 3\n * The full license information can be found in LICENSE in the root directory of this project.\n */\nimport {\n Observable,\n OperatorFunction,\n combineLatest as combineLatestOperator,\n map as mapOperator,\n} from \"rxjs\";\n\n\ntype combineOptions<T, U> = {\n readonly preTreatment?: OperatorFunction<readonly [T, U], readonly [T, U]>;\n};\n\n/**\n * Combine two observables with a map function and an optional pre-treatment.\n *\n * Note: you can use the pre-treatment to add a filter, a distinctUntilChanged,\n * any other operator that can be used in a pipe, or even an `UntilDestroy`\n * operator.\n *\n * @param source1 first source of data\n * @param source2 second source of data\n * @param map way to combine data\n * @param options options for the combineLatest operator\n * @returns an observable that emits the result of the map function\n * @see combineLatestOperator\n * @see mapOperator\n * @since 1.0.0\n */\nexport function combine<T, U, R>(\n source1: Observable<T>,\n source2: Observable<U>,\n map: (c: readonly [T, U]) => R,\n options?: combineOptions<T, U>\n): Observable<R> {\n if (options?.preTreatment) {\n return combineLatestOperator([source1, source2]).pipe(\n options.preTreatment,\n mapOperator(map)\n );\n } else {\n return combineLatestOperator([source1, source2]).pipe(mapOperator(map));\n }\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport type { Maybe } from './Maybe';\n\n/**\n * Checks if a value is defined (not undefined nor null).\n * This is the inverse of {@link isNullish}.\n *\n * Use as a type-safe filter callback to remove `null`/`undefined` from arrays.\n *\n * @param value - The value to check\n * @returns True if value is not undefined nor null\n * @example\n * isDefined(42) // => true\n * isDefined('') // => true (empty string is defined)\n * isDefined(null) // => false\n * isDefined(undefined) // => false\n *\n * @example\n * // Type-safe alternative to filter out null/undefined\n * const items: (string | null | undefined)[] = ['a', null, 'b', undefined];\n * const result = items.filter(isDefined);\n * // => ['a', 'b'] with type string[]\n *\n * @see {@link isNullish} for the inverse check\n * @see {@link isTruthy} to also filter out `0`, `\"\"`, `false`, and `NaN`\n * @since 2.0.0\n */\nexport function isDefined<T>(value: Maybe<T>): value is T {\n return value !== undefined && value !== null;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/*\n * This program is under the terms of the GNU Lesser General Public License version 3\n * The full license information can be found in LICENSE in the root directory of this project.\n */\nimport {\n Observable,\n ObservableInput,\n ObservableInputTuple,\n ObservedValueOf,\n combineLatest as combineLatestOperator,\n of,\n} from \"rxjs\";\nimport { isDefined } from '../type/isDefined';\n\n// combineLatest([a, b, c])\nexport function combineLatest<A extends readonly unknown[]>(\n sources: readonly [...ObservableInputTuple<A>]\n): Observable<A>;\n\n// combineLatest({a, b, c})\nexport function combineLatest<T extends Record<string, ObservableInput<unknown>>>(\n sourcesObject: T\n): Observable<{ [K in keyof T]: ObservedValueOf<T[K]> }>;\n\n/**\n * Combines multiple Observables to create an Observable whose values are\n * calculated from the latest values of each of its input Observables.\n *\n * This method relies on {@link combineLatestOperator} of rxjs.\n *\n * The main difference with {@link combineLatestOperator} is in case of empty parameters.\n * If the parameter is empty (empty array or empty object), the result will be\n * also empty.\n *\n * ATTENTION: this version doesn't support `scheduler` nor `mapper` as last\n * argument like in {@link combineLatestOperator}.\n *\n * @see {@link combineLatestOperator}\n * @see {@link combineLatestAll}\n * @see {@link merge}\n * @see {@link withLatestFrom}\n *\n * @param {ObservableInput} [observables] An array of input Observables to combine with each other.\n * An array of Observables must be given as the first argument.\n * @returns {Observable} An Observable of projected values from the most recent\n * values from each input Observable, or an array of the most recent values from\n * each input Observable.\n * @since 1.0.0\n */\nexport function combineLatest(input: readonly ObservableInput<unknown>[] | Record<string, ObservableInput<unknown>>): Observable<unknown> {\n if (Array.isArray(input)) {\n const filtered = input.filter(isDefined);\n return filtered.length ? combineLatestOperator(filtered) : of([]);\n } else {\n const filtered = Object.fromEntries(\n Object.entries(input).filter(([_, v]) => isDefined(v)),\n );\n return Object.keys(filtered).length\n ? combineLatestOperator(filtered)\n : of({});\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,QACd,SACA,SACA,OACA,SACe;CACf,IAAI,SAAS,cACX,OAAO,gBAAsB,CAAC,SAAS,OAAO,CAAC,EAAE,KAC/C,QAAQ,cACR,IAAY,KAAG,CACjB;MAEA,OAAO,gBAAsB,CAAC,SAAS,OAAO,CAAC,EAAE,KAAK,IAAY,KAAG,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpBA,SAAgB,UAAa,OAA6B;CACxD,OAAO,UAAU,KAAA,KAAa,UAAU;AAC1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACqBA,SAAgB,cAAc,OAA4G;CACxI,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,MAAM,WAAW,MAAM,OAAO,SAAS;EACvC,OAAO,SAAS,SAAS,gBAAsB,QAAQ,IAAI,GAAG,CAAC,CAAC;CAClE,OAAO;EACL,MAAM,WAAW,OAAO,YACtB,OAAO,QAAQ,KAAK,EAAE,QAAQ,CAAC,GAAG,OAAO,UAAU,CAAC,CAAC,CACvD;EACA,OAAO,OAAO,KAAK,QAAQ,EAAE,SACzB,gBAAsB,QAAQ,IAC9B,GAAG,CAAC,CAAC;CACX;AACF"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../helpers/observable/combine.ts","../../../helpers/type/isDefined.ts","../../../helpers/observable/combineLatest.ts","../../../helpers/observable/isObservable.ts"],"sourcesContent":["/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/*\n * This program is under the terms of the GNU Lesser General Public License version 3\n * The full license information can be found in LICENSE in the root directory of this project.\n */\nimport {\n Observable,\n OperatorFunction,\n combineLatest as combineLatestOperator,\n map as mapOperator,\n} from \"rxjs\";\n\n\ntype combineOptions<T, U> = {\n readonly preTreatment?: OperatorFunction<readonly [T, U], readonly [T, U]>;\n};\n\n/**\n * Combine two observables with a map function and an optional pre-treatment.\n *\n * Note: you can use the pre-treatment to add a filter, a distinctUntilChanged,\n * any other operator that can be used in a pipe, or even an `UntilDestroy`\n * operator.\n *\n * @param source1 first source of data\n * @param source2 second source of data\n * @param map way to combine data\n * @param options options for the combineLatest operator\n * @returns an observable that emits the result of the map function\n * @see combineLatestOperator\n * @see mapOperator\n * @since 1.0.0\n */\nexport function combine<T, U, R>(\n source1: Observable<T>,\n source2: Observable<U>,\n map: (c: readonly [T, U]) => R,\n options?: combineOptions<T, U>\n): Observable<R> {\n if (options?.preTreatment) {\n return combineLatestOperator([source1, source2]).pipe(\n options.preTreatment,\n mapOperator(map)\n );\n } else {\n return combineLatestOperator([source1, source2]).pipe(mapOperator(map));\n }\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport type { Maybe } from './Maybe';\n\n/**\n * Checks if a value is defined (not undefined nor null).\n * This is the inverse of {@link isNullish}.\n *\n * Use as a type-safe filter callback to remove `null`/`undefined` from arrays.\n *\n * @param value - The value to check\n * @returns True if value is not undefined nor null\n * @example\n * isDefined(42) // => true\n * isDefined('') // => true (empty string is defined)\n * isDefined(null) // => false\n * isDefined(undefined) // => false\n *\n * @example\n * // Type-safe alternative to filter out null/undefined\n * const items: (string | null | undefined)[] = ['a', null, 'b', undefined];\n * const result = items.filter(isDefined);\n * // => ['a', 'b'] with type string[]\n *\n * @see {@link isNullish} for the inverse check\n * @see {@link isTruthy} to also filter out `0`, `\"\"`, `false`, and `NaN`\n * @since 2.0.0\n */\nexport function isDefined<T>(value: Maybe<T>): value is T {\n return value !== undefined && value !== null;\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\n/*\n * This program is under the terms of the GNU Lesser General Public License version 3\n * The full license information can be found in LICENSE in the root directory of this project.\n */\nimport {\n Observable,\n ObservableInput,\n ObservableInputTuple,\n ObservedValueOf,\n combineLatest as combineLatestOperator,\n of,\n} from \"rxjs\";\nimport { isDefined } from '../type/isDefined';\n\n// combineLatest([a, b, c])\nexport function combineLatest<A extends readonly unknown[]>(\n sources: readonly [...ObservableInputTuple<A>]\n): Observable<A>;\n\n// combineLatest({a, b, c})\nexport function combineLatest<T extends Record<string, ObservableInput<unknown>>>(\n sourcesObject: T\n): Observable<{ [K in keyof T]: ObservedValueOf<T[K]> }>;\n\n/**\n * Combines multiple Observables to create an Observable whose values are\n * calculated from the latest values of each of its input Observables.\n *\n * This method relies on {@link combineLatestOperator} of rxjs.\n *\n * The main difference with {@link combineLatestOperator} is in case of empty parameters.\n * If the parameter is empty (empty array or empty object), the result will be\n * also empty.\n *\n * ATTENTION: this version doesn't support `scheduler` nor `mapper` as last\n * argument like in {@link combineLatestOperator}.\n *\n * @see {@link combineLatestOperator}\n * @see {@link combineLatestAll}\n * @see {@link merge}\n * @see {@link withLatestFrom}\n *\n * @param {ObservableInput} [observables] An array of input Observables to combine with each other.\n * An array of Observables must be given as the first argument.\n * @returns {Observable} An Observable of projected values from the most recent\n * values from each input Observable, or an array of the most recent values from\n * each input Observable.\n * @since 1.0.0\n */\nexport function combineLatest(input: readonly ObservableInput<unknown>[] | Record<string, ObservableInput<unknown>>): Observable<unknown> {\n if (Array.isArray(input)) {\n const filtered = input.filter(isDefined);\n return filtered.length ? combineLatestOperator(filtered) : of([]);\n } else {\n const filtered = Object.fromEntries(\n Object.entries(input).filter(([_, v]) => isDefined(v)),\n );\n return Object.keys(filtered).length\n ? combineLatestOperator(filtered)\n : of({});\n }\n}\n","/**\n * This file is part of helpers4.\n * Copyright (C) 2025 baxyz\n * SPDX-License-Identifier: LGPL-3.0-or-later\n */\n\nimport type { Observable } from 'rxjs';\n\n/**\n * Checks if a value is an RxJS Observable or any compatible observable.\n *\n * Uses duck-typing: returns `true` for any object with both `.subscribe()` and\n * `.pipe()` methods, covering `Observable`, `Subject`, `BehaviorSubject`,\n * `ReplaySubject`, and any RxJS-compatible observable implementation.\n *\n * @param value - The value to check\n * @returns `true` if value is observable-like\n * @example\n * import { Observable, Subject } from 'rxjs';\n * isObservable(new Observable()) // => true\n * isObservable(new Subject()) // => true\n * isObservable(Promise.resolve()) // => false\n * isObservable({}) // => false\n * @since 2.0.3\n */\nexport function isObservable(value: unknown): value is Observable<unknown> {\n return (\n // Intentionally `object`-only, unlike `isPromiseLike` (see type/isPromiseLike.ts):\n // a callable function exposing `.subscribe()`/`.pipe()` would be an unusual,\n // contrived observable shape.\n value !== null &&\n typeof value === 'object' &&\n typeof (value as Record<string, unknown>)['subscribe'] === 'function' &&\n typeof (value as Record<string, unknown>)['pipe'] === 'function'\n );\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAsCA,SAAgB,QACd,SACA,SACA,OACA,SACe;CACf,IAAI,SAAS,cACX,OAAO,gBAAsB,CAAC,SAAS,OAAO,CAAC,EAAE,KAC/C,QAAQ,cACR,IAAY,KAAG,CACjB;MAEA,OAAO,gBAAsB,CAAC,SAAS,OAAO,CAAC,EAAE,KAAK,IAAY,KAAG,CAAC;AAE1E;;;;;;;;;;;;;;;;;;;;;;;;;;;ACpBA,SAAgB,UAAa,OAA6B;CACxD,OAAO,UAAU,KAAA,KAAa,UAAU;AAC1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACqBA,SAAgB,cAAc,OAA4G;CACxI,IAAI,MAAM,QAAQ,KAAK,GAAG;EACxB,MAAM,WAAW,MAAM,OAAO,SAAS;EACvC,OAAO,SAAS,SAAS,gBAAsB,QAAQ,IAAI,GAAG,CAAC,CAAC;CAClE,OAAO;EACL,MAAM,WAAW,OAAO,YACtB,OAAO,QAAQ,KAAK,EAAE,QAAQ,CAAC,GAAG,OAAO,UAAU,CAAC,CAAC,CACvD;EACA,OAAO,OAAO,KAAK,QAAQ,EAAE,SACzB,gBAAsB,QAAQ,IAC9B,GAAG,CAAC,CAAC;CACX;AACF;;;;;;;;;;;;;;;;;;;;AC1CA,SAAgB,aAAa,OAA8C;CACzE,OAIE,UAAU,QACV,OAAO,UAAU,YACjB,OAAQ,MAAkC,iBAAiB,cAC3D,OAAQ,MAAkC,YAAY;AAE1D"}
package/llms.txt CHANGED
@@ -1,7 +1,7 @@
1
1
  # @helpers4/observable
2
2
 
3
3
  > Tree-shakable TypeScript utility functions for the `observable` domain.
4
- > Package: `@helpers4/observable` — Version: 2.0.1
4
+ > Package: `@helpers4/observable` — Version: 2.0.3
5
5
  > License: LGPL-3.0-or-later
6
6
 
7
7
  ## Installation
@@ -15,7 +15,7 @@ pnpm add @helpers4/observable
15
15
  ## Usage
16
16
 
17
17
  ```typescript
18
- import { combine, combineLatest } from '@helpers4/observable';
18
+ import { combine, combineLatest, isObservable } from '@helpers4/observable';
19
19
  ```
20
20
 
21
21
  ## Functions
@@ -24,6 +24,7 @@ import { combine, combineLatest } from '@helpers4/observable';
24
24
  |---|---|
25
25
  | `combine` | Combine two observables with a map function and an optional pre-treatment. Note: you can use the pr |
26
26
  | `combineLatest` | Combines multiple Observables to create an Observable whose values are calculated from the latest va |
27
+ | `isObservable` | Checks if a value is an RxJS Observable or any compatible observable. Uses duck-typing: returns `tr |
27
28
 
28
29
  ---
29
30
 
@@ -120,3 +121,50 @@ combineLatest([])
120
121
  ```
121
122
 
122
123
  ---
124
+
125
+ ### `isObservable`
126
+
127
+ Checks if a value is an RxJS Observable or any compatible observable.
128
+
129
+ Uses duck-typing: returns `true` for any object with both `.subscribe()` and
130
+ `.pipe()` methods, covering `Observable`, `Subject`, `BehaviorSubject`,
131
+ `ReplaySubject`, and any RxJS-compatible observable implementation.
132
+
133
+ ```typescript
134
+ import { isObservable } from '@helpers4/observable';
135
+
136
+ isObservable(value: unknown): value is Observable<unknown>
137
+ ```
138
+
139
+ **Parameters:**
140
+
141
+ - `value: unknown` — The value to check
142
+
143
+ **Returns:** `value is Observable<unknown>` — `true` if value is observable-like
144
+
145
+ **Examples:**
146
+
147
+ *Detect an RxJS Observable or Subject*
148
+
149
+ Returns true for Observable, Subject, BehaviorSubject, and any duck-typed observable.
150
+
151
+ ```typescript
152
+ import { Observable, Subject } from 'rxjs';
153
+ isObservable(new Observable()) // => true
154
+ isObservable(new Subject()) // => true
155
+ isObservable(Promise.resolve()) // => false
156
+ isObservable({}) // => false
157
+ ```
158
+
159
+ *Accept either an Observable or a plain value*
160
+
161
+ Use as a guard to normalize inputs that may be Observables or raw values.
162
+
163
+ ```typescript
164
+ import { Observable, of } from 'rxjs';
165
+ function toObservable<T>(value: T | Observable<T>): Observable<T> {
166
+ return isObservable(value) ? value : of(value);
167
+ }
168
+ ```
169
+
170
+ ---
package/meta/api.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "category": "observable",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "functions": [
5
5
  {
6
6
  "name": "combine",
@@ -122,6 +122,42 @@
122
122
  }
123
123
  ],
124
124
  "sourceFile": "combineLatest.ts"
125
+ },
126
+ {
127
+ "name": "isObservable",
128
+ "kind": "function",
129
+ "description": "Checks if a value is an RxJS Observable or any compatible observable.\n\nUses duck-typing: returns `true` for any object with both `.subscribe()` and\n`.pipe()` methods, covering `Observable`, `Subject`, `BehaviorSubject`,\n`ReplaySubject`, and any RxJS-compatible observable implementation.",
130
+ "since": "2.0.3",
131
+ "signatures": [
132
+ {
133
+ "signature": "isObservable(value: unknown): value is Observable<unknown>",
134
+ "description": "Checks if a value is an RxJS Observable or any compatible observable.\n\nUses duck-typing: returns `true` for any object with both `.subscribe()` and\n`.pipe()` methods, covering `Observable`, `Subject`, `BehaviorSubject`,\n`ReplaySubject`, and any RxJS-compatible observable implementation.",
135
+ "params": [
136
+ {
137
+ "name": "value",
138
+ "type": "unknown",
139
+ "description": "The value to check"
140
+ }
141
+ ],
142
+ "returns": {
143
+ "type": "value is Observable<unknown>",
144
+ "description": "`true` if value is observable-like"
145
+ }
146
+ }
147
+ ],
148
+ "examples": [
149
+ {
150
+ "title": "Detect an RxJS Observable or Subject",
151
+ "description": "Returns true for Observable, Subject, BehaviorSubject, and any duck-typed observable.",
152
+ "code": "import { Observable, Subject } from 'rxjs';\nisObservable(new Observable()) // => true\nisObservable(new Subject()) // => true\nisObservable(Promise.resolve()) // => false\nisObservable({}) // => false"
153
+ },
154
+ {
155
+ "title": "Accept either an Observable or a plain value",
156
+ "description": "Use as a guard to normalize inputs that may be Observables or raw values.",
157
+ "code": "import { Observable, of } from 'rxjs';\nfunction toObservable<T>(value: T | Observable<T>): Observable<T> {\n return isObservable(value) ? value : of(value);\n}"
158
+ }
159
+ ],
160
+ "sourceFile": "isObservable.ts"
125
161
  }
126
162
  ]
127
163
  }
@@ -25,6 +25,21 @@
25
25
  "code": "combineLatest([])\n// emits []"
26
26
  }
27
27
  ]
28
+ },
29
+ {
30
+ "name": "isObservable",
31
+ "examples": [
32
+ {
33
+ "title": "Detect an RxJS Observable or Subject",
34
+ "description": "Returns true for Observable, Subject, BehaviorSubject, and any duck-typed observable.",
35
+ "code": "import { Observable, Subject } from 'rxjs';\nisObservable(new Observable()) // => true\nisObservable(new Subject()) // => true\nisObservable(Promise.resolve()) // => false\nisObservable({}) // => false"
36
+ },
37
+ {
38
+ "title": "Accept either an Observable or a plain value",
39
+ "description": "Use as a guard to normalize inputs that may be Observables or raw values.",
40
+ "code": "import { Observable, of } from 'rxjs';\nfunction toObservable<T>(value: T | Observable<T>): Observable<T> {\n return isObservable(value) ? value : of(value);\n}"
41
+ }
42
+ ]
28
43
  }
29
44
  ]
30
45
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@helpers4/observable",
3
- "version": "2.0.1",
3
+ "version": "2.0.3",
4
4
  "description": "A set of helpers in TS/JS, compatible with tree-shaking, for observable.",
5
5
  "author": "baxyz <baxy@etik.com>",
6
6
  "license": "LGPL-3.0",
@@ -28,7 +28,8 @@
28
28
  "helpers",
29
29
  "observable",
30
30
  "combine",
31
- "combineLatest"
31
+ "combineLatest",
32
+ "isObservable"
32
33
  ],
33
34
  "files": [
34
35
  "lib/index.js",