Skip to content

Commit 848fca2

Browse files
committed
Revive zen-observable-ts wrapper.
Apollo Client currently uses the Observable implementation provided by the zen-observable npm package, since it is small and works well for our needs. Although zen-observable itself is not written in TypeScript, we use the companion package @types/zen-observable to provide types. We are actively considering switching from zen-observable to RxJS (#5749), though it remains to be seen how much of a breaking change that will be (and thus whether it makes sense for a minor or major version update). In the meantime, several issues (most recently #5961) have been opened pointing out that zen-observable effectively does not support importing its code as ECMAScript modules, even though it has a separate entry point (zen-observable/esm.js) that uses ESM syntax. This is a problem the zen-observable package could easily fix by adding a "module" field to its package.json, but @abdonrd tried to propose that change in a PR (as I requested), and has not heard back since June 2020: zenparsing/zen-observable#74 Fortunately, Apollo maintains an npm package called zen-observable-ts, which was originally created to provide TypeScript types, before @types/zen-observable was introduced. This commit revives that wrapper package, so we can make sure both CommonJS and ESM exports are supported, with full TypeScript types, until the zen-observable maintainer gets around to merging that PR. I considered forking zen-observable, but I'm happy with this wrapping strategy, since reusing zen-observable makes it easier to take advantage of any future updates to the zen-observable package. I also considered using https://www.npmjs.com/package/patch-package to apply changes to node_modules/zen-observable/package.json upon installation, but that doesn't really work unless @apollo/client bundles the zen-observable implementation into itself, since otherwise the original (unpatched) zen-observable package will continue to be installed when developers npm install @apollo/client. The patch-package tool is great, but I don't think it's meant for libraries to use. Thankfully, this time around we do not need to hand-write the TypeScript types, since they can be re-exported from @types/zen-observable. I bumped the major version of zen-observable-ts, since the older versions (used by apollo-link) still get more than two million downloads per week. The source code for the zen-observable-ts package can now be found at https://github.com/apollographql/zen-observable-ts, rather than the old https://github.com/apollographql/apollo-link monorepo.
1 parent 333ff48 commit 848fca2

File tree

3 files changed

+29
-14
lines changed

3 files changed

+29
-14
lines changed

package-lock.json

+18-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

+1-2
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,6 @@
7474
},
7575
"dependencies": {
7676
"@graphql-typed-document-node/core": "^3.0.0",
77-
"@types/zen-observable": "^0.8.0",
7877
"@wry/context": "^0.5.2",
7978
"@wry/equality": "^0.3.0",
8079
"@wry/trie": "^0.2.1",
@@ -86,7 +85,7 @@
8685
"symbol-observable": "^2.0.0",
8786
"ts-invariant": "^0.6.0",
8887
"tslib": "^1.10.0",
89-
"zen-observable": "^0.8.14"
88+
"zen-observable-ts": "^1.0.0-beta.4"
9089
},
9190
"devDependencies": {
9291
"@babel/parser": "7.12.11",

src/utilities/observables/Observable.ts

+10-3
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,17 @@
1-
import Observable from 'zen-observable';
1+
import {
2+
Observable,
3+
Observer,
4+
Subscription as ObservableSubscription,
5+
} from 'zen-observable-ts';
26

37
// This simplified polyfill attempts to follow the ECMAScript Observable
48
// proposal (https://github.com/zenparsing/es-observable)
59
import 'symbol-observable';
610

7-
export type ObservableSubscription = ZenObservable.Subscription;
8-
export type Observer<T> = ZenObservable.Observer<T>;
11+
export type {
12+
Observer,
13+
ObservableSubscription,
14+
};
915

1016
// Use global module augmentation to add RxJS interop functionality. By
1117
// using this approach (instead of subclassing `Observable` and adding an
@@ -18,4 +24,5 @@ declare global {
1824
}
1925
}
2026
(Observable.prototype as any)['@@observable'] = function () { return this; };
27+
2128
export { Observable };

0 commit comments

Comments
 (0)