mirror of
https://github.com/re-rxjs/react-rxjs.git
synced 2025-12-08 18:01:51 +00:00
chore: remove tsdx and upgrade dependencies
This commit is contained in:
parent
03ef720011
commit
80a9fd67ee
2
.github/workflows/CI.yml
vendored
2
.github/workflows/CI.yml
vendored
@ -15,7 +15,7 @@ jobs:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12'
|
||||
node-version: '14'
|
||||
- run: yarn install --frozen-lockfile
|
||||
- run: yarn lint
|
||||
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@ -4,8 +4,8 @@ node_modules
|
||||
coverage
|
||||
.cache
|
||||
packages/core/dist/**
|
||||
!packages/core/dist/index.js
|
||||
!packages/core/dist/index.cjs
|
||||
packages/utils/dist/**
|
||||
!packages/utils/dist/index.js
|
||||
!packages/utils/dist/index.cjs
|
||||
packages/dom/dist/**
|
||||
!packages/dom/dist/index.js
|
||||
!packages/dom/dist/index.cjs
|
||||
|
||||
33
package.json
33
package.json
@ -18,7 +18,7 @@
|
||||
},
|
||||
{
|
||||
"path": "./packages/dom/dist/dom.cjs.production.min.js",
|
||||
"maxSize": "1 kB",
|
||||
"maxSize": "2 kB",
|
||||
"compression": "none"
|
||||
},
|
||||
{
|
||||
@ -40,22 +40,29 @@
|
||||
"trailingComma": "all"
|
||||
},
|
||||
"devDependencies": {
|
||||
"cross-env": "^7.0.3",
|
||||
"esbuild": "^0.11.2",
|
||||
"eslint-plugin-prettier": "^3.3.1",
|
||||
"@babel/preset-env": "^7.14.2",
|
||||
"@babel/preset-typescript": "^7.13.0",
|
||||
"@testing-library/jest-dom": "^5.12.0",
|
||||
"@testing-library/react": "^11.2.7",
|
||||
"@testing-library/react-hooks": "^7.0.0",
|
||||
"@types/jest": "^26.0.23",
|
||||
"@types/react": "^17.0.8",
|
||||
"@types/react-dom": "^17.0.5",
|
||||
"esbuild": "^0.12.3",
|
||||
"jest": "^27.0.1",
|
||||
"jest-marbles": "^2.5.1",
|
||||
"husky": "^4.3.7",
|
||||
"lint-staged": "^10.5.4",
|
||||
"prettier": "^2.2.1",
|
||||
"typescript": "^4.2.3",
|
||||
"prettier": "^2.3.0",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-test-renderer": "^17.0.2",
|
||||
"rxjs": "^7.1.0",
|
||||
"typescript": "^4.2.4",
|
||||
"ts-jest": "^27.0.1",
|
||||
"tslib": "^2.2.0",
|
||||
"wsrun": "^5.2.4"
|
||||
},
|
||||
"resolutions": {
|
||||
"**/@typescript-eslint/eslint-plugin": "^4.11.1",
|
||||
"**/@typescript-eslint/parser": "^4.11.1",
|
||||
"**/jest": "^26.6.3",
|
||||
"**/ts-jest": "^26.4.4",
|
||||
"**/typescript": "^4.2.3"
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{js,jsx,ts,tsx,json,md}": "prettier --write"
|
||||
},
|
||||
|
||||
21
packages/core/babel.config.js
Normal file
21
packages/core/babel.config.js
Normal file
@ -0,0 +1,21 @@
|
||||
// Only used by Jest
|
||||
module.exports = {
|
||||
presets: [
|
||||
[
|
||||
"@babel/preset-env",
|
||||
{ useBuiltIns: "entry", corejs: "2", targets: { node: "current" } },
|
||||
],
|
||||
"@babel/preset-typescript",
|
||||
],
|
||||
plugins: [
|
||||
function () {
|
||||
return {
|
||||
visitor: {
|
||||
MetaProperty(path) {
|
||||
path.replaceWithSourceString("process")
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
],
|
||||
}
|
||||
@ -1,7 +1,13 @@
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "jsdom",
|
||||
moduleNameMapper: {
|
||||
"^@/(.*)$": "<rootDir>/src/$1",
|
||||
},
|
||||
setupFilesAfterEnv: ["<rootDir>/setupTests.ts"],
|
||||
globals: {
|
||||
"ts-jest": {
|
||||
diagnostics: false,
|
||||
babelConfig: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -6,23 +6,25 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"exports": "dist/core.esm2019.js",
|
||||
"module": "dist/core.esm2017.js",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"exports": {
|
||||
"import": "./dist/core.es2019.mjs",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"module": "./dist/core.es2017.mjs",
|
||||
"main": "./dist/index.cjs",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "tsdx watch",
|
||||
"build": "yarn build:ts && yarn build:esm2017 && yarn build:esm2019 && yarn build:cjs:dev && yarn build:cjs:prod",
|
||||
"build:esm2019": "esbuild src/index.tsx --bundle --outfile=./dist/core.esm2019.js --target=es2019 --external:react --external:rxjs --format=esm --sourcemap",
|
||||
"build:esm2017": "esbuild src/index.tsx --bundle --outfile=./dist/core.esm2017.js --target=es2017 --external:react --external:rxjs --format=esm --sourcemap",
|
||||
"build:esm2019": "esbuild src/index.tsx --bundle --outfile=./dist/core.es2019.mjs --target=es2019 --external:react --external:rxjs --format=esm --sourcemap",
|
||||
"build:esm2017": "esbuild src/index.tsx --bundle --outfile=./dist/core.es2017.mjs --target=es2017 --external:react --external:rxjs --format=esm --sourcemap",
|
||||
"build:cjs:dev": "esbuild src/index.tsx --bundle --outfile=./dist/core.cjs.development.js --target=es2015 --external:react --external:rxjs --format=cjs --sourcemap",
|
||||
"build:cjs:prod": "esbuild src/index.tsx --bundle --outfile=./dist/core.cjs.production.min.js --target=es2015 --external:react --external:rxjs --format=cjs --minify --sourcemap",
|
||||
"build:ts": "tsc -p ./tsconfig.json --outDir ./dist --skipLibCheck --emitDeclarationOnly",
|
||||
"test": "tsdx test --coverage",
|
||||
"lint": "prettier --check README.md && tsdx lint src",
|
||||
"build:ts": "tsc -p ./tsconfig-build.json --outDir ./dist --skipLibCheck --emitDeclarationOnly",
|
||||
"test": "jest --coverage",
|
||||
"lint": "prettier --check README.md \"src/**/*.{js,jsx,ts,tsx,json,md}\"",
|
||||
"format": "prettier --write README.md \"src/**/*.{js,jsx,ts,tsx,json,md}\"",
|
||||
"prepare": "yarn build"
|
||||
},
|
||||
@ -39,22 +41,5 @@
|
||||
"authors": [
|
||||
"Josep M Sobrepere (https://github.com/josepot)",
|
||||
"Victor Oliva (https://github.com/voliva)"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@testing-library/react": "^11.2.6",
|
||||
"@testing-library/react-hooks": "^5.1.1",
|
||||
"@types/jest": "^26.0.22",
|
||||
"@types/react": "^17.0.3",
|
||||
"@types/react-dom": "^17.0.3",
|
||||
"esbuild": "^0.11.2",
|
||||
"jest-marbles": "^2.5.1",
|
||||
"lint-staged": "^10.5.4",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-test-renderer": "^17.0.2",
|
||||
"rxjs": "^6.6.7",
|
||||
"tsdx": "^0.14.1",
|
||||
"tslib": "^2.1.0",
|
||||
"typescript": "^4.2.3"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
5
packages/core/setupTests.ts
Normal file
5
packages/core/setupTests.ts
Normal file
@ -0,0 +1,5 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import "@testing-library/jest-dom"
|
||||
@ -46,9 +46,8 @@ export const Subscribe: React.FC<{
|
||||
subscriptionRef.current = new Subscription()
|
||||
}
|
||||
|
||||
const [subscribedSource, setSubscribedSource] = useState<
|
||||
Observable<any> | null | undefined
|
||||
>(null)
|
||||
const [subscribedSource, setSubscribedSource] =
|
||||
useState<Observable<any> | null | undefined>(null)
|
||||
|
||||
if (subscribedSource !== null && subscribedSource !== source$) {
|
||||
if (source$ === undefined) {
|
||||
|
||||
@ -9,7 +9,6 @@ import {
|
||||
merge,
|
||||
EMPTY,
|
||||
NEVER,
|
||||
noop,
|
||||
} from "rxjs"
|
||||
import { renderHook, act as actHook } from "@testing-library/react-hooks"
|
||||
import {
|
||||
@ -145,11 +144,9 @@ describe("connectFactoryObservable", () => {
|
||||
return from([1, 2, 3, 4, 5])
|
||||
})
|
||||
|
||||
const [
|
||||
useLatestNumber,
|
||||
latestNumber$,
|
||||
] = bind((id: number, value: { val: number }) =>
|
||||
concat(observable$, of(id + value.val)),
|
||||
const [useLatestNumber, latestNumber$] = bind(
|
||||
(id: number, value: { val: number }) =>
|
||||
concat(observable$, of(id + value.val)),
|
||||
)
|
||||
expect(subscriberCount).toBe(0)
|
||||
|
||||
@ -835,13 +832,15 @@ describe("connectFactoryObservable", () => {
|
||||
it("does not crash when the observable lazily references its enhanced self", () => {
|
||||
const [, obs$] = bind(
|
||||
(key: number) => defer(() => obs$(key)).pipe(take(1)),
|
||||
(key) => key,
|
||||
)
|
||||
(key: number) => key,
|
||||
) as [(key: number) => number, (key: number) => Observable<number>]
|
||||
|
||||
let error = null
|
||||
obs$(1)
|
||||
.subscribe(noop, (e: any) => {
|
||||
error = e
|
||||
.subscribe({
|
||||
error: (e: any) => {
|
||||
error = e
|
||||
},
|
||||
})
|
||||
.unsubscribe()
|
||||
|
||||
|
||||
@ -33,15 +33,15 @@ export default function connectFactoryObservable<A extends [], O>(
|
||||
(...args: A) => Observable<O>,
|
||||
] {
|
||||
const cache = new NestedMap<A, BehaviorObservable<O>>()
|
||||
const getDefaultValue = (typeof defaultValue === "function"
|
||||
? defaultValue
|
||||
: () => defaultValue) as (...args: A) => O
|
||||
const getDefaultValue = (
|
||||
typeof defaultValue === "function" ? defaultValue : () => defaultValue
|
||||
) as (...args: A) => O
|
||||
|
||||
const getSharedObservables$ = (input: A): BehaviorObservable<O> => {
|
||||
for (let i = input.length - 1; input[i] === undefined && i > -1; i--) {
|
||||
input.splice(-1)
|
||||
}
|
||||
const keys = ([input.length, ...input] as any) as A
|
||||
const keys = [input.length, ...input] as any as A
|
||||
const cachedVal = cache.get(keys)
|
||||
|
||||
if (cachedVal !== undefined) {
|
||||
|
||||
@ -224,7 +224,7 @@ describe("connectObservable", () => {
|
||||
})
|
||||
|
||||
it("suspends the component when the observable emits SUSPENSE", async () => {
|
||||
const subject$ = new Subject()
|
||||
const subject$ = new Subject<void>()
|
||||
const source$ = subject$.pipe(
|
||||
scan((a) => a + 1, 0),
|
||||
map((x) => {
|
||||
@ -264,7 +264,7 @@ describe("connectObservable", () => {
|
||||
})
|
||||
|
||||
it("keeps in suspense if more than two SUSPENSE are emitted in succesion", async () => {
|
||||
const subject$ = new Subject()
|
||||
const subject$ = new Subject<void>()
|
||||
const source$ = subject$.pipe(
|
||||
scan((a) => a + 1, 0),
|
||||
map((x) => {
|
||||
@ -308,7 +308,7 @@ describe("connectObservable", () => {
|
||||
})
|
||||
|
||||
it("correctly unsubscribes when the Subscribe component gets unmounted", async () => {
|
||||
const subject$ = new Subject()
|
||||
const subject$ = new Subject<void>()
|
||||
const [useNumber, number$] = bind(subject$.pipe(scan((a) => a + 1, 0)))
|
||||
|
||||
const Result: React.FC = () => <div>Result {useNumber()}</div>
|
||||
|
||||
@ -51,10 +51,9 @@ export function bind<A extends unknown[], O>(
|
||||
): [(...args: A) => Exclude<O, typeof SUSPENSE>, (...args: A) => Observable<O>]
|
||||
|
||||
export function bind(observable: any, defaultValue: any) {
|
||||
return (typeof observable === "function"
|
||||
? (connectFactoryObservable as any)
|
||||
: connectObservable)(
|
||||
observable,
|
||||
arguments.length > 1 ? defaultValue : EMPTY_VALUE,
|
||||
)
|
||||
return (
|
||||
typeof observable === "function"
|
||||
? (connectFactoryObservable as any)
|
||||
: connectObservable
|
||||
)(observable, arguments.length > 1 ? defaultValue : EMPTY_VALUE)
|
||||
}
|
||||
|
||||
@ -49,22 +49,22 @@ const shareLatest = <T>(
|
||||
subject = new Subject<T>()
|
||||
innerSub = subject.subscribe(subscriber)
|
||||
subscription = null
|
||||
subscription = new Subscriber<T>(
|
||||
(value: T) => {
|
||||
subscription = new Subscriber<T>({
|
||||
next: (value: T) => {
|
||||
subject!.next((currentValue = value))
|
||||
},
|
||||
(err: any) => {
|
||||
error: (err: any) => {
|
||||
const _subject = subject
|
||||
subscription = null
|
||||
subject = null
|
||||
_subject!.error(err)
|
||||
},
|
||||
() => {
|
||||
complete: () => {
|
||||
subscription = null
|
||||
emitIfEmpty()
|
||||
subject!.complete()
|
||||
},
|
||||
)
|
||||
})
|
||||
source$.subscribe(subscription)
|
||||
emitIfEmpty()
|
||||
} else {
|
||||
|
||||
@ -56,7 +56,7 @@ describe("shareLatest", () => {
|
||||
const values$ = hot('----b-c-d---')
|
||||
const latest$ = hot('----------x-')
|
||||
const expected = ' a---b-c-d-d-'
|
||||
const input$ = merge(
|
||||
const input$: any = merge(
|
||||
values$,
|
||||
latest$.pipe(
|
||||
withLatestFrom(defer(() => result$)),
|
||||
@ -64,7 +64,7 @@ describe("shareLatest", () => {
|
||||
)
|
||||
)
|
||||
|
||||
const result$ = input$.pipe(
|
||||
const result$: any = input$.pipe(
|
||||
startWith('a'),
|
||||
shareLatest()
|
||||
)
|
||||
|
||||
@ -16,6 +16,7 @@ import { EMPTY_VALUE } from "./internal/empty-value"
|
||||
* @remarks The enhanced observables returned from `connectObservable` and
|
||||
* `connectFactoryObservable` have been enhanced with this operator.
|
||||
*/
|
||||
export const shareLatest = <T>(): MonoTypeOperatorFunction<T> => (
|
||||
source$: Observable<T>,
|
||||
) => internalShareLatest(source$, EMPTY_VALUE)
|
||||
export const shareLatest =
|
||||
<T>(): MonoTypeOperatorFunction<T> =>
|
||||
(source$: Observable<T>) =>
|
||||
internalShareLatest(source$, EMPTY_VALUE)
|
||||
|
||||
4
packages/core/tsconfig-build.json
Normal file
4
packages/core/tsconfig-build.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["**/*.test.*", "**/test-helpers/*.*"]
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"include": ["src"],
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"lib": ["dom", "esnext"],
|
||||
"importHelpers": true,
|
||||
@ -26,6 +26,5 @@
|
||||
},
|
||||
"jsx": "react",
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"exclude": ["**/*.test.*", "**/test-helpers/*.*"]
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "jsdom",
|
||||
moduleNameMapper: {
|
||||
"^@/(.*)$": "<rootDir>/src/$1",
|
||||
},
|
||||
setupFilesAfterEnv: ["<rootDir>/setupTests.ts"],
|
||||
globals: {
|
||||
"ts-jest": {
|
||||
diagnostics: false,
|
||||
babelConfig: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -6,23 +6,26 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"exports": "dist/dom.esm2019.js",
|
||||
"module": "dist/dom.esm2017.js",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"exports": {
|
||||
"import": "./dist/dom.es2019.mjs",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"module": "./dist/dom.es2017.mjs",
|
||||
"main": "./dist/index.cjs",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "tsdx watch",
|
||||
"build": "yarn build:ts && yarn build:esm2017 && yarn build:esm2019 && yarn build:cjs:dev && yarn build:cjs:prod",
|
||||
"build:esm2019": "esbuild src/index.tsx --bundle --outfile=./dist/dom.esm2019.js --target=es2019 --external:react --external:rxjs --external:react-dom --format=esm --sourcemap",
|
||||
"build:esm2017": "esbuild src/index.tsx --bundle --outfile=./dist/dom.esm2017.js --target=es2017 --external:react --external:rxjs --external:react-dom --format=esm --sourcemap",
|
||||
"build:esm2019": "esbuild src/index.tsx --bundle --outfile=./dist/dom.es2019.mjs --target=es2019 --external:react --external:rxjs --external:react-dom --format=esm --sourcemap",
|
||||
"build:esm2017": "esbuild src/index.tsx --bundle --outfile=./dist/dom.es2017.mjs --target=es2017 --external:react --external:rxjs --external:react-dom --format=esm --sourcemap",
|
||||
"build:cjs:dev": "esbuild src/index.tsx --bundle --outfile=./dist/dom.cjs.development.js --target=es2015 --external:react --external:rxjs --external:react-dom --format=cjs --sourcemap",
|
||||
"build:cjs:prod": "esbuild src/index.tsx --bundle --outfile=./dist/dom.cjs.production.min.js --target=es2015 --external:react --external:rxjs --external:react-dom --format=cjs --minify --sourcemap",
|
||||
"build:ts": "tsc -p ./tsconfig.json --outDir ./dist --skipLibCheck --emitDeclarationOnly",
|
||||
"test": "tsdx test --coverage",
|
||||
"lint": "prettier --check README.md && tsdx lint src",
|
||||
"test": "jest --coverage",
|
||||
"lint": "prettier --check README.md \"src/**/*.{js,jsx,ts,tsx,json,md}\"",
|
||||
"format": "prettier --write README.md \"src/**/*.{js,jsx,ts,tsx,json,md}\"",
|
||||
"prepare": "yarn build"
|
||||
},
|
||||
@ -42,19 +45,6 @@
|
||||
"Victor Oliva (https://github.com/voliva)"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@react-rxjs/core": "0.8.0",
|
||||
"@testing-library/react": "^11.2.6",
|
||||
"@testing-library/react-hooks": "^5.1.1",
|
||||
"@types/jest": "^26.0.22",
|
||||
"@types/react": "^17.0.3",
|
||||
"@types/react-dom": "^17.0.3",
|
||||
"jest-marbles": "^2.5.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-test-renderer": "^17.0.2",
|
||||
"rxjs": "^6.6.7",
|
||||
"tsdx": "^0.14.1",
|
||||
"tslib": "^2.1.0",
|
||||
"typescript": "^4.2.3"
|
||||
"@react-rxjs/core": "0.8.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
packages/dom/setupTests.ts
Normal file
5
packages/dom/setupTests.ts
Normal file
@ -0,0 +1,5 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import "@testing-library/jest-dom"
|
||||
@ -12,31 +12,31 @@ import { unstable_batchedUpdates } from "react-dom"
|
||||
* automatically batches all synchronous updates. Meaning that with React CM,
|
||||
* observing a stream through the asapScheduler accomplishes the same thing.
|
||||
*/
|
||||
export const batchUpdates = <T>() => (
|
||||
source$: Observable<T>,
|
||||
): Observable<T> => {
|
||||
return new Observable<T>((observer) => {
|
||||
const obs = {
|
||||
n: (v: T) => observer.next(v),
|
||||
c: () => observer.complete(),
|
||||
e: (e: any) => observer.error(e),
|
||||
}
|
||||
let queue: ["n" | "c" | "e", any?][] = []
|
||||
let promise: Promise<void> | null = null
|
||||
const flush = () => {
|
||||
promise = null
|
||||
const originalQueue = queue
|
||||
queue = []
|
||||
unstable_batchedUpdates(() => {
|
||||
originalQueue.forEach(([prop, val]) => obs[prop](val))
|
||||
})
|
||||
}
|
||||
const push = (type: "n" | "c" | "e") => (val?: any) => {
|
||||
queue.push([type, val])
|
||||
if (!promise) {
|
||||
promise = Promise.resolve().then(flush)
|
||||
export const batchUpdates =
|
||||
<T>() =>
|
||||
(source$: Observable<T>): Observable<T> => {
|
||||
return new Observable<T>((observer) => {
|
||||
const obs = {
|
||||
n: (v: T) => observer.next(v),
|
||||
c: () => observer.complete(),
|
||||
e: (e: any) => observer.error(e),
|
||||
}
|
||||
}
|
||||
return source$.subscribe(push("n"), push("e"), push("c"))
|
||||
})
|
||||
}
|
||||
let queue: ["n" | "c" | "e", any?][] = []
|
||||
let promise: Promise<void> | null = null
|
||||
const flush = () => {
|
||||
promise = null
|
||||
const originalQueue = queue
|
||||
queue = []
|
||||
unstable_batchedUpdates(() => {
|
||||
originalQueue.forEach(([prop, val]) => obs[prop](val))
|
||||
})
|
||||
}
|
||||
const push = (type: "n" | "c" | "e") => (val?: any) => {
|
||||
queue.push([type, val])
|
||||
if (!promise) {
|
||||
promise = Promise.resolve().then(flush)
|
||||
}
|
||||
}
|
||||
return source$.subscribe(push("n"), push("e"), push("c"))
|
||||
})
|
||||
}
|
||||
|
||||
4
packages/dom/tsconfig-build.json
Normal file
4
packages/dom/tsconfig-build.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["**/*.test.*", "**/test-helpers/*.*"]
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"include": ["src"],
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"lib": ["dom", "esnext"],
|
||||
"importHelpers": true,
|
||||
@ -26,6 +26,5 @@
|
||||
},
|
||||
"jsx": "react",
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"exclude": ["**/*.test.ts"]
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,7 +1,13 @@
|
||||
module.exports = {
|
||||
preset: "ts-jest",
|
||||
testEnvironment: "jsdom",
|
||||
moduleNameMapper: {
|
||||
"^@/(.*)$": "<rootDir>/src/$1",
|
||||
},
|
||||
setupFilesAfterEnv: ["<rootDir>/setupTests.ts"],
|
||||
globals: {
|
||||
"ts-jest": {
|
||||
diagnostics: false,
|
||||
babelConfig: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
@ -6,23 +6,25 @@
|
||||
},
|
||||
"license": "MIT",
|
||||
"sideEffects": false,
|
||||
"exports": "dist/utils.esm2019.js",
|
||||
"module": "dist/utils.esm2017.js",
|
||||
"main": "dist/index.js",
|
||||
"typings": "dist/index.d.ts",
|
||||
"exports": {
|
||||
"import": "./dist/utils.es2019.mjs",
|
||||
"require": "./dist/index.cjs"
|
||||
},
|
||||
"module": "./dist/utils.es2017.mjs",
|
||||
"main": "./dist/index.cjs",
|
||||
"typings": "./dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"scripts": {
|
||||
"start": "tsdx watch",
|
||||
"build": "yarn build:ts && yarn build:esm2017 && yarn build:esm2019 && yarn build:cjs:dev && yarn build:cjs:prod",
|
||||
"build:esm2019": "esbuild src/index.tsx --bundle --outfile=./dist/utils.esm2019.js --target=es2019 --external:react --external:rxjs --external:@react-rxjs/core --format=esm --sourcemap",
|
||||
"build:esm2017": "esbuild src/index.tsx --bundle --outfile=./dist/utils.esm2017.js --target=es2017 --external:react --external:rxjs --external:@react-rxjs/core --format=esm --sourcemap",
|
||||
"build:esm2019": "esbuild src/index.tsx --bundle --outfile=./dist/utils.es2019.mjs --target=es2019 --external:react --external:rxjs --external:@react-rxjs/core --format=esm --sourcemap",
|
||||
"build:esm2017": "esbuild src/index.tsx --bundle --outfile=./dist/utils.es2017.mjs --target=es2017 --external:react --external:rxjs --external:@react-rxjs/core --format=esm --sourcemap",
|
||||
"build:cjs:dev": "esbuild src/index.tsx --bundle --outfile=./dist/utils.cjs.development.js --target=es2015 --external:react --external:rxjs --external:@react-rxjs/core --format=cjs --sourcemap",
|
||||
"build:cjs:prod": "esbuild src/index.tsx --bundle --outfile=./dist/utils.cjs.production.min.js --target=es2015 --external:react --external:rxjs --external:@react-rxjs/core --format=cjs --minify --sourcemap",
|
||||
"build:ts": "tsc -p ./tsconfig.json --outDir ./dist --skipLibCheck --emitDeclarationOnly",
|
||||
"test": "tsdx test --coverage",
|
||||
"lint": "prettier --check README.md && tsdx lint src",
|
||||
"build:ts": "tsc -p ./tsconfig-build.json --outDir ./dist --skipLibCheck --emitDeclarationOnly",
|
||||
"test": "jest --coverage",
|
||||
"lint": "prettier --check README.md \"src/**/*.{js,jsx,ts,tsx,json,md}\"",
|
||||
"format": "prettier --write README.md \"src/**/*.{js,jsx,ts,tsx,json,md}\"",
|
||||
"prepare": "yarn build"
|
||||
},
|
||||
@ -42,19 +44,6 @@
|
||||
"Victor Oliva (https://github.com/voliva)"
|
||||
],
|
||||
"devDependencies": {
|
||||
"@react-rxjs/core": "0.8.0",
|
||||
"@testing-library/react": "^11.2.6",
|
||||
"@testing-library/react-hooks": "^5.1.1",
|
||||
"@types/jest": "^26.0.22",
|
||||
"@types/react": "^17.0.3",
|
||||
"@types/react-dom": "^17.0.3",
|
||||
"jest-marbles": "^2.5.1",
|
||||
"react": "^17.0.2",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-test-renderer": "^17.0.2",
|
||||
"rxjs": "^6.6.7",
|
||||
"tsdx": "^0.14.1",
|
||||
"tslib": "^2.1.0",
|
||||
"typescript": "^4.2.3"
|
||||
"@react-rxjs/core": "0.8.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
5
packages/utils/setupTests.ts
Normal file
5
packages/utils/setupTests.ts
Normal file
@ -0,0 +1,5 @@
|
||||
// jest-dom adds custom jest matchers for asserting on DOM nodes.
|
||||
// allows you to do things like:
|
||||
// expect(element).toHaveTextContent(/react/i)
|
||||
// learn more: https://github.com/testing-library/jest-dom
|
||||
import "@testing-library/jest-dom"
|
||||
@ -16,7 +16,7 @@ describe("collect", () => {
|
||||
string,
|
||||
string
|
||||
>
|
||||
result.key = key
|
||||
;(result as any).key = key
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@ -11,14 +11,16 @@ const scheduler = () =>
|
||||
describe("combineKeys", () => {
|
||||
it("emits a map with the latest value of the stream of each key", () => {
|
||||
scheduler().run(({ expectObservable, cold }) => {
|
||||
const keys = cold(" ab---cd---").pipe(scan((acc, v) => [...acc, v], []))
|
||||
const keys = cold(" ab---cd---").pipe(
|
||||
scan((acc, v) => [...acc, v], [] as Array<string>),
|
||||
)
|
||||
const a = cold(" --1---2---")
|
||||
const b = cold(" ---------")
|
||||
const c = cold(" 1----")
|
||||
const d = cold(" 9---")
|
||||
const expectedStr = "--e--f(gh)"
|
||||
|
||||
const innerStreams = { a, b, c, d }
|
||||
const innerStreams: Record<string, Observable<string>> = { a, b, c, d }
|
||||
|
||||
const result = combineKeys(
|
||||
keys,
|
||||
@ -36,14 +38,16 @@ describe("combineKeys", () => {
|
||||
|
||||
it("doesn't emit if the inner value hasn't changed", () => {
|
||||
scheduler().run(({ expectObservable, cold }) => {
|
||||
const keys = cold(" ab---cd---").pipe(scan((acc, v) => [...acc, v], []))
|
||||
const keys = cold(" ab---cd---").pipe(
|
||||
scan((acc, v) => [...acc, v], [] as Array<string>),
|
||||
)
|
||||
const a = cold(" --11112---")
|
||||
const b = cold(" ---------")
|
||||
const c = cold(" 1----")
|
||||
const d = cold(" 9---")
|
||||
const expectedStr = "--e--f(gh)"
|
||||
|
||||
const innerStreams = { a, b, c, d }
|
||||
const innerStreams: Record<string, Observable<string>> = { a, b, c, d }
|
||||
|
||||
const result = combineKeys(
|
||||
keys,
|
||||
@ -67,7 +71,7 @@ describe("combineKeys", () => {
|
||||
const c = cold(" ---5")
|
||||
const expectedStr = "e--f"
|
||||
|
||||
const innerStreams = { a, b, c }
|
||||
const innerStreams: Record<string, Observable<string>> = { a, b, c }
|
||||
|
||||
const result = combineKeys(
|
||||
keys,
|
||||
@ -89,7 +93,7 @@ describe("combineKeys", () => {
|
||||
const c = cold(" -2-3")
|
||||
const expectedStr = "---e-fgh-i"
|
||||
|
||||
const innerStreams = { a, b, c }
|
||||
const innerStreams: Record<string, Observable<string>> = { a, b, c }
|
||||
|
||||
const result = combineKeys(
|
||||
keys,
|
||||
@ -108,12 +112,14 @@ describe("combineKeys", () => {
|
||||
|
||||
it("completes when the key stream completes", () => {
|
||||
scheduler().run(({ expectObservable, cold }) => {
|
||||
const keys = cold(" a-b---|").pipe(scan((acc, v) => [...acc, v], []))
|
||||
const keys = cold(" a-b---|").pipe(
|
||||
scan((acc, v) => [...acc, v], [] as Array<string>),
|
||||
)
|
||||
const a = cold(" -1-----")
|
||||
const b = cold(" -1---")
|
||||
const expectedStr = "-e-f--|"
|
||||
|
||||
const innerStreams = { a, b }
|
||||
const innerStreams: Record<string, Observable<string>> = { a, b }
|
||||
|
||||
const result = combineKeys(
|
||||
keys,
|
||||
@ -129,12 +135,14 @@ describe("combineKeys", () => {
|
||||
|
||||
it("propagates errors from the inner streams", () => {
|
||||
scheduler().run(({ expectObservable, cold }) => {
|
||||
const keys = cold(" a-b---|").pipe(scan((acc, v) => [...acc, v], []))
|
||||
const keys = cold(" a-b---|").pipe(
|
||||
scan((acc, v) => [...acc, v], [] as Array<string>),
|
||||
)
|
||||
const a = cold(" -1-----")
|
||||
const b = cold(" -#")
|
||||
const expectedStr = "-e-#"
|
||||
|
||||
const innerStreams = { a, b }
|
||||
const innerStreams: Record<string, Observable<string>> = { a, b }
|
||||
|
||||
const result = combineKeys(
|
||||
keys,
|
||||
@ -149,12 +157,14 @@ describe("combineKeys", () => {
|
||||
|
||||
it("propagates errors from the key stream", () => {
|
||||
scheduler().run(({ expectObservable, cold }) => {
|
||||
const keys = cold(" a-b#").pipe(scan((acc, v) => [...acc, v], []))
|
||||
const keys = cold(" a-b#").pipe(
|
||||
scan((acc, v) => [...acc, v], [] as Array<string>),
|
||||
)
|
||||
const a = cold(" -1--")
|
||||
const b = cold(" -1")
|
||||
const expectedStr = "-e-#"
|
||||
|
||||
const innerStreams = { a, b }
|
||||
const innerStreams: Record<string, Observable<string>> = { a, b }
|
||||
|
||||
const result = combineKeys(
|
||||
keys,
|
||||
@ -180,7 +190,7 @@ describe("combineKeys", () => {
|
||||
const b = cold(" 2---")
|
||||
const expectedStr = "efgef"
|
||||
|
||||
const innerStreams = { a, b }
|
||||
const innerStreams: Record<string, Observable<string>> = { a, b }
|
||||
|
||||
const result = combineKeys(
|
||||
keys,
|
||||
|
||||
@ -19,7 +19,7 @@ export function contextBinder<
|
||||
A extends (() => any)[],
|
||||
OT extends {
|
||||
[K in keyof A]: A[K] extends () => infer V ? V : unknown
|
||||
}
|
||||
},
|
||||
>(
|
||||
...args: A
|
||||
): <AA extends any[], T, ARGS extends [...OT, ...AA]>(
|
||||
|
||||
@ -72,7 +72,7 @@ export function createKeyedSignal<K, T, A extends any[]>(
|
||||
}
|
||||
}
|
||||
}) as GroupedObservable<K, T>
|
||||
res.key = key
|
||||
;(res as any).key = key
|
||||
return res
|
||||
},
|
||||
(...args: A) => {
|
||||
|
||||
@ -17,7 +17,7 @@ describe("getGroupedObservable", () => {
|
||||
string,
|
||||
string
|
||||
>
|
||||
result.key = key
|
||||
;(result as any).key = key
|
||||
return result
|
||||
}
|
||||
|
||||
|
||||
@ -22,6 +22,6 @@ export const getGroupedObservable = <K, T>(
|
||||
outterSub.unsubscribe()
|
||||
}
|
||||
}) as GroupedObservable<K, T>
|
||||
result.key = key
|
||||
;(result as any).key = key
|
||||
return result
|
||||
}
|
||||
|
||||
@ -1,69 +1,73 @@
|
||||
import { Observable, GroupedObservable, Subscription } from "rxjs"
|
||||
import { shareLatest } from "@react-rxjs/core"
|
||||
|
||||
export const defaultStart = <T, D>(value: D) => (source$: Observable<T>) =>
|
||||
new Observable<T | D>((observer) => {
|
||||
let emitted = false
|
||||
const subscription = source$.subscribe(
|
||||
(x) => {
|
||||
emitted = true
|
||||
observer.next(x)
|
||||
},
|
||||
(e) => {
|
||||
observer.error(e)
|
||||
},
|
||||
() => {
|
||||
observer.complete()
|
||||
},
|
||||
)
|
||||
|
||||
if (!emitted) {
|
||||
observer.next(value)
|
||||
}
|
||||
|
||||
return subscription
|
||||
})
|
||||
|
||||
export const collector = <K, V, VV>(
|
||||
enhancer: (source: GroupedObservable<K, V>) => Observable<VV>,
|
||||
): ((
|
||||
source: Observable<GroupedObservable<K, V>>,
|
||||
) => Observable<Map<K, VV>>) => (source$) =>
|
||||
new Observable<Map<K, VV>>((observer) => {
|
||||
const subscription = new Subscription()
|
||||
const map = new Map<K, VV>()
|
||||
let emitted = false
|
||||
|
||||
subscription.add(
|
||||
source$.subscribe(
|
||||
export const defaultStart =
|
||||
<T, D>(value: D) =>
|
||||
(source$: Observable<T>) =>
|
||||
new Observable<T | D>((observer) => {
|
||||
let emitted = false
|
||||
const subscription = source$.subscribe(
|
||||
(x) => {
|
||||
subscription.add(
|
||||
enhancer(x).subscribe(
|
||||
(v) => {
|
||||
map.set(x.key, v)
|
||||
emitted = true
|
||||
observer.next(map)
|
||||
},
|
||||
(e) => {
|
||||
observer.error(e)
|
||||
},
|
||||
() => {
|
||||
map.delete(x.key)
|
||||
observer.next(map)
|
||||
},
|
||||
),
|
||||
)
|
||||
emitted = true
|
||||
observer.next(x)
|
||||
},
|
||||
(e) => {
|
||||
observer.error(e)
|
||||
},
|
||||
() => {
|
||||
map.clear()
|
||||
observer.next(map)
|
||||
observer.complete()
|
||||
},
|
||||
),
|
||||
)
|
||||
if (!emitted) observer.next(map)
|
||||
return subscription
|
||||
}).pipe(shareLatest())
|
||||
)
|
||||
|
||||
if (!emitted) {
|
||||
observer.next(value)
|
||||
}
|
||||
|
||||
return subscription
|
||||
})
|
||||
|
||||
export const collector =
|
||||
<K, V, VV>(
|
||||
enhancer: (source: GroupedObservable<K, V>) => Observable<VV>,
|
||||
): ((
|
||||
source: Observable<GroupedObservable<K, V>>,
|
||||
) => Observable<Map<K, VV>>) =>
|
||||
(source$) =>
|
||||
new Observable<Map<K, VV>>((observer) => {
|
||||
const subscription = new Subscription()
|
||||
const map = new Map<K, VV>()
|
||||
let emitted = false
|
||||
|
||||
subscription.add(
|
||||
source$.subscribe(
|
||||
(x) => {
|
||||
subscription.add(
|
||||
enhancer(x).subscribe(
|
||||
(v) => {
|
||||
map.set(x.key, v)
|
||||
emitted = true
|
||||
observer.next(map)
|
||||
},
|
||||
(e) => {
|
||||
observer.error(e)
|
||||
},
|
||||
() => {
|
||||
map.delete(x.key)
|
||||
observer.next(map)
|
||||
},
|
||||
),
|
||||
)
|
||||
},
|
||||
(e) => {
|
||||
observer.error(e)
|
||||
},
|
||||
() => {
|
||||
map.clear()
|
||||
observer.next(map)
|
||||
observer.complete()
|
||||
},
|
||||
),
|
||||
)
|
||||
if (!emitted) observer.next(map)
|
||||
return subscription
|
||||
}).pipe(shareLatest())
|
||||
|
||||
@ -13,13 +13,13 @@ export const mergeWithKey: <
|
||||
[K in keyof O]: O[K] extends ObservableInput<infer V>
|
||||
? { type: K; payload: V }
|
||||
: unknown
|
||||
}
|
||||
},
|
||||
>(
|
||||
x: O,
|
||||
concurrent?: number,
|
||||
scheduler?: SchedulerLike,
|
||||
) => Observable<OT[keyof O]> = (input, ...optionalArgs) =>
|
||||
merge(
|
||||
merge<any[]>(
|
||||
...(Object.entries(input)
|
||||
.map(
|
||||
([type, stream]) =>
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
import { NEVER, Subject } from "rxjs"
|
||||
import { NEVER, Observable, Subject } from "rxjs"
|
||||
import { switchMap, take } from "rxjs/operators"
|
||||
import { TestScheduler } from "rxjs/testing"
|
||||
import { partitionByKey } from "./"
|
||||
@ -37,7 +37,7 @@ describe("partitionByKey", () => {
|
||||
const b = cold(" ---|")
|
||||
const c = cold(" 1-|")
|
||||
const expectedStr = "efg--hi-j"
|
||||
const innerStreams = { a, b, c }
|
||||
const innerStreams: Record<string, Observable<any>> = { a, b, c }
|
||||
const [, result] = partitionByKey(
|
||||
source,
|
||||
(v) => v,
|
||||
@ -71,7 +71,7 @@ describe("partitionByKey", () => {
|
||||
const expectB = " -----|"
|
||||
const expectC = " ------1-|"
|
||||
|
||||
const innerStreams = { a, b, c }
|
||||
const innerStreams: Record<string, Observable<any>> = { a, b, c }
|
||||
const [getInstance$] = partitionByKey(
|
||||
source,
|
||||
(v) => v,
|
||||
|
||||
@ -55,11 +55,13 @@ export function split<T, K, R>(
|
||||
: new ReplaySubject<T>(1)
|
||||
groups.set(key, subject)
|
||||
|
||||
const res = (streamSelector
|
||||
? streamSelector(subject, key).pipe(shareReplay(1))
|
||||
: subject.asObservable()) as GroupedObservable<K, R>
|
||||
const res = (
|
||||
streamSelector
|
||||
? streamSelector(subject, key).pipe(shareReplay(1))
|
||||
: subject.asObservable()
|
||||
) as GroupedObservable<K, R>
|
||||
|
||||
res.key = key
|
||||
;(res as any).key = key
|
||||
const onFinish = () => groups.delete(key)
|
||||
res.subscribe(noop, onFinish, onFinish)
|
||||
|
||||
|
||||
4
packages/utils/tsconfig-build.json
Normal file
4
packages/utils/tsconfig-build.json
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["**/*.test.*", "**/test-helpers/*.*"]
|
||||
}
|
||||
@ -1,7 +1,7 @@
|
||||
{
|
||||
"include": ["src"],
|
||||
"compilerOptions": {
|
||||
"target": "es5",
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"lib": ["dom", "esnext"],
|
||||
"importHelpers": true,
|
||||
@ -26,6 +26,5 @@
|
||||
},
|
||||
"jsx": "react",
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"exclude": ["**/*.test.*"]
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user