Version 1.0.2 mit node_modules Verzeichnis

This commit is contained in:
ISA
2024-10-02 07:58:24 +02:00
parent f353a06b1b
commit 62b6e55a0a
68228 changed files with 4548477 additions and 651 deletions

View File

@@ -0,0 +1,110 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* Implements (a subset of) the interface of built-in Map but supports arrays as
* keys. Two keys are equal if corresponding elements are equal according to the
* equality semantics of built-in Map. Operations are at worst O(n*b) where n is
* the array length and b is the complexity of the built-in operation.
*
* @flow
* @format
* @oncall recoil
*/
'use strict';
const LEAF = {};
const emptyMap = new Map<mixed, mixed>();
class ArrayKeyedMap<V> {
_base: Map<any, any> = new Map();
constructor(
existing?: ArrayKeyedMap<V> | Iterable<[mixed, V]>,
// $FlowFixMe[incompatible-return]
): ArrayKeyedMap<V> {
if (existing instanceof ArrayKeyedMap) {
for (const [k, v] of existing.entries()) {
this.set(k, v);
}
} else if (existing) {
for (const [k, v] of existing) {
this.set(k, v);
}
}
return this;
}
get(key: mixed): V | void {
const ks = Array.isArray(key) ? key : [key];
let map = this._base;
ks.forEach(k => {
map = map.get(k) ?? emptyMap;
});
return map === undefined ? undefined : map.get(LEAF);
}
set(key: mixed, value: V): any {
const ks = Array.isArray(key) ? key : [key];
let map: ?(any | Map<mixed, mixed> | Map<any, any>) = this._base;
let next: ?(any | Map<mixed, mixed> | Map<any, any>) = map;
ks.forEach(k => {
// $FlowFixMe[incompatible-use]
next = map.get(k);
if (!next) {
next = new Map();
// $FlowFixMe[incompatible-use]
map.set(k, next);
}
map = next;
});
// $FlowFixMe[incompatible-use]
next.set(LEAF, value);
return this;
}
delete(key: mixed): any {
const ks = Array.isArray(key) ? key : [key];
let map: ?(any | Map<mixed, mixed> | Map<any, any>) = this._base;
let next: ?(any | Map<mixed, mixed> | Map<any, any>) = map;
ks.forEach(k => {
// $FlowFixMe[incompatible-use]
next = map.get(k);
if (!next) {
next = new Map();
// $FlowFixMe[incompatible-use]
map.set(k, next);
}
map = next;
});
// $FlowFixMe[incompatible-use]
next.delete(LEAF);
// TODO We could cleanup empty maps
return this;
}
entries(): Iterator<[$ReadOnlyArray<mixed>, V]> {
const answer = [];
function recurse(level: any | Map<any, any>, prefix: Array<mixed>) {
level.forEach((v, k) => {
if (k === LEAF) {
answer.push([prefix, v]);
} else {
recurse(v, prefix.concat(k));
}
});
}
recurse(this._base, []);
return answer.values();
}
toBuiltInMap(): Map<$ReadOnlyArray<mixed>, V> {
return new Map(this.entries());
}
}
module.exports = {ArrayKeyedMap};

313
node_modules/recoil/cjs/adt/Recoil_Loadable.js.flow generated vendored Normal file
View File

@@ -0,0 +1,313 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* A type that represents a value that may or may not be loaded. It differs from
* LoadObject in that the `loading` state has a Promise that is meant to resolve
* when the value is available (but as with LoadObject, an individual Loadable
* is a value type and is not mutated when the status of a request changes).
*
* @flow strict
* @format
* @oncall recoil
*/
'use strict';
const err = require('recoil-shared/util/Recoil_err');
const isPromise = require('recoil-shared/util/Recoil_isPromise');
const nullthrows = require('recoil-shared/util/Recoil_nullthrows');
class BaseLoadable<T> {
getValue(): T {
throw err('BaseLoadable');
}
toPromise(): Promise<T> {
throw err('BaseLoadable');
}
valueMaybe(): T | void {
throw err('BaseLoadable');
}
valueOrThrow(): T {
// $FlowFixMe[prop-missing]
throw err(`Loadable expected value, but in "${this.state}" state`);
}
promiseMaybe(): Promise<T> | void {
throw err('BaseLoadable');
}
promiseOrThrow(): Promise<T> {
// $FlowFixMe[prop-missing]
throw err(`Loadable expected promise, but in "${this.state}" state`);
}
errorMaybe(): mixed | void {
throw err('BaseLoadable');
}
errorOrThrow(): mixed {
// $FlowFixMe[prop-missing]
throw err(`Loadable expected error, but in "${this.state}" state`);
}
is(other: Loadable<mixed>): boolean {
// $FlowFixMe[prop-missing]
return other.state === this.state && other.contents === this.contents;
}
map<S>(_map: T => Promise<S> | Loadable<S> | S): Loadable<S> {
throw err('BaseLoadable');
}
}
class ValueLoadable<T> extends BaseLoadable<T> {
state: 'hasValue' = 'hasValue';
contents: T;
constructor(value: T) {
super();
this.contents = value;
}
getValue(): T {
return this.contents;
}
toPromise(): Promise<T> {
return Promise.resolve(this.contents);
}
valueMaybe(): T {
return this.contents;
}
valueOrThrow(): T {
return this.contents;
}
promiseMaybe(): void {
return undefined;
}
errorMaybe(): void {
return undefined;
}
map<S>(map: T => Promise<S> | Loadable<S> | S): Loadable<S> {
try {
const next = map(this.contents);
return isPromise(next)
? loadableWithPromise(next)
: isLoadable(next)
? next
: loadableWithValue(next);
} catch (e) {
return isPromise(e)
? // If we "suspended", then try again.
// errors and subsequent retries will be handled in 'loading' case
// $FlowFixMe[prop-missing]
loadableWithPromise(e.next(() => this.map(map)))
: loadableWithError(e);
}
}
}
class ErrorLoadable<T> extends BaseLoadable<T> {
state: 'hasError' = 'hasError';
contents: mixed;
constructor(error: mixed) {
super();
this.contents = error;
}
getValue(): T {
throw this.contents;
}
toPromise(): Promise<T> {
return Promise.reject(this.contents);
}
valueMaybe(): void {
return undefined;
}
promiseMaybe(): void {
return undefined;
}
errorMaybe(): mixed {
return this.contents;
}
errorOrThrow(): mixed {
return this.contents;
}
map<S>(_map: T => Promise<S> | Loadable<S> | S): $ReadOnly<ErrorLoadable<S>> {
// $FlowIssue[incompatible-return]
return this;
}
}
class LoadingLoadable<T> extends BaseLoadable<T> {
state: 'loading' = 'loading';
contents: Promise<T>;
constructor(promise: Promise<T>) {
super();
this.contents = promise;
}
getValue(): T {
throw this.contents;
}
toPromise(): Promise<T> {
return this.contents;
}
valueMaybe(): void {
return undefined;
}
promiseMaybe(): Promise<T> {
return this.contents;
}
promiseOrThrow(): Promise<T> {
return this.contents;
}
errorMaybe(): void {
return undefined;
}
map<S>(
map: T => Promise<S> | Loadable<S> | S,
): $ReadOnly<LoadingLoadable<S>> {
return loadableWithPromise(
this.contents
.then(value => {
const next = map(value);
if (isLoadable(next)) {
const nextLoadable: Loadable<S> = next;
switch (nextLoadable.state) {
case 'hasValue':
return nextLoadable.contents;
case 'hasError':
throw nextLoadable.contents;
case 'loading':
return nextLoadable.contents;
}
}
// $FlowIssue[incompatible-return]
return next;
})
// $FlowFixMe[incompatible-call]
.catch(e => {
if (isPromise(e)) {
// we were "suspended," try again
return e.then(() => this.map(map).contents);
}
throw e;
}),
);
}
}
export type Loadable<+T> =
| $ReadOnly<ValueLoadable<T>>
| $ReadOnly<ErrorLoadable<T>>
| $ReadOnly<LoadingLoadable<T>>;
export type ValueLoadableType<+T> = $ReadOnly<ValueLoadable<T>>;
export type ErrorLoadableType<+T> = $ReadOnly<ErrorLoadable<T>>;
export type LoadingLoadableType<+T> = $ReadOnly<LoadingLoadable<T>>;
function loadableWithValue<+T>(value: T): $ReadOnly<ValueLoadable<T>> {
return Object.freeze(new ValueLoadable(value));
}
function loadableWithError<+T>(error: mixed): $ReadOnly<ErrorLoadable<T>> {
return Object.freeze(new ErrorLoadable(error));
}
function loadableWithPromise<+T>(
promise: Promise<T>,
): $ReadOnly<LoadingLoadable<T>> {
return Object.freeze(new LoadingLoadable(promise));
}
function loadableLoading<+T>(): $ReadOnly<LoadingLoadable<T>> {
return Object.freeze(new LoadingLoadable(new Promise(() => {})));
}
type UnwrapLoadables<Loadables> = $TupleMap<Loadables, <T>(Loadable<T>) => T>;
type LoadableAllOfTuple = <
Tuple: $ReadOnlyArray<Loadable<mixed> | Promise<mixed> | mixed>,
>(
tuple: Tuple,
) => Loadable<$TupleMap<Tuple, <V>(Loadable<V> | Promise<V> | V) => V>>;
type LoadableAllOfObj = <
Obj: $ReadOnly<{[string]: Loadable<mixed> | Promise<mixed> | mixed, ...}>,
>(
obj: Obj,
) => Loadable<$ObjMap<Obj, <V>(Loadable<V> | Promise<V> | V) => V>>;
type LoadableAll = LoadableAllOfTuple & LoadableAllOfObj;
function loadableAllArray<Inputs: $ReadOnlyArray<Loadable<mixed>>>(
inputs: Inputs,
): Loadable<UnwrapLoadables<Inputs>> {
return inputs.every(i => i.state === 'hasValue')
? loadableWithValue(inputs.map(i => i.contents))
: inputs.some(i => i.state === 'hasError')
? loadableWithError(
nullthrows(
inputs.find(i => i.state === 'hasError'),
'Invalid loadable passed to loadableAll',
).contents,
)
: loadableWithPromise(Promise.all(inputs.map(i => i.contents)));
}
function loadableAll<
Inputs:
| $ReadOnlyArray<Loadable<mixed> | Promise<mixed> | mixed>
| $ReadOnly<{[string]: Loadable<mixed> | Promise<mixed> | mixed, ...}>,
>(
inputs: Inputs,
): Loadable<$ReadOnlyArray<mixed> | $ReadOnly<{[string]: mixed, ...}>> {
const unwrapedInputs = Array.isArray(inputs)
? inputs
: Object.getOwnPropertyNames(inputs).map(key => inputs[key]);
const normalizedInputs = unwrapedInputs.map(x =>
isLoadable(x)
? x
: isPromise(x)
? loadableWithPromise(x)
: loadableWithValue(x),
);
const output = loadableAllArray(normalizedInputs);
return Array.isArray(inputs)
? // $FlowIssue[incompatible-return]
output
: // Object.getOwnPropertyNames() has consistent key ordering with ES6
// $FlowIssue[incompatible-call]
output.map(outputs =>
Object.getOwnPropertyNames(inputs).reduce(
// $FlowFixMe[invalid-computed-prop]
(out, key, idx) => ({...out, [key]: outputs[idx]}),
{},
),
);
}
function isLoadable(x: mixed): boolean %checks {
return x instanceof BaseLoadable;
}
const LoadableStaticInterface = {
of: <T>(value: Promise<T> | Loadable<T> | T): Loadable<T> =>
isPromise(value)
? loadableWithPromise(value)
: isLoadable(value)
? value
: loadableWithValue(value),
error: <T>(error: mixed): $ReadOnly<ErrorLoadable<T>> =>
loadableWithError(error),
// $FlowIssue[incompatible-return]
loading: <T>(): LoadingLoadable<T> => loadableLoading<T>(),
// $FlowIssue[unclear-type]
all: ((loadableAll: any): LoadableAll),
isLoadable,
};
module.exports = {
loadableWithValue,
loadableWithError,
loadableWithPromise,
loadableLoading,
loadableAll,
isLoadable,
RecoilLoadable: LoadableStaticInterface,
};

View File

@@ -0,0 +1,142 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
* @oncall recoil
*/
'use strict';
import type {HAMTPlusMap} from 'hamt_plus';
const hamt = require('hamt_plus');
const gkx = require('recoil-shared/util/Recoil_gkx');
export interface PersistentMap<K: string, V> {
keys(): Iterable<K>;
entries(): Iterable<[K, V]>;
get(key: K): V | void;
has(key: K): boolean;
set(key: K, value: V): PersistentMap<K, V>;
delete(key: K): PersistentMap<K, V>;
clone(): PersistentMap<K, V>;
toMap(): Map<K, V>;
}
class BuiltInMap<K: string, V> implements PersistentMap<K, V> {
_map: Map<K, V>;
constructor(existing?: PersistentMap<K, V>) {
this._map = new Map(existing?.entries());
}
keys(): Iterable<K> {
return this._map.keys();
}
entries(): Iterable<[K, V]> {
return this._map.entries();
}
get(k: K): V | void {
return this._map.get(k);
}
has(k: K): boolean {
return this._map.has(k);
}
set(k: K, v: V): PersistentMap<K, V> {
this._map.set(k, v);
return this;
}
delete(k: K): PersistentMap<K, V> {
this._map.delete(k);
return this;
}
clone(): PersistentMap<K, V> {
return persistentMap(this);
}
toMap(): Map<K, V> {
return new Map(this._map);
}
}
class HashArrayMappedTrieMap<K: string, V> implements PersistentMap<K, V> {
// Because hamt.empty is not a function there is no way to introduce type
// parameters on it, so empty is typed as HAMTPlusMap<string, mixed>.
// $FlowIssue
_hamt: HAMTPlusMap<K, V> = ((hamt.empty: any).beginMutation(): HAMTPlusMap<
K,
V,
>);
constructor(existing?: PersistentMap<K, V>) {
if (existing instanceof HashArrayMappedTrieMap) {
const h = existing._hamt.endMutation();
existing._hamt = h.beginMutation();
this._hamt = h.beginMutation();
} else if (existing) {
for (const [k, v] of existing.entries()) {
this._hamt.set(k, v);
}
}
}
keys(): Iterable<K> {
return this._hamt.keys();
}
entries(): Iterable<[K, V]> {
return this._hamt.entries();
}
get(k: K): V | void {
return this._hamt.get(k);
}
has(k: K): boolean {
return this._hamt.has(k);
}
set(k: K, v: V): PersistentMap<K, V> {
this._hamt.set(k, v);
return this;
}
delete(k: K): PersistentMap<K, V> {
this._hamt.delete(k);
return this;
}
clone(): PersistentMap<K, V> {
return persistentMap(this);
}
toMap(): Map<K, V> {
return new Map(this._hamt);
}
}
function persistentMap<K: string, V>(
existing?: PersistentMap<K, V>,
): PersistentMap<K, V> {
if (gkx('recoil_hamt_2020')) {
return new HashArrayMappedTrieMap(existing);
} else {
return new BuiltInMap(existing);
}
}
module.exports = {
persistentMap,
};

20
node_modules/recoil/cjs/adt/Recoil_Queue.js.flow generated vendored Normal file
View File

@@ -0,0 +1,20 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict
* @format
* @oncall recoil
*/
'use strict';
function enqueueExecution(s: string, f: () => mixed) {
f();
}
module.exports = {
enqueueExecution,
};

22
node_modules/recoil/cjs/adt/Recoil_Wrapper.js.flow generated vendored Normal file
View File

@@ -0,0 +1,22 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall recoil
*/
'use strict';
class WrappedValue<T> {
value: T;
constructor(value: T) {
this.value = value;
}
}
module.exports = {
WrappedValue,
};

View File

@@ -0,0 +1,50 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall recoil
*/
'use strict';
const {ArrayKeyedMap} = require('../Recoil_ArrayKeyedMap');
test('basic operation', () => {
const m = new ArrayKeyedMap<number>();
m.set([], 0);
m.set(['a'], 1);
m.set(['a', 'b'], 2);
expect(m.get([])).toBe(0);
expect(m.get(['a'])).toBe(1);
expect(m.get(['a', 'b'])).toBe(2);
});
test('enumeration of properties', () => {
const m = new ArrayKeyedMap<number>();
m.set([], 0);
m.set(['a'], 1);
m.set(['a', 'b'], 2);
const entries = Array.from(m.entries());
expect(entries[0][0]).toEqual([]);
expect(entries[0][1]).toBe(0);
expect(entries[1][0]).toEqual(['a']);
expect(entries[1][1]).toBe(1);
expect(entries[2][0]).toEqual(['a', 'b']);
expect(entries[2][1]).toBe(2);
});
test('copying', () => {
const m = new ArrayKeyedMap<number | $FlowFixMe>();
m.set([], 0);
m.set(['a'], 1);
m.set(['a', 'b'], 2);
const mm = new ArrayKeyedMap(m);
expect(mm.get([])).toBe(0);
expect(mm.get(['a'])).toBe(1);
expect(mm.get(['a', 'b'])).toBe(2);
expect(Array.from(m.entries())).toEqual(Array.from(mm.entries()));
});

View File

@@ -0,0 +1,281 @@
/**
* Copyright (c) Meta Platforms, Inc. and affiliates.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*
* @flow strict-local
* @format
* @oncall recoil
*/
'use strict';
const {
RecoilLoadable,
loadableWithError,
loadableWithPromise,
loadableWithValue,
} = require('../Recoil_Loadable');
const ERROR = new Error('ERROR');
test('Value Loadable', async () => {
const loadable = loadableWithValue('VALUE');
expect(loadable.state).toBe('hasValue');
expect(loadable.contents).toBe('VALUE');
expect(loadable.getValue()).toBe('VALUE');
await expect(loadable.toPromise()).resolves.toBe('VALUE');
expect(loadable.valueMaybe()).toBe('VALUE');
expect(loadable.valueOrThrow()).toBe('VALUE');
expect(loadable.errorMaybe()).toBe(undefined);
expect(() => loadable.errorOrThrow()).toThrow();
expect(loadable.promiseMaybe()).toBe(undefined);
expect(() => loadable.promiseOrThrow()).toThrow();
});
test('Error Loadable', async () => {
const loadable = loadableWithError<$FlowFixMe>(ERROR);
expect(loadable.state).toBe('hasError');
expect(loadable.contents).toBe(ERROR);
expect(() => loadable.getValue()).toThrow(ERROR);
await expect(loadable.toPromise()).rejects.toBe(ERROR);
expect(loadable.valueMaybe()).toBe(undefined);
expect(() => loadable.valueOrThrow()).toThrow();
expect(loadable.errorMaybe()).toBe(ERROR);
expect(loadable.errorOrThrow()).toBe(ERROR);
expect(loadable.promiseMaybe()).toBe(undefined);
expect(() => loadable.promiseOrThrow()).toThrow();
});
test('Pending Value Loadable', async () => {
const promise = Promise.resolve('VALUE');
const loadable = loadableWithPromise(promise);
expect(loadable.state).toBe('loading');
expect(loadable.contents).toBe(promise);
expect(() => loadable.getValue()).toThrow();
await expect(loadable.toPromise()).resolves.toBe('VALUE');
expect(loadable.valueMaybe()).toBe(undefined);
expect(() => loadable.valueOrThrow()).toThrow();
expect(loadable.errorMaybe()).toBe(undefined);
expect(() => loadable.errorOrThrow()).toThrow();
await expect(loadable.promiseMaybe()).resolves.toBe('VALUE');
await expect(loadable.promiseOrThrow()).resolves.toBe('VALUE');
});
describe('Loadable mapping', () => {
test('Loadable mapping value', () => {
const loadable = loadableWithValue('VALUE').map(x => 'MAPPED ' + x);
expect(loadable.state).toBe('hasValue');
expect(loadable.contents).toBe('MAPPED VALUE');
});
test('Loadable mapping value to error', () => {
const loadable = loadableWithValue('VALUE').map<$FlowFixMe>(() => {
throw ERROR;
});
expect(loadable.state).toBe('hasError');
expect(loadable.contents).toBe(ERROR);
});
test('Loadable mapping value to Promise', async () => {
const loadable = loadableWithValue('VALUE').map(value =>
Promise.resolve('MAPPED ' + value),
);
expect(loadable.state).toBe('loading');
await expect(loadable.toPromise()).resolves.toBe('MAPPED VALUE');
});
test('Loadable mapping value to reject', async () => {
const loadable = loadableWithValue('VALUE').map(() =>
Promise.reject(ERROR),
);
expect(loadable.state).toBe('loading');
await expect(loadable.toPromise()).rejects.toBe(ERROR);
});
test('Loadable mapping error', () => {
const loadable = loadableWithError<mixed>(ERROR).map(() => 'NOT_USED');
expect(loadable.state).toBe('hasError');
expect(loadable.contents).toBe(ERROR);
});
test('Loadable mapping promise value', async () => {
const loadable = loadableWithPromise(Promise.resolve('VALUE')).map(
x => 'MAPPED ' + x,
);
expect(loadable.state).toBe('loading');
await expect(loadable.toPromise()).resolves.toBe('MAPPED VALUE');
});
test('Loadable mapping promise value to reject', async () => {
const loadable = loadableWithPromise(Promise.resolve('VALUE')).map(() =>
Promise.reject(ERROR),
);
expect(loadable.state).toBe('loading');
await expect(loadable.toPromise()).rejects.toBe(ERROR);
});
test('Loadable mapping promise value to error', async () => {
const loadable = loadableWithPromise(Promise.resolve('VALUE')).map<mixed>(
() => {
throw ERROR;
},
);
expect(loadable.state).toBe('loading');
await expect(loadable.toPromise()).rejects.toBe(ERROR);
});
test('Loadable mapping promise error', async () => {
const loadable = loadableWithPromise(Promise.reject(ERROR)).map(
() => 'NOT_USED',
);
expect(loadable.state).toBe('loading');
await expect(loadable.toPromise()).rejects.toBe(ERROR);
});
test('Loadable mapping to loadable', () => {
const loadable = loadableWithValue('VALUE').map(value =>
loadableWithValue(value),
);
expect(loadable.state).toBe('hasValue');
expect(loadable.contents).toBe('VALUE');
});
test('Loadable mapping promise to loadable value', async () => {
const loadable = loadableWithPromise(Promise.resolve('VALUE')).map(value =>
loadableWithValue('MAPPED ' + value),
);
expect(loadable.state).toBe('loading');
await expect(loadable.toPromise()).resolves.toBe('MAPPED VALUE');
});
test('Loadable mapping promise to loadable error', async () => {
const loadable = loadableWithPromise(Promise.resolve('VALUE')).map(() =>
// $FlowFixMe[underconstrained-implicit-instantiation]
loadableWithError(ERROR),
);
expect(loadable.state).toBe('loading');
await expect(loadable.toPromise()).rejects.toBe(ERROR);
});
test('Loadable mapping promise to loadable promise', async () => {
const loadable = loadableWithPromise(Promise.resolve('VALUE')).map(value =>
loadableWithPromise(Promise.resolve('MAPPED ' + value)),
);
expect(loadable.state).toBe('loading');
await expect(loadable.toPromise()).resolves.toBe('MAPPED VALUE');
});
});
test('Loadable Factory Interface', async () => {
const valueLoadable = RecoilLoadable.of('VALUE');
expect(valueLoadable.state).toBe('hasValue');
expect(valueLoadable.contents).toBe('VALUE');
const valueLoadable2 = RecoilLoadable.of(RecoilLoadable.of('VALUE'));
expect(valueLoadable2.state).toBe('hasValue');
expect(valueLoadable2.contents).toBe('VALUE');
const promiseLoadable = RecoilLoadable.of(Promise.resolve('ASYNC'));
expect(promiseLoadable.state).toBe('loading');
await expect(promiseLoadable.contents).resolves.toBe('ASYNC');
const promiseLoadable2 = RecoilLoadable.of(
RecoilLoadable.of(Promise.resolve('ASYNC')),
);
expect(promiseLoadable2.state).toBe('loading');
await expect(promiseLoadable2.contents).resolves.toBe('ASYNC');
const errorLoadable = RecoilLoadable.error<mixed>('ERROR');
expect(errorLoadable.state).toBe('hasError');
expect(errorLoadable.contents).toBe('ERROR');
// $FlowFixMe[underconstrained-implicit-instantiation]
const errorLoadable2 = RecoilLoadable.of(RecoilLoadable.error('ERROR'));
expect(errorLoadable2.state).toBe('hasError');
expect(errorLoadable2.contents).toBe('ERROR');
const loadingLoadable = RecoilLoadable.loading<mixed>();
expect(loadingLoadable.state).toBe('loading');
});
describe('Loadable All', () => {
test('Array', async () => {
expect(
RecoilLoadable.all([RecoilLoadable.of('x'), RecoilLoadable.of(123)])
.contents,
).toEqual(['x', 123]);
await expect(
RecoilLoadable.all([
RecoilLoadable.of(Promise.resolve('x')),
RecoilLoadable.of(123),
]).contents,
).resolves.toEqual(['x', 123]);
expect(
RecoilLoadable.all([
RecoilLoadable.of('x'),
RecoilLoadable.of(123),
// $FlowFixMe[underconstrained-implicit-instantiation]
RecoilLoadable.error('ERROR'),
]).contents,
).toEqual('ERROR');
expect(
RecoilLoadable.all([
RecoilLoadable.of('x'),
RecoilLoadable.all([RecoilLoadable.of(1), RecoilLoadable.of(2)]),
]).contents,
).toEqual(['x', [1, 2]]);
});
test('Object', async () => {
expect(
RecoilLoadable.all({
str: RecoilLoadable.of('x'),
num: RecoilLoadable.of(123),
}).contents,
).toEqual({
str: 'x',
num: 123,
});
await expect(
RecoilLoadable.all({
str: RecoilLoadable.of(Promise.resolve('x')),
num: RecoilLoadable.of(123),
}).contents,
).resolves.toEqual({
str: 'x',
num: 123,
});
expect(
RecoilLoadable.all({
str: RecoilLoadable.of('x'),
num: RecoilLoadable.of(123),
// $FlowFixMe[underconstrained-implicit-instantiation]
err: RecoilLoadable.error('ERROR'),
}).contents,
).toEqual('ERROR');
});
test('mixed values', async () => {
expect(RecoilLoadable.all([RecoilLoadable.of('A'), 'B']).contents).toEqual([
'A',
'B',
]);
await expect(
RecoilLoadable.all([RecoilLoadable.of('A'), Promise.resolve('B')])
.contents,
).resolves.toEqual(['A', 'B']);
await expect(
RecoilLoadable.all([RecoilLoadable.of('A'), Promise.reject('B')])
.contents,
).rejects.toEqual('B');
await expect(
RecoilLoadable.all({
a: 'A',
b: RecoilLoadable.of('B'),
c: Promise.resolve('C'),
}).contents,
).resolves.toEqual({a: 'A', b: 'B', c: 'C'});
});
});