@depup/reduxjs__toolkit 2.12.0-depup.28
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/LICENSE +21 -0
- package/README.md +33 -0
- package/changes.json +18 -0
- package/dist/cjs/index.js +6 -0
- package/dist/cjs/redux-toolkit.development.cjs +2406 -0
- package/dist/cjs/redux-toolkit.development.cjs.map +1 -0
- package/dist/cjs/redux-toolkit.production.min.cjs +3 -0
- package/dist/cjs/redux-toolkit.production.min.cjs.map +1 -0
- package/dist/index.d.mts +2665 -0
- package/dist/index.d.ts +2665 -0
- package/dist/query/cjs/index.js +6 -0
- package/dist/query/cjs/rtk-query.development.cjs +3092 -0
- package/dist/query/cjs/rtk-query.development.cjs.map +1 -0
- package/dist/query/cjs/rtk-query.production.min.cjs +2 -0
- package/dist/query/cjs/rtk-query.production.min.cjs.map +1 -0
- package/dist/query/index.d.mts +3066 -0
- package/dist/query/index.d.ts +3066 -0
- package/dist/query/react/cjs/index.js +6 -0
- package/dist/query/react/cjs/rtk-query-react.development.cjs +748 -0
- package/dist/query/react/cjs/rtk-query-react.development.cjs.map +1 -0
- package/dist/query/react/cjs/rtk-query-react.production.min.cjs +2 -0
- package/dist/query/react/cjs/rtk-query-react.production.min.cjs.map +1 -0
- package/dist/query/react/index.d.mts +1009 -0
- package/dist/query/react/index.d.ts +1009 -0
- package/dist/query/react/rtk-query-react.browser.mjs +2 -0
- package/dist/query/react/rtk-query-react.browser.mjs.map +1 -0
- package/dist/query/react/rtk-query-react.legacy-esm.js +740 -0
- package/dist/query/react/rtk-query-react.legacy-esm.js.map +1 -0
- package/dist/query/react/rtk-query-react.modern.mjs +705 -0
- package/dist/query/react/rtk-query-react.modern.mjs.map +1 -0
- package/dist/query/rtk-query.browser.mjs +2 -0
- package/dist/query/rtk-query.browser.mjs.map +1 -0
- package/dist/query/rtk-query.legacy-esm.js +3117 -0
- package/dist/query/rtk-query.legacy-esm.js.map +1 -0
- package/dist/query/rtk-query.modern.mjs +3052 -0
- package/dist/query/rtk-query.modern.mjs.map +1 -0
- package/dist/react/cjs/index.js +6 -0
- package/dist/react/cjs/redux-toolkit-react.development.cjs +55 -0
- package/dist/react/cjs/redux-toolkit-react.development.cjs.map +1 -0
- package/dist/react/cjs/redux-toolkit-react.production.min.cjs +2 -0
- package/dist/react/cjs/redux-toolkit-react.production.min.cjs.map +1 -0
- package/dist/react/index.d.mts +22 -0
- package/dist/react/index.d.ts +22 -0
- package/dist/react/redux-toolkit-react.browser.mjs +2 -0
- package/dist/react/redux-toolkit-react.browser.mjs.map +1 -0
- package/dist/react/redux-toolkit-react.legacy-esm.js +47 -0
- package/dist/react/redux-toolkit-react.legacy-esm.js.map +1 -0
- package/dist/react/redux-toolkit-react.modern.mjs +28 -0
- package/dist/react/redux-toolkit-react.modern.mjs.map +1 -0
- package/dist/redux-toolkit.browser.mjs +3 -0
- package/dist/redux-toolkit.browser.mjs.map +1 -0
- package/dist/redux-toolkit.legacy-esm.js +2351 -0
- package/dist/redux-toolkit.legacy-esm.js.map +1 -0
- package/dist/redux-toolkit.modern.mjs +2330 -0
- package/dist/redux-toolkit.modern.mjs.map +1 -0
- package/dist/uncheckedindexed.ts +16 -0
- package/package.json +310 -0
- package/query/package.json +13 -0
- package/query/react/package.json +13 -0
- package/react/package.json +13 -0
- package/skills/build-modern-redux-apps/modern-redux/SKILL.md +304 -0
- package/skills/build-modern-redux-apps/modern-redux/references/store-lifetime.md +53 -0
- package/skills/build-modern-redux-apps/redux-dataflow/SKILL.md +264 -0
- package/skills/evolve-and-diagnose-redux-apps/debug-redux-toolkit-apps/SKILL.md +269 -0
- package/skills/evolve-and-diagnose-redux-apps/migrate-to-modern-redux/SKILL.md +226 -0
- package/skills/manage-server-data/adopt-rtk-query/SKILL.md +385 -0
- package/skills/manage-server-data/adopt-rtk-query/references/endpoint-lifecycle.md +36 -0
- package/skills/model-redux-state/build-slices-and-selectors/SKILL.md +364 -0
- package/skills/model-redux-state/build-slices-and-selectors/references/slice-patterns.md +59 -0
- package/skills/model-redux-state/design-state-ownership/SKILL.md +322 -0
- package/skills/model-redux-state/design-state-ownership/references/state-ownership.md +28 -0
- package/skills/orchestrate-side-effects/handle-side-effects/SKILL.md +271 -0
- package/skills/orchestrate-side-effects/handle-side-effects/references/listener-workflows.md +34 -0
- package/src/actionCreatorInvariantMiddleware.ts +34 -0
- package/src/autoBatchEnhancer.ts +146 -0
- package/src/combineSlices.ts +487 -0
- package/src/configureStore.ts +248 -0
- package/src/createAction.ts +324 -0
- package/src/createAsyncThunk.ts +791 -0
- package/src/createDraftSafeSelector.ts +30 -0
- package/src/createReducer.ts +217 -0
- package/src/createSlice.ts +1079 -0
- package/src/devtoolsExtension.ts +241 -0
- package/src/dynamicMiddleware/index.ts +93 -0
- package/src/dynamicMiddleware/react/index.ts +101 -0
- package/src/dynamicMiddleware/types.ts +82 -0
- package/src/entities/create_adapter.ts +47 -0
- package/src/entities/entity_state.ts +38 -0
- package/src/entities/index.ts +8 -0
- package/src/entities/models.ts +198 -0
- package/src/entities/sorted_state_adapter.ts +266 -0
- package/src/entities/state_adapter.ts +58 -0
- package/src/entities/state_selectors.ts +73 -0
- package/src/entities/unsorted_state_adapter.ts +204 -0
- package/src/entities/utils.ts +68 -0
- package/src/formatProdErrorMessage.ts +13 -0
- package/src/getDefaultEnhancers.ts +31 -0
- package/src/getDefaultMiddleware.ts +113 -0
- package/src/immerImports.ts +7 -0
- package/src/immutableStateInvariantMiddleware.ts +274 -0
- package/src/index.ts +213 -0
- package/src/listenerMiddleware/exceptions.ts +20 -0
- package/src/listenerMiddleware/index.ts +562 -0
- package/src/listenerMiddleware/task.ts +100 -0
- package/src/listenerMiddleware/types.ts +886 -0
- package/src/listenerMiddleware/utils.ts +30 -0
- package/src/mapBuilders.ts +298 -0
- package/src/matchers.ts +365 -0
- package/src/nanoid.ts +20 -0
- package/src/query/HandledError.ts +6 -0
- package/src/query/apiTypes.ts +120 -0
- package/src/query/baseQueryTypes.ts +101 -0
- package/src/query/core/apiState.ts +377 -0
- package/src/query/core/buildInitiate.ts +596 -0
- package/src/query/core/buildMiddleware/batchActions.ts +207 -0
- package/src/query/core/buildMiddleware/cacheCollection.ts +204 -0
- package/src/query/core/buildMiddleware/cacheLifecycle.ts +379 -0
- package/src/query/core/buildMiddleware/devMiddleware.ts +34 -0
- package/src/query/core/buildMiddleware/index.ts +162 -0
- package/src/query/core/buildMiddleware/invalidationByTags.ts +139 -0
- package/src/query/core/buildMiddleware/polling.ts +187 -0
- package/src/query/core/buildMiddleware/queryLifecycle.ts +508 -0
- package/src/query/core/buildMiddleware/types.ts +173 -0
- package/src/query/core/buildMiddleware/windowEventHandling.ts +64 -0
- package/src/query/core/buildSelectors.ts +413 -0
- package/src/query/core/buildSlice.ts +735 -0
- package/src/query/core/buildThunks.ts +1124 -0
- package/src/query/core/index.ts +58 -0
- package/src/query/core/module.ts +727 -0
- package/src/query/core/rtkImports.ts +24 -0
- package/src/query/core/setupListeners.ts +118 -0
- package/src/query/createApi.ts +506 -0
- package/src/query/defaultSerializeQueryArgs.ts +52 -0
- package/src/query/endpointDefinitions.ts +1717 -0
- package/src/query/fakeBaseQuery.ts +21 -0
- package/src/query/fetchBaseQuery.ts +385 -0
- package/src/query/index.ts +105 -0
- package/src/query/react/ApiProvider.tsx +69 -0
- package/src/query/react/buildHooks.ts +2297 -0
- package/src/query/react/constants.ts +2 -0
- package/src/query/react/index.ts +45 -0
- package/src/query/react/module.ts +275 -0
- package/src/query/react/namedHooks.ts +59 -0
- package/src/query/react/reactImports.ts +10 -0
- package/src/query/react/reactReduxImports.ts +1 -0
- package/src/query/react/rtkqImports.ts +8 -0
- package/src/query/react/useSerializedStableValue.ts +17 -0
- package/src/query/react/useShallowStableValue.ts +13 -0
- package/src/query/retry.ts +233 -0
- package/src/query/standardSchema.ts +35 -0
- package/src/query/tsHelpers.ts +48 -0
- package/src/query/utils/capitalize.ts +3 -0
- package/src/query/utils/copyWithStructuralSharing.ts +27 -0
- package/src/query/utils/countObjectKeys.ts +14 -0
- package/src/query/utils/filterMap.ts +27 -0
- package/src/query/utils/getCurrent.ts +6 -0
- package/src/query/utils/getOrInsert.ts +41 -0
- package/src/query/utils/immerImports.ts +9 -0
- package/src/query/utils/index.ts +11 -0
- package/src/query/utils/isAbsoluteUrl.ts +9 -0
- package/src/query/utils/isDocumentVisible.ts +12 -0
- package/src/query/utils/isNotNullish.ts +7 -0
- package/src/query/utils/isOnline.ts +12 -0
- package/src/query/utils/isValidUrl.ts +9 -0
- package/src/query/utils/joinUrls.ts +26 -0
- package/src/query/utils/signals.ts +33 -0
- package/src/react/index.ts +7 -0
- package/src/reduxImports.ts +8 -0
- package/src/reselectImports.ts +1 -0
- package/src/serializableStateInvariantMiddleware.ts +285 -0
- package/src/tsHelpers.ts +214 -0
- package/src/uncheckedindexed.ts +16 -0
- package/src/utils.ts +125 -0
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from '@standard-schema/spec'
|
|
2
|
+
import { SchemaError } from '@standard-schema/utils'
|
|
3
|
+
import type { SchemaType } from './endpointDefinitions'
|
|
4
|
+
|
|
5
|
+
export class NamedSchemaError extends SchemaError {
|
|
6
|
+
constructor(
|
|
7
|
+
issues: readonly StandardSchemaV1.Issue[],
|
|
8
|
+
public readonly value: any,
|
|
9
|
+
public readonly schemaName: `${SchemaType}Schema`,
|
|
10
|
+
public readonly _bqMeta: any,
|
|
11
|
+
) {
|
|
12
|
+
super(issues)
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export const shouldSkip = (
|
|
17
|
+
skipSchemaValidation: boolean | SchemaType[] | undefined,
|
|
18
|
+
schemaName: SchemaType,
|
|
19
|
+
) =>
|
|
20
|
+
Array.isArray(skipSchemaValidation)
|
|
21
|
+
? skipSchemaValidation.includes(schemaName)
|
|
22
|
+
: !!skipSchemaValidation
|
|
23
|
+
|
|
24
|
+
export async function parseWithSchema<Schema extends StandardSchemaV1>(
|
|
25
|
+
schema: Schema,
|
|
26
|
+
data: unknown,
|
|
27
|
+
schemaName: `${SchemaType}Schema`,
|
|
28
|
+
bqMeta: any,
|
|
29
|
+
): Promise<StandardSchemaV1.InferOutput<Schema>> {
|
|
30
|
+
const result = await schema['~standard'].validate(data)
|
|
31
|
+
if (result.issues) {
|
|
32
|
+
throw new NamedSchemaError(result.issues, data, schemaName, bqMeta)
|
|
33
|
+
}
|
|
34
|
+
return result.value
|
|
35
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
export type Id<T> = { [K in keyof T]: T[K] } & {}
|
|
2
|
+
export type WithRequiredProp<T, K extends keyof T> = Omit<T, K> &
|
|
3
|
+
Required<Pick<T, K>>
|
|
4
|
+
export type Override<T1, T2> = T2 extends any ? Omit<T1, keyof T2> & T2 : never
|
|
5
|
+
export function assertCast<T>(v: any): asserts v is T {}
|
|
6
|
+
|
|
7
|
+
export function safeAssign<T extends object>(
|
|
8
|
+
target: T,
|
|
9
|
+
...args: Array<Partial<NoInfer<T>>>
|
|
10
|
+
): T {
|
|
11
|
+
return Object.assign(target, ...args)
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Convert a Union type `(A|B)` to an intersection type `(A&B)`
|
|
16
|
+
*/
|
|
17
|
+
export type UnionToIntersection<U> = (
|
|
18
|
+
U extends any ? (k: U) => void : never
|
|
19
|
+
) extends (k: infer I) => void
|
|
20
|
+
? I
|
|
21
|
+
: never
|
|
22
|
+
|
|
23
|
+
export type NonOptionalKeys<T> = {
|
|
24
|
+
[K in keyof T]-?: undefined extends T[K] ? never : K
|
|
25
|
+
}[keyof T]
|
|
26
|
+
|
|
27
|
+
export type HasRequiredProps<T, True, False> =
|
|
28
|
+
NonOptionalKeys<T> extends never ? False : True
|
|
29
|
+
|
|
30
|
+
export type OptionalIfAllPropsOptional<T> = HasRequiredProps<T, T, T | never>
|
|
31
|
+
|
|
32
|
+
export type NonUndefined<T> = T extends undefined ? never : T
|
|
33
|
+
|
|
34
|
+
export type UnwrapPromise<T> = T extends PromiseLike<infer V> ? V : T
|
|
35
|
+
|
|
36
|
+
export type MaybePromise<T> = T | PromiseLike<T>
|
|
37
|
+
|
|
38
|
+
export type OmitFromUnion<T, K extends keyof T> = T extends any
|
|
39
|
+
? Omit<T, K>
|
|
40
|
+
: never
|
|
41
|
+
|
|
42
|
+
export type IsAny<T, True, False = never> = true | false extends (
|
|
43
|
+
T extends never ? true : false
|
|
44
|
+
)
|
|
45
|
+
? True
|
|
46
|
+
: False
|
|
47
|
+
|
|
48
|
+
export type CastAny<T, CastTo> = IsAny<T, CastTo, T>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { isPlainObject as _iPO } from '../core/rtkImports'
|
|
2
|
+
|
|
3
|
+
// remove type guard
|
|
4
|
+
const isPlainObject: (_: any) => boolean = _iPO
|
|
5
|
+
|
|
6
|
+
export function copyWithStructuralSharing<T>(oldObj: any, newObj: T): T
|
|
7
|
+
export function copyWithStructuralSharing(oldObj: any, newObj: any): any {
|
|
8
|
+
if (
|
|
9
|
+
oldObj === newObj ||
|
|
10
|
+
!(
|
|
11
|
+
(isPlainObject(oldObj) && isPlainObject(newObj)) ||
|
|
12
|
+
(Array.isArray(oldObj) && Array.isArray(newObj))
|
|
13
|
+
)
|
|
14
|
+
) {
|
|
15
|
+
return newObj
|
|
16
|
+
}
|
|
17
|
+
const newKeys = Object.keys(newObj)
|
|
18
|
+
const oldKeys = Object.keys(oldObj)
|
|
19
|
+
|
|
20
|
+
let isSameObject = newKeys.length === oldKeys.length
|
|
21
|
+
const mergeObj: any = Array.isArray(newObj) ? [] : {}
|
|
22
|
+
for (const key of newKeys) {
|
|
23
|
+
mergeObj[key] = copyWithStructuralSharing(oldObj[key], newObj[key])
|
|
24
|
+
if (isSameObject) isSameObject = oldObj[key] === mergeObj[key]
|
|
25
|
+
}
|
|
26
|
+
return isSameObject ? oldObj : mergeObj
|
|
27
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
// Fast method for counting an object's keys
|
|
2
|
+
// without resorting to `Object.keys(obj).length
|
|
3
|
+
// Will this make a big difference in perf? Probably not
|
|
4
|
+
// But we can save a few allocations.
|
|
5
|
+
|
|
6
|
+
export function countObjectKeys(obj: Record<any, any>) {
|
|
7
|
+
let count = 0
|
|
8
|
+
|
|
9
|
+
for (const _key in obj) {
|
|
10
|
+
count++
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
return count
|
|
14
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
// Preserve type guard predicate behavior when passing to mapper
|
|
2
|
+
export function filterMap<T, U, S extends T = T>(
|
|
3
|
+
array: readonly T[],
|
|
4
|
+
predicate: (item: T, index: number) => item is S,
|
|
5
|
+
mapper: (item: S, index: number) => U | U[],
|
|
6
|
+
): U[]
|
|
7
|
+
|
|
8
|
+
export function filterMap<T, U>(
|
|
9
|
+
array: readonly T[],
|
|
10
|
+
predicate: (item: T, index: number) => boolean,
|
|
11
|
+
mapper: (item: T, index: number) => U | U[],
|
|
12
|
+
): U[]
|
|
13
|
+
|
|
14
|
+
export function filterMap<T, U>(
|
|
15
|
+
array: readonly T[],
|
|
16
|
+
predicate: (item: T, index: number) => boolean,
|
|
17
|
+
mapper: (item: T, index: number) => U | U[],
|
|
18
|
+
): U[] {
|
|
19
|
+
return array
|
|
20
|
+
.reduce<(U | U[])[]>((acc, item, i) => {
|
|
21
|
+
if (predicate(item as any, i)) {
|
|
22
|
+
acc.push(mapper(item as any, i))
|
|
23
|
+
}
|
|
24
|
+
return acc
|
|
25
|
+
}, [])
|
|
26
|
+
.flat() as U[]
|
|
27
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Duplicate some of the utils in `/src/utils` to ensure
|
|
2
|
+
// we don't end up dragging in larger chunks of the RTK core
|
|
3
|
+
// into the RTKQ bundle
|
|
4
|
+
|
|
5
|
+
export function getOrInsert<K extends object, V>(
|
|
6
|
+
map: WeakMap<K, V>,
|
|
7
|
+
key: K,
|
|
8
|
+
value: V,
|
|
9
|
+
): V
|
|
10
|
+
export function getOrInsert<K, V>(map: Map<K, V>, key: K, value: V): V
|
|
11
|
+
export function getOrInsert<K extends object, V>(
|
|
12
|
+
map: Map<K, V> | WeakMap<K, V>,
|
|
13
|
+
key: K,
|
|
14
|
+
value: V,
|
|
15
|
+
): V {
|
|
16
|
+
if (map.has(key)) return map.get(key) as V
|
|
17
|
+
|
|
18
|
+
return map.set(key, value).get(key) as V
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function getOrInsertComputed<K extends object, V>(
|
|
22
|
+
map: WeakMap<K, V>,
|
|
23
|
+
key: K,
|
|
24
|
+
compute: (key: K) => V,
|
|
25
|
+
): V
|
|
26
|
+
export function getOrInsertComputed<K, V>(
|
|
27
|
+
map: Map<K, V>,
|
|
28
|
+
key: K,
|
|
29
|
+
compute: (key: K) => V,
|
|
30
|
+
): V
|
|
31
|
+
export function getOrInsertComputed<K extends object, V>(
|
|
32
|
+
map: Map<K, V> | WeakMap<K, V>,
|
|
33
|
+
key: K,
|
|
34
|
+
compute: (key: K) => V,
|
|
35
|
+
): V {
|
|
36
|
+
if (map.has(key)) return map.get(key) as V
|
|
37
|
+
|
|
38
|
+
return map.set(key, compute(key)).get(key) as V
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export const createNewMap = () => new Map()
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export * from './capitalize'
|
|
2
|
+
export * from './copyWithStructuralSharing'
|
|
3
|
+
export * from './countObjectKeys'
|
|
4
|
+
export * from './filterMap'
|
|
5
|
+
export * from './isAbsoluteUrl'
|
|
6
|
+
export * from './isDocumentVisible'
|
|
7
|
+
export * from './isNotNullish'
|
|
8
|
+
export * from './isOnline'
|
|
9
|
+
export * from './isValidUrl'
|
|
10
|
+
export * from './joinUrls'
|
|
11
|
+
export * from './getOrInsert'
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assumes true for a non-browser env, otherwise makes a best effort
|
|
3
|
+
* @link https://developer.mozilla.org/en-US/docs/Web/API/Document/visibilityState
|
|
4
|
+
*/
|
|
5
|
+
export function isDocumentVisible(): boolean {
|
|
6
|
+
// `document` may not exist in non-browser envs (like RN)
|
|
7
|
+
if (typeof document === 'undefined') {
|
|
8
|
+
return true
|
|
9
|
+
}
|
|
10
|
+
// Match true for visible, prerender, undefined
|
|
11
|
+
return document.visibilityState !== 'hidden'
|
|
12
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assumes a browser is online if `undefined`, otherwise makes a best effort
|
|
3
|
+
* @link https://developer.mozilla.org/en-US/docs/Web/API/NavigatorOnLine/onLine
|
|
4
|
+
*/
|
|
5
|
+
export function isOnline() {
|
|
6
|
+
// We set the default config value in the store, so we'd need to check for this in a SSR env
|
|
7
|
+
return typeof navigator === 'undefined'
|
|
8
|
+
? true
|
|
9
|
+
: navigator.onLine === undefined
|
|
10
|
+
? true
|
|
11
|
+
: navigator.onLine
|
|
12
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { isAbsoluteUrl } from './isAbsoluteUrl'
|
|
2
|
+
|
|
3
|
+
const withoutTrailingSlash = (url: string) => url.replace(/\/$/, '')
|
|
4
|
+
const withoutLeadingSlash = (url: string) => url.replace(/^\//, '')
|
|
5
|
+
|
|
6
|
+
export function joinUrls(
|
|
7
|
+
base: string | undefined,
|
|
8
|
+
url: string | undefined,
|
|
9
|
+
): string {
|
|
10
|
+
if (!base) {
|
|
11
|
+
return url!
|
|
12
|
+
}
|
|
13
|
+
if (!url) {
|
|
14
|
+
return base
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
if (isAbsoluteUrl(url)) {
|
|
18
|
+
return url
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const delimiter = base.endsWith('/') || !url.startsWith('?') ? '/' : ''
|
|
22
|
+
base = withoutTrailingSlash(base)
|
|
23
|
+
url = withoutLeadingSlash(url)
|
|
24
|
+
|
|
25
|
+
return `${base}${delimiter}${url}`
|
|
26
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
// AbortSignal.timeout() is currently baseline 2024
|
|
2
|
+
export const timeoutSignal = (milliseconds: number) => {
|
|
3
|
+
const abortController = new AbortController()
|
|
4
|
+
setTimeout(() => {
|
|
5
|
+
const message = 'signal timed out'
|
|
6
|
+
const name = 'TimeoutError'
|
|
7
|
+
abortController.abort(
|
|
8
|
+
// some environments (React Native, Node) don't have DOMException
|
|
9
|
+
typeof DOMException !== 'undefined'
|
|
10
|
+
? new DOMException(message, name)
|
|
11
|
+
: Object.assign(new Error(message), { name }),
|
|
12
|
+
)
|
|
13
|
+
}, milliseconds)
|
|
14
|
+
return abortController.signal
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
// AbortSignal.any() is currently baseline 2024
|
|
18
|
+
export const anySignal = (...signals: AbortSignal[]) => {
|
|
19
|
+
// if any are already aborted, return an already aborted signal
|
|
20
|
+
for (const signal of signals)
|
|
21
|
+
if (signal.aborted) return AbortSignal.abort(signal.reason)
|
|
22
|
+
|
|
23
|
+
// otherwise, create a new signal that aborts when any of the given signals abort
|
|
24
|
+
const abortController = new AbortController()
|
|
25
|
+
for (const signal of signals) {
|
|
26
|
+
signal.addEventListener(
|
|
27
|
+
'abort',
|
|
28
|
+
() => abortController.abort(signal.reason),
|
|
29
|
+
{ signal: abortController.signal, once: true },
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
return abortController.signal
|
|
33
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
// This must remain here so that the `mangleErrors.cjs` build script
|
|
2
|
+
// does not have to import this into each source file it rewrites.
|
|
3
|
+
import { formatProdErrorMessage } from '@reduxjs/toolkit'
|
|
4
|
+
export * from '@reduxjs/toolkit'
|
|
5
|
+
|
|
6
|
+
export { createDynamicMiddleware } from '../dynamicMiddleware/react'
|
|
7
|
+
export type { CreateDispatchWithMiddlewareHook } from '../dynamicMiddleware/react/index'
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { createSelectorCreator, weakMapMemoize } from 'reselect'
|
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import type { Middleware } from 'redux'
|
|
2
|
+
import { isAction, isPlainObject } from './reduxImports'
|
|
3
|
+
import { getTimeMeasureUtils } from './utils'
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Returns true if the passed value is "plain", i.e. a value that is either
|
|
7
|
+
* directly JSON-serializable (boolean, number, string, array, plain object)
|
|
8
|
+
* or `undefined`.
|
|
9
|
+
*
|
|
10
|
+
* @param val The value to check.
|
|
11
|
+
*
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
export function isPlain(val: any) {
|
|
15
|
+
const type = typeof val
|
|
16
|
+
return (
|
|
17
|
+
val == null ||
|
|
18
|
+
type === 'string' ||
|
|
19
|
+
type === 'boolean' ||
|
|
20
|
+
type === 'number' ||
|
|
21
|
+
Array.isArray(val) ||
|
|
22
|
+
isPlainObject(val)
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface NonSerializableValue {
|
|
27
|
+
keyPath: string
|
|
28
|
+
value: unknown
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type IgnoredPaths = readonly (string | RegExp)[]
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* @public
|
|
35
|
+
*/
|
|
36
|
+
export function findNonSerializableValue(
|
|
37
|
+
value: unknown,
|
|
38
|
+
path: string = '',
|
|
39
|
+
isSerializable: (value: unknown) => boolean = isPlain,
|
|
40
|
+
getEntries?: (value: unknown) => [string, any][],
|
|
41
|
+
ignoredPaths: IgnoredPaths = [],
|
|
42
|
+
cache?: WeakSet<object>,
|
|
43
|
+
): NonSerializableValue | false {
|
|
44
|
+
let foundNestedSerializable: NonSerializableValue | false
|
|
45
|
+
|
|
46
|
+
if (!isSerializable(value)) {
|
|
47
|
+
return {
|
|
48
|
+
keyPath: path || '<root>',
|
|
49
|
+
value: value,
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
if (typeof value !== 'object' || value === null) {
|
|
54
|
+
return false
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
if (cache?.has(value)) return false
|
|
58
|
+
|
|
59
|
+
const entries = getEntries != null ? getEntries(value) : Object.entries(value)
|
|
60
|
+
|
|
61
|
+
const hasIgnoredPaths = ignoredPaths.length > 0
|
|
62
|
+
|
|
63
|
+
for (const [key, nestedValue] of entries) {
|
|
64
|
+
const nestedPath = path ? path + '.' + key : key
|
|
65
|
+
|
|
66
|
+
if (hasIgnoredPaths) {
|
|
67
|
+
const hasMatches = ignoredPaths.some((ignored) => {
|
|
68
|
+
if (ignored instanceof RegExp) {
|
|
69
|
+
return ignored.test(nestedPath)
|
|
70
|
+
}
|
|
71
|
+
return nestedPath === ignored
|
|
72
|
+
})
|
|
73
|
+
if (hasMatches) {
|
|
74
|
+
continue
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (!isSerializable(nestedValue)) {
|
|
79
|
+
return {
|
|
80
|
+
keyPath: nestedPath,
|
|
81
|
+
value: nestedValue,
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (typeof nestedValue === 'object') {
|
|
86
|
+
foundNestedSerializable = findNonSerializableValue(
|
|
87
|
+
nestedValue,
|
|
88
|
+
nestedPath,
|
|
89
|
+
isSerializable,
|
|
90
|
+
getEntries,
|
|
91
|
+
ignoredPaths,
|
|
92
|
+
cache,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
if (foundNestedSerializable) {
|
|
96
|
+
return foundNestedSerializable
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (cache && isNestedFrozen(value)) cache.add(value)
|
|
102
|
+
|
|
103
|
+
return false
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
export function isNestedFrozen(value: object) {
|
|
107
|
+
if (!Object.isFrozen(value)) return false
|
|
108
|
+
|
|
109
|
+
for (const nestedValue of Object.values(value)) {
|
|
110
|
+
if (typeof nestedValue !== 'object' || nestedValue === null) continue
|
|
111
|
+
|
|
112
|
+
if (!isNestedFrozen(nestedValue)) return false
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
return true
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Options for `createSerializableStateInvariantMiddleware()`.
|
|
120
|
+
*
|
|
121
|
+
* @public
|
|
122
|
+
*/
|
|
123
|
+
export interface SerializableStateInvariantMiddlewareOptions {
|
|
124
|
+
/**
|
|
125
|
+
* The function to check if a value is considered serializable. This
|
|
126
|
+
* function is applied recursively to every value contained in the
|
|
127
|
+
* state. Defaults to `isPlain()`.
|
|
128
|
+
*/
|
|
129
|
+
isSerializable?: (value: any) => boolean
|
|
130
|
+
/**
|
|
131
|
+
* The function that will be used to retrieve entries from each
|
|
132
|
+
* value. If unspecified, `Object.entries` will be used. Defaults
|
|
133
|
+
* to `undefined`.
|
|
134
|
+
*/
|
|
135
|
+
getEntries?: (value: any) => [string, any][]
|
|
136
|
+
|
|
137
|
+
/**
|
|
138
|
+
* An array of action types to ignore when checking for serializability.
|
|
139
|
+
* Defaults to []
|
|
140
|
+
*/
|
|
141
|
+
ignoredActions?: string[]
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* An array of dot-separated path strings or regular expressions to ignore
|
|
145
|
+
* when checking for serializability, Defaults to
|
|
146
|
+
* ['meta.arg', 'meta.baseQueryMeta']
|
|
147
|
+
*/
|
|
148
|
+
ignoredActionPaths?: (string | RegExp)[]
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* An array of dot-separated path strings or regular expressions to ignore
|
|
152
|
+
* when checking for serializability, Defaults to []
|
|
153
|
+
*/
|
|
154
|
+
ignoredPaths?: (string | RegExp)[]
|
|
155
|
+
/**
|
|
156
|
+
* Execution time warning threshold. If the middleware takes longer
|
|
157
|
+
* than `warnAfter` ms, a warning will be displayed in the console.
|
|
158
|
+
* Defaults to 32ms.
|
|
159
|
+
*/
|
|
160
|
+
warnAfter?: number
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Opt out of checking state. When set to `true`, other state-related params will be ignored.
|
|
164
|
+
*/
|
|
165
|
+
ignoreState?: boolean
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Opt out of checking actions. When set to `true`, other action-related params will be ignored.
|
|
169
|
+
*/
|
|
170
|
+
ignoreActions?: boolean
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Opt out of caching the results. The cache uses a WeakSet and speeds up repeated checking processes.
|
|
174
|
+
* The cache is automatically disabled if no browser support for WeakSet is present.
|
|
175
|
+
*/
|
|
176
|
+
disableCache?: boolean
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/**
|
|
180
|
+
* Creates a middleware that, after every state change, checks if the new
|
|
181
|
+
* state is serializable. If a non-serializable value is found within the
|
|
182
|
+
* state, an error is printed to the console.
|
|
183
|
+
*
|
|
184
|
+
* @param options Middleware options.
|
|
185
|
+
*
|
|
186
|
+
* @public
|
|
187
|
+
*/
|
|
188
|
+
export function createSerializableStateInvariantMiddleware(
|
|
189
|
+
options: SerializableStateInvariantMiddlewareOptions = {},
|
|
190
|
+
): Middleware {
|
|
191
|
+
if (process.env.NODE_ENV === 'production') {
|
|
192
|
+
return () => (next) => (action) => next(action)
|
|
193
|
+
} else {
|
|
194
|
+
const {
|
|
195
|
+
isSerializable = isPlain,
|
|
196
|
+
getEntries,
|
|
197
|
+
ignoredActions = [],
|
|
198
|
+
ignoredActionPaths = ['meta.arg', 'meta.baseQueryMeta'],
|
|
199
|
+
ignoredPaths = [],
|
|
200
|
+
warnAfter = 32,
|
|
201
|
+
ignoreState = false,
|
|
202
|
+
ignoreActions = false,
|
|
203
|
+
disableCache = false,
|
|
204
|
+
} = options
|
|
205
|
+
|
|
206
|
+
const cache: WeakSet<object> | undefined =
|
|
207
|
+
!disableCache && WeakSet ? new WeakSet() : undefined
|
|
208
|
+
|
|
209
|
+
return (storeAPI) => (next) => (action) => {
|
|
210
|
+
if (!isAction(action)) {
|
|
211
|
+
return next(action)
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
const result = next(action)
|
|
215
|
+
|
|
216
|
+
const measureUtils = getTimeMeasureUtils(
|
|
217
|
+
warnAfter,
|
|
218
|
+
'SerializableStateInvariantMiddleware',
|
|
219
|
+
)
|
|
220
|
+
|
|
221
|
+
if (
|
|
222
|
+
!ignoreActions &&
|
|
223
|
+
!(
|
|
224
|
+
ignoredActions.length &&
|
|
225
|
+
ignoredActions.indexOf(action.type as any) !== -1
|
|
226
|
+
)
|
|
227
|
+
) {
|
|
228
|
+
measureUtils.measureTime(() => {
|
|
229
|
+
const foundActionNonSerializableValue = findNonSerializableValue(
|
|
230
|
+
action,
|
|
231
|
+
'',
|
|
232
|
+
isSerializable,
|
|
233
|
+
getEntries,
|
|
234
|
+
ignoredActionPaths,
|
|
235
|
+
cache,
|
|
236
|
+
)
|
|
237
|
+
|
|
238
|
+
if (foundActionNonSerializableValue) {
|
|
239
|
+
const { keyPath, value } = foundActionNonSerializableValue
|
|
240
|
+
|
|
241
|
+
console.error(
|
|
242
|
+
`A non-serializable value was detected in an action, in the path: \`${keyPath}\`. Value:`,
|
|
243
|
+
value,
|
|
244
|
+
'\nTake a look at the logic that dispatched this action: ',
|
|
245
|
+
action,
|
|
246
|
+
'\n(See https://redux.js.org/faq/actions#why-should-type-be-a-string-or-at-least-serializable-why-should-my-action-types-be-constants)',
|
|
247
|
+
'\n(To allow non-serializable values see: https://redux-toolkit.js.org/usage/usage-guide#working-with-non-serializable-data)',
|
|
248
|
+
)
|
|
249
|
+
}
|
|
250
|
+
})
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
if (!ignoreState) {
|
|
254
|
+
measureUtils.measureTime(() => {
|
|
255
|
+
const state = storeAPI.getState()
|
|
256
|
+
|
|
257
|
+
const foundStateNonSerializableValue = findNonSerializableValue(
|
|
258
|
+
state,
|
|
259
|
+
'',
|
|
260
|
+
isSerializable,
|
|
261
|
+
getEntries,
|
|
262
|
+
ignoredPaths,
|
|
263
|
+
cache,
|
|
264
|
+
)
|
|
265
|
+
|
|
266
|
+
if (foundStateNonSerializableValue) {
|
|
267
|
+
const { keyPath, value } = foundStateNonSerializableValue
|
|
268
|
+
|
|
269
|
+
console.error(
|
|
270
|
+
`A non-serializable value was detected in the state, in the path: \`${keyPath}\`. Value:`,
|
|
271
|
+
value,
|
|
272
|
+
`
|
|
273
|
+
Take a look at the reducer(s) handling this action type: ${action.type}.
|
|
274
|
+
(See https://redux.js.org/faq/organizing-state#can-i-put-functions-promises-or-other-non-serializable-items-in-my-store-state)`,
|
|
275
|
+
)
|
|
276
|
+
}
|
|
277
|
+
})
|
|
278
|
+
|
|
279
|
+
measureUtils.warnIfExceeded()
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
return result
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
}
|