diff --git a/.changeset/config.json b/.changeset/config.json index fe690d3e2..7d34ec262 100644 --- a/.changeset/config.json +++ b/.changeset/config.json @@ -2,7 +2,15 @@ "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", "changelog": ["@changesets/changelog-github", { "repo": "toss/suspensive" }], "commit": false, - "fixed": [["@suspensive/react", "@suspensive/react-query", "@suspensive/react-query-4", "@suspensive/react-query-5"]], + "fixed": [ + [ + "@suspensive/utils", + "@suspensive/react", + "@suspensive/react-query", + "@suspensive/react-query-4", + "@suspensive/react-query-5" + ] + ], "ignore": ["@suspensive/next-streaming-react-query", "@suspensive/visualization", "@suspensive/suspensive.org"], "linked": [], "access": "restricted", diff --git a/.changeset/strange-buttons-retire.md b/.changeset/strange-buttons-retire.md new file mode 100644 index 000000000..e62dafaa4 --- /dev/null +++ b/.changeset/strange-buttons-retire.md @@ -0,0 +1,5 @@ +--- +"@suspensive/utils": patch +--- + +feat(utils): add @suspensive/utils diff --git a/.github/labeler.yml b/.github/labeler.yml index 7d50e1820..62b6aa3d8 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,3 +1,5 @@ +"@suspensive/utils": + - "packages/utils/**/*" "@suspensive/react": - "packages/react/**/*" "@suspensive/react-query": diff --git a/codecov.yml b/codecov.yml index 6e596b22a..1ecc6db43 100644 --- a/codecov.yml +++ b/codecov.yml @@ -20,6 +20,10 @@ ignore: component_management: individual_components: + - component_id: utils + name: '@suspensive/utils' + paths: + - packages/utils/** - component_id: react name: '@suspensive/react' paths: diff --git a/configs/test-utils/src/index.tsx b/configs/test-utils/src/index.tsx deleted file mode 100644 index fa75ec151..000000000 --- a/configs/test-utils/src/index.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import { type PropsWithChildren, type ReactNode, useEffect, useLayoutEffect, useRef, useState } from 'react' - -export const sleep = (ms: number) => new Promise((resolve) => setTimeout(() => resolve(undefined), ms)) - -export class CustomError extends Error { - constructor(...args: ConstructorParameters) { - super(...args) - console.error(...args) - } -} -export class CustomNotError { - constructor(public message?: string) { - console.log(message) - } -} - -const suspendIsNeed = { current: true } -type SuspendProps = { during: number; toShow?: ReactNode } -export const Suspend = ({ during, toShow }: SuspendProps) => { - if (suspendIsNeed.current) { - throw new Promise((resolve) => - setTimeout(() => { - suspendIsNeed.current = false - resolve('resolved') - }, during) - ) - } - return toShow -} -Suspend.reset = () => { - suspendIsNeed.current = true -} - -const useIsomorphicLayoutEffect = typeof window !== 'undefined' ? useLayoutEffect : useEffect - -const useTimeout = (fn: () => void, ms: number) => { - const fnRef = useRef(fn) - - useIsomorphicLayoutEffect(() => { - fnRef.current = fn - }, [fn]) - - useEffect(() => { - const id = setTimeout(fnRef.current, ms) - return () => clearTimeout(id) - }, [ms]) -} - -const throwErrorIsNeed = { current: false } -type ThrowErrorProps = PropsWithChildren<{ message: string; after?: number }> -export const ThrowError = ({ message, after = 0, children }: ThrowErrorProps) => { - const [isNeedError, setIsNeedError] = useState(after === 0 ? true : throwErrorIsNeed.current) - if (isNeedError) { - throw new Error(message) - } - useTimeout(() => setIsNeedError(true), after) - return <>{children} -} - -type ThrowNullProps = PropsWithChildren<{ after: number }> -export const ThrowNull = ({ after, children }: ThrowNullProps) => { - const [isNeedError, setIsNeedError] = useState(throwErrorIsNeed.current) - if (isNeedError) { - throw null - } - useTimeout(() => setIsNeedError(true), after) - return <>{children} -} - -ThrowError.reset = () => { - throwErrorIsNeed.current = false -} - -export const TEXT = 'TEXT' -export const ERROR_MESSAGE = 'ERROR_MESSAGE' -export const FALLBACK = 'FALLBACK' - -export const queryKey = ['key'] as const -export const queryFn = () => sleep(10).then(() => ({ text: 'response' })) -export const boolean = Math.random() > 0.5 -export const select = (data: Awaited>) => data.text diff --git a/packages/cache/package.json b/packages/cache/package.json index ae2c887be..8bc7b5004 100644 --- a/packages/cache/package.json +++ b/packages/cache/package.json @@ -49,10 +49,12 @@ "dev": "tsup --watch", "prepack": "pnpm build" }, + "dependencies": { + "@suspensive/utils": "workspace:*" + }, "devDependencies": { "@suspensive/eslint-config": "workspace:*", "@suspensive/react": "workspace:*", - "@suspensive/test-utils": "workspace:*", "@suspensive/tsconfig": "workspace:*", "@suspensive/tsup": "workspace:*", "@types/react": "^18.3.3", diff --git a/packages/cache/src/Cache.spec.tsx b/packages/cache/src/Cache.spec.tsx index d055253c4..4d479d86b 100644 --- a/packages/cache/src/Cache.spec.tsx +++ b/packages/cache/src/Cache.spec.tsx @@ -1,5 +1,5 @@ import { Suspense } from '@suspensive/react' -import { TEXT } from '@suspensive/test-utils' +import { TEXT } from '@suspensive/utils' import { render, screen } from '@testing-library/react' import { Cache } from './Cache' import { CacheStore } from './CacheStore' diff --git a/packages/cache/src/CacheStore.spec.tsx b/packages/cache/src/CacheStore.spec.tsx index c52e8efdb..72bfce47c 100644 --- a/packages/cache/src/CacheStore.spec.tsx +++ b/packages/cache/src/CacheStore.spec.tsx @@ -1,4 +1,4 @@ -import { ERROR_MESSAGE, FALLBACK, TEXT, sleep } from '@suspensive/test-utils' +import { ERROR_MESSAGE, FALLBACK, TEXT, sleep } from '@suspensive/utils' import { render, screen, waitFor } from '@testing-library/react' import ms from 'ms' import { Suspense } from 'react' diff --git a/packages/cache/src/cacheOptions.spec.tsx b/packages/cache/src/cacheOptions.spec.tsx index a3211736f..de502bb09 100644 --- a/packages/cache/src/cacheOptions.spec.tsx +++ b/packages/cache/src/cacheOptions.spec.tsx @@ -1,4 +1,4 @@ -import { FALLBACK, TEXT } from '@suspensive/test-utils' +import { FALLBACK, TEXT } from '@suspensive/utils' import { render, screen } from '@testing-library/react' import { Suspense } from 'react' import { Cache } from './Cache' diff --git a/packages/cache/src/useCache.spec.tsx b/packages/cache/src/useCache.spec.tsx index 2434111ae..4b1196a59 100644 --- a/packages/cache/src/useCache.spec.tsx +++ b/packages/cache/src/useCache.spec.tsx @@ -1,5 +1,5 @@ import { ErrorBoundary, Suspense } from '@suspensive/react' -import { ERROR_MESSAGE, FALLBACK, TEXT, sleep } from '@suspensive/test-utils' +import { ERROR_MESSAGE, FALLBACK, TEXT, sleep } from '@suspensive/utils' import { render, screen, waitFor } from '@testing-library/react' import ms from 'ms' import { cacheOptions } from './cacheOptions' diff --git a/packages/jotai/package.json b/packages/jotai/package.json index 37446e69f..7e1b330e3 100644 --- a/packages/jotai/package.json +++ b/packages/jotai/package.json @@ -49,6 +49,9 @@ "dev": "tsup --watch", "prepack": "pnpm build" }, + "dependencies": { + "@suspensive/utils": "workspace:*" + }, "devDependencies": { "@suspensive/eslint-config": "workspace:*", "@suspensive/tsconfig": "workspace:*", diff --git a/packages/react-await/package.json b/packages/react-await/package.json index 32d97ca0a..bd4fa6f02 100644 --- a/packages/react-await/package.json +++ b/packages/react-await/package.json @@ -49,10 +49,12 @@ "dev": "tsup --watch", "prepack": "pnpm build" }, + "dependencies": { + "@suspensive/utils": "workspace:*" + }, "devDependencies": { "@suspensive/eslint-config": "workspace:*", "@suspensive/react": "workspace:*", - "@suspensive/test-utils": "workspace:*", "@suspensive/tsconfig": "workspace:*", "@suspensive/tsup": "workspace:*", "@types/react": "^18.3.3", diff --git a/packages/react-await/src/Await.spec.tsx b/packages/react-await/src/Await.spec.tsx index 0f368276c..cd319261e 100644 --- a/packages/react-await/src/Await.spec.tsx +++ b/packages/react-await/src/Await.spec.tsx @@ -1,5 +1,5 @@ import { Suspense } from '@suspensive/react' -import { TEXT } from '@suspensive/test-utils' +import { TEXT } from '@suspensive/utils' import { render, screen } from '@testing-library/react' import { Await } from './Await' diff --git a/packages/react-await/src/AwaitClient.spec.tsx b/packages/react-await/src/AwaitClient.spec.tsx index 2746bd12f..361d54678 100644 --- a/packages/react-await/src/AwaitClient.spec.tsx +++ b/packages/react-await/src/AwaitClient.spec.tsx @@ -1,4 +1,4 @@ -import { ERROR_MESSAGE, FALLBACK, TEXT, sleep } from '@suspensive/test-utils' +import { ERROR_MESSAGE, FALLBACK, TEXT, sleep } from '@suspensive/utils' import { render, screen, waitFor } from '@testing-library/react' import ms from 'ms' import { Suspense } from 'react' diff --git a/packages/react-await/src/awaitOptions.spec.tsx b/packages/react-await/src/awaitOptions.spec.tsx index a23e1245c..20615d16a 100644 --- a/packages/react-await/src/awaitOptions.spec.tsx +++ b/packages/react-await/src/awaitOptions.spec.tsx @@ -1,4 +1,4 @@ -import { FALLBACK, TEXT } from '@suspensive/test-utils' +import { FALLBACK, TEXT } from '@suspensive/utils' import { render, screen } from '@testing-library/react' import { Suspense } from 'react' import { Await } from './Await' diff --git a/packages/react-await/src/useAwait.spec.tsx b/packages/react-await/src/useAwait.spec.tsx index f06b33dab..5b567a45b 100644 --- a/packages/react-await/src/useAwait.spec.tsx +++ b/packages/react-await/src/useAwait.spec.tsx @@ -1,5 +1,5 @@ import { ErrorBoundary, Suspense } from '@suspensive/react' -import { ERROR_MESSAGE, FALLBACK, TEXT, sleep } from '@suspensive/test-utils' +import { ERROR_MESSAGE, FALLBACK, TEXT, sleep } from '@suspensive/utils' import { render, screen, waitFor } from '@testing-library/react' import ms from 'ms' import { awaitClient } from './AwaitClient' diff --git a/packages/react-image/package.json b/packages/react-image/package.json index 44ff0a7a2..f984c0799 100644 --- a/packages/react-image/package.json +++ b/packages/react-image/package.json @@ -49,9 +49,11 @@ "dev": "tsup --watch", "prepack": "pnpm build" }, + "dependencies": { + "@suspensive/utils": "workspace:*" + }, "devDependencies": { "@suspensive/eslint-config": "workspace:*", - "@suspensive/test-utils": "workspace:*", "@suspensive/tsconfig": "workspace:*", "@suspensive/tsup": "workspace:*", "@types/react": "^18.3.3", diff --git a/packages/react-query-4/package.json b/packages/react-query-4/package.json index e0cf812f7..74d62d947 100644 --- a/packages/react-query-4/package.json +++ b/packages/react-query-4/package.json @@ -50,10 +50,12 @@ "dev": "tsup --watch", "prepack": "pnpm build" }, + "dependencies": { + "@suspensive/utils": "workspace:*" + }, "devDependencies": { "@suspensive/eslint-config": "workspace:*", "@suspensive/react": "workspace:*", - "@suspensive/test-utils": "workspace:*", "@suspensive/tsconfig": "workspace:*", "@suspensive/tsup": "workspace:*", "@tanstack/react-query": "^4.36.1", diff --git a/packages/react-query-4/src/SuspenseInfiniteQuery.test-d.tsx b/packages/react-query-4/src/SuspenseInfiniteQuery.test-d.tsx index 9a51b107d..9b5c47a77 100644 --- a/packages/react-query-4/src/SuspenseInfiniteQuery.test-d.tsx +++ b/packages/react-query-4/src/SuspenseInfiniteQuery.test-d.tsx @@ -1,4 +1,4 @@ -import { queryFn, queryKey } from '@suspensive/test-utils' +import { queryFn, queryKey } from '@suspensive/utils' import type { InfiniteData } from '@tanstack/react-query' import type { ReactNode } from 'react' import { describe, expectTypeOf, it } from 'vitest' diff --git a/packages/react-query-4/src/SuspenseQueries.test-d.tsx b/packages/react-query-4/src/SuspenseQueries.test-d.tsx index 016cc39d5..52686df43 100644 --- a/packages/react-query-4/src/SuspenseQueries.test-d.tsx +++ b/packages/react-query-4/src/SuspenseQueries.test-d.tsx @@ -1,4 +1,4 @@ -import { queryFn, queryKey } from '@suspensive/test-utils' +import { queryFn, queryKey } from '@suspensive/utils' import type { ReactNode } from 'react' import { describe, expectTypeOf, it } from 'vitest' import { queryOptions } from './queryOptions' diff --git a/packages/react-query-4/src/SuspenseQuery.test-d.tsx b/packages/react-query-4/src/SuspenseQuery.test-d.tsx index 28562a53f..f84500fdd 100644 --- a/packages/react-query-4/src/SuspenseQuery.test-d.tsx +++ b/packages/react-query-4/src/SuspenseQuery.test-d.tsx @@ -1,4 +1,4 @@ -import { queryFn, queryKey } from '@suspensive/test-utils' +import { queryFn, queryKey } from '@suspensive/utils' import type { ReactNode } from 'react' import { describe, expectTypeOf, it } from 'vitest' import { queryOptions } from './queryOptions' diff --git a/packages/react-query-4/src/infiniteQueryOptions.test-d.tsx b/packages/react-query-4/src/infiniteQueryOptions.test-d.tsx index 4d4c27f11..3a2340b71 100644 --- a/packages/react-query-4/src/infiniteQueryOptions.test-d.tsx +++ b/packages/react-query-4/src/infiniteQueryOptions.test-d.tsx @@ -1,4 +1,4 @@ -import { queryKey } from '@suspensive/test-utils' +import { queryKey } from '@suspensive/utils' import { type InfiniteData, type UseInfiniteQueryResult, useInfiniteQuery, useQueryClient } from '@tanstack/react-query' import { describe, expectTypeOf, it } from 'vitest' import { infiniteQueryOptions } from './infiniteQueryOptions' diff --git a/packages/react-query-4/src/infiniteQueryOptions.ts b/packages/react-query-4/src/infiniteQueryOptions.ts index cb12c331e..6cd48de00 100644 --- a/packages/react-query-4/src/infiniteQueryOptions.ts +++ b/packages/react-query-4/src/infiniteQueryOptions.ts @@ -1,5 +1,5 @@ +import type { OmitKeyof, RequiredKeyof } from '@suspensive/utils' import type { InfiniteData, QueryKey, UseInfiniteQueryOptions } from '@tanstack/react-query' -import type { OmitKeyof, RequiredKeyof } from './utility-types' type SelectedInfiniteOptions< TQueryFnData, diff --git a/packages/react-query-4/src/queryOptions.test-d.tsx b/packages/react-query-4/src/queryOptions.test-d.tsx index 126eef6e8..8b26f6ffb 100644 --- a/packages/react-query-4/src/queryOptions.test-d.tsx +++ b/packages/react-query-4/src/queryOptions.test-d.tsx @@ -1,4 +1,4 @@ -import { queryKey } from '@suspensive/test-utils' +import { queryKey } from '@suspensive/utils' import { type UseQueryResult, useQueries, useQuery, useQueryClient } from '@tanstack/react-query' import { describe, expectTypeOf, it } from 'vitest' import { queryOptions } from './queryOptions' diff --git a/packages/react-query-4/src/queryOptions.ts b/packages/react-query-4/src/queryOptions.ts index 3c6918598..87101a8cb 100644 --- a/packages/react-query-4/src/queryOptions.ts +++ b/packages/react-query-4/src/queryOptions.ts @@ -1,5 +1,5 @@ +import type { OmitKeyof, RequiredKeyof } from '@suspensive/utils' import type { QueryKey, UseQueryOptions } from '@tanstack/react-query' -import type { OmitKeyof, RequiredKeyof } from './utility-types' type SelectedQueryOptions< TQueryFnData = unknown, diff --git a/packages/react-query-4/src/useSuspenseInfiniteQuery.test-d.ts b/packages/react-query-4/src/useSuspenseInfiniteQuery.test-d.ts index 5f6756b9d..194c831d6 100644 --- a/packages/react-query-4/src/useSuspenseInfiniteQuery.test-d.ts +++ b/packages/react-query-4/src/useSuspenseInfiniteQuery.test-d.ts @@ -1,4 +1,4 @@ -import { queryFn, queryKey } from '@suspensive/test-utils' +import { queryFn, queryKey } from '@suspensive/utils' import type { InfiniteData } from '@tanstack/react-query' import { infiniteQueryOptions } from './infiniteQueryOptions' import { type UseSuspenseInfiniteQueryResult, useSuspenseInfiniteQuery } from './useSuspenseInfiniteQuery' diff --git a/packages/react-query-4/src/useSuspenseInfiniteQuery.ts b/packages/react-query-4/src/useSuspenseInfiniteQuery.ts index af26f2be2..e3fe060c6 100644 --- a/packages/react-query-4/src/useSuspenseInfiniteQuery.ts +++ b/packages/react-query-4/src/useSuspenseInfiniteQuery.ts @@ -1,3 +1,4 @@ +import type { OmitKeyof } from '@suspensive/utils' import { type InfiniteData, type QueryKey, @@ -5,7 +6,6 @@ import { type UseInfiniteQueryResult, useInfiniteQuery, } from '@tanstack/react-query' -import type { OmitKeyof } from './utility-types' export interface UseSuspenseInfiniteQueryResult extends OmitKeyof< diff --git a/packages/react-query-4/src/useSuspenseQueries.test-d.ts b/packages/react-query-4/src/useSuspenseQueries.test-d.ts index cb3e30409..d23302110 100644 --- a/packages/react-query-4/src/useSuspenseQueries.test-d.ts +++ b/packages/react-query-4/src/useSuspenseQueries.test-d.ts @@ -1,4 +1,4 @@ -import { queryFn, queryKey, select } from '@suspensive/test-utils' +import { queryFn, queryKey, select } from '@suspensive/utils' import { describe, expectTypeOf, it } from 'vitest' import { queryOptions } from './queryOptions' import { useSuspenseQueries } from './useSuspenseQueries' diff --git a/packages/react-query-4/src/useSuspenseQuery.test-d.ts b/packages/react-query-4/src/useSuspenseQuery.test-d.ts index 63355274e..c230e00bd 100644 --- a/packages/react-query-4/src/useSuspenseQuery.test-d.ts +++ b/packages/react-query-4/src/useSuspenseQuery.test-d.ts @@ -1,4 +1,4 @@ -import { queryFn, queryKey } from '@suspensive/test-utils' +import { queryFn, queryKey } from '@suspensive/utils' import { describe, expectTypeOf, it } from 'vitest' import { queryOptions } from './queryOptions' import { type UseSuspenseQueryResult, useSuspenseQuery } from './useSuspenseQuery' diff --git a/packages/react-query-4/src/useSuspenseQuery.ts b/packages/react-query-4/src/useSuspenseQuery.ts index 146e0a23b..49a9bea1e 100644 --- a/packages/react-query-4/src/useSuspenseQuery.ts +++ b/packages/react-query-4/src/useSuspenseQuery.ts @@ -1,5 +1,5 @@ +import type { OmitKeyof } from '@suspensive/utils' import { type QueryKey, type UseQueryOptions, type UseQueryResult, useQuery } from '@tanstack/react-query' -import type { OmitKeyof } from './utility-types' export interface UseSuspenseQueryResult extends OmitKeyof, keyof Pick> { diff --git a/packages/react-query-4/src/utility-types/index.ts b/packages/react-query-4/src/utility-types/index.ts deleted file mode 100644 index 48c94ffa5..000000000 --- a/packages/react-query-4/src/utility-types/index.ts +++ /dev/null @@ -1,2 +0,0 @@ -export type { OmitKeyof } from './OmitKeyof' -export type { RequiredKeyof } from './RequiredKeyof' diff --git a/packages/react-query-5/package.json b/packages/react-query-5/package.json index 3bec33ee6..6d3bb0dc7 100644 --- a/packages/react-query-5/package.json +++ b/packages/react-query-5/package.json @@ -50,10 +50,12 @@ "dev": "tsup --watch", "prepack": "pnpm build" }, + "dependencies": { + "@suspensive/utils": "workspace:*" + }, "devDependencies": { "@suspensive/eslint-config": "workspace:*", "@suspensive/react": "workspace:*", - "@suspensive/test-utils": "workspace:*", "@suspensive/tsconfig": "workspace:*", "@suspensive/tsup": "workspace:*", "@tanstack/react-query": "^5.50.1", diff --git a/packages/react-query-5/src/SuspenseInfiniteQuery.test-d.tsx b/packages/react-query-5/src/SuspenseInfiniteQuery.test-d.tsx index 2cfdaba60..1d66d1dd3 100644 --- a/packages/react-query-5/src/SuspenseInfiniteQuery.test-d.tsx +++ b/packages/react-query-5/src/SuspenseInfiniteQuery.test-d.tsx @@ -1,4 +1,4 @@ -import { queryFn, queryKey } from '@suspensive/test-utils' +import { queryFn, queryKey } from '@suspensive/utils' import type { InfiniteData, UseSuspenseInfiniteQueryResult } from '@tanstack/react-query' import type { ReactNode } from 'react' import { describe, expectTypeOf, it } from 'vitest' diff --git a/packages/react-query-5/src/SuspenseQueries.test-d.tsx b/packages/react-query-5/src/SuspenseQueries.test-d.tsx index f952ac8b7..730f7bb2a 100644 --- a/packages/react-query-5/src/SuspenseQueries.test-d.tsx +++ b/packages/react-query-5/src/SuspenseQueries.test-d.tsx @@ -1,4 +1,4 @@ -import { queryFn, queryKey } from '@suspensive/test-utils' +import { queryFn, queryKey } from '@suspensive/utils' import type { UseSuspenseQueryResult } from '@tanstack/react-query' import type { ReactNode } from 'react' import { describe, expectTypeOf, it } from 'vitest' diff --git a/packages/react-query-5/src/SuspenseQuery.test-d.tsx b/packages/react-query-5/src/SuspenseQuery.test-d.tsx index 6f44bb172..642b89cb4 100644 --- a/packages/react-query-5/src/SuspenseQuery.test-d.tsx +++ b/packages/react-query-5/src/SuspenseQuery.test-d.tsx @@ -1,4 +1,4 @@ -import { queryFn, queryKey } from '@suspensive/test-utils' +import { queryFn, queryKey } from '@suspensive/utils' import type { UseSuspenseQueryResult } from '@tanstack/react-query' import type { ReactNode } from 'react' import { describe, expectTypeOf, it } from 'vitest' diff --git a/packages/react-query/package.json b/packages/react-query/package.json index 17b948903..060845152 100644 --- a/packages/react-query/package.json +++ b/packages/react-query/package.json @@ -59,13 +59,13 @@ "@commander-js/extra-typings": "^12.1.0", "@suspensive/react-query-4": "workspace:^2.8.0", "@suspensive/react-query-5": "workspace:^2.8.0", + "@suspensive/utils": "workspace:*", "cli-table3": "^0.6.5", "commander": "^12.1.0" }, "devDependencies": { "@suspensive/eslint-config": "workspace:*", "@suspensive/react": "workspace:*", - "@suspensive/test-utils": "workspace:*", "@suspensive/tsconfig": "workspace:*", "@suspensive/tsup": "workspace:*", "@tanstack/react-query": "^4.36.1", diff --git a/packages/react/package.json b/packages/react/package.json index 0ffa4a810..27fb35235 100644 --- a/packages/react/package.json +++ b/packages/react/package.json @@ -50,9 +50,11 @@ "dev": "tsup --watch", "prepack": "pnpm build" }, + "dependencies": { + "@suspensive/utils": "workspace:*" + }, "devDependencies": { "@suspensive/eslint-config": "workspace:*", - "@suspensive/test-utils": "workspace:*", "@suspensive/tsconfig": "workspace:*", "@suspensive/tsup": "workspace:*", "@types/react": "^18.3.3", diff --git a/packages/react/src/Delay.spec.tsx b/packages/react/src/Delay.spec.tsx index c4aa4c031..5023ec263 100644 --- a/packages/react/src/Delay.spec.tsx +++ b/packages/react/src/Delay.spec.tsx @@ -1,4 +1,4 @@ -import { CustomError, TEXT } from '@suspensive/test-utils' +import { CustomError, TEXT } from '@suspensive/utils' import { render, screen, waitFor } from '@testing-library/react' import ms from 'ms' import { Delay } from './Delay' diff --git a/packages/react/src/Delay.tsx b/packages/react/src/Delay.tsx index 2b3387e05..a72d33884 100644 --- a/packages/react/src/Delay.tsx +++ b/packages/react/src/Delay.tsx @@ -1,6 +1,6 @@ +import { useTimeout } from '@suspensive/utils' import { type PropsWithChildren, type ReactNode, useContext, useState } from 'react' import { DelayDefaultPropsContext } from './contexts' -import { useTimeout } from './hooks' import { Message_Delay_ms_prop_should_be_greater_than_or_equal_to_0, SuspensiveError } from './models/SuspensiveError' export interface DelayProps extends PropsWithChildren { diff --git a/packages/react/src/ErrorBoundary.spec.tsx b/packages/react/src/ErrorBoundary.spec.tsx index aca635af5..ab92bac5b 100644 --- a/packages/react/src/ErrorBoundary.spec.tsx +++ b/packages/react/src/ErrorBoundary.spec.tsx @@ -1,4 +1,4 @@ -import { CustomError, ERROR_MESSAGE, FALLBACK, TEXT, ThrowError, ThrowNull } from '@suspensive/test-utils' +import { CustomError, ERROR_MESSAGE, FALLBACK, TEXT, Throw, useTimeout } from '@suspensive/utils' import { act, render, screen, waitFor } from '@testing-library/react' import { userEvent } from '@testing-library/user-event' import ms from 'ms' @@ -9,19 +9,18 @@ import { useErrorBoundary, useErrorBoundaryFallbackProps, } from './ErrorBoundary' -import { useTimeout } from './hooks' import { SuspensiveError } from './models/SuspensiveError' describe('', () => { - beforeEach(() => ThrowError.reset()) + beforeEach(() => Throw.reset()) it('should show children if no error but if error in children, catch it and show fallback and call onError', async () => { const onError = vi.fn() render( {FALLBACK}}> - + {TEXT} - + ) expect(screen.queryByText(TEXT)).toBeInTheDocument() @@ -35,9 +34,9 @@ describe('', () => { it('should show children if no error but if error in children, catch it and show fallback component', async () => { render( <>{props.error.message}}> - + {TEXT} - + ) expect(screen.queryByText(TEXT)).toBeInTheDocument() @@ -50,7 +49,7 @@ describe('', () => { expect(() => render( - + ) ).toThrow(ERROR_MESSAGE) @@ -60,7 +59,7 @@ describe('', () => { const onError = vi.fn() render( {FALLBACK}}> - {TEXT} + {TEXT} ) expect(screen.queryByText(TEXT)).toBeInTheDocument() @@ -75,9 +74,9 @@ describe('', () => { const onReset = vi.fn() const { rerender } = render( props.error.message} onReset={onReset}> - + {TEXT} - + ) expect(onReset).toHaveBeenCalledTimes(0) @@ -87,9 +86,9 @@ describe('', () => { expect(onReset).toHaveBeenCalledTimes(0) rerender( props.error.message} onReset={onReset}> - + {TEXT} - + ) expect(screen.queryByText(TEXT)).toBeInTheDocument() @@ -100,9 +99,9 @@ describe('', () => { const onReset = vi.fn() const { rerender } = render( props.error.message} onReset={onReset}> - + {TEXT} - + ) expect(onReset).toHaveBeenCalledTimes(0) @@ -112,9 +111,9 @@ describe('', () => { expect(onReset).toHaveBeenCalledTimes(0) rerender( props.error.message} onReset={onReset}> - + {TEXT} - + ) expect(screen.queryByText(TEXT)).toBeInTheDocument() @@ -126,9 +125,9 @@ describe('', () => { const fallbackFn = vi.fn<(props: ErrorBoundaryFallbackProps) => undefined>() render( - + {TEXT} - + ) expect(screen.queryByText(TEXT)).toBeInTheDocument() @@ -147,9 +146,9 @@ describe('', () => { const ref = createRef>() render( <>{props.error.message}} onReset={onReset}> - + {TEXT} - + ) @@ -312,7 +311,7 @@ describe('', () => { }) describe('useErrorBoundary', () => { - beforeEach(() => ThrowError.reset()) + beforeEach(() => Throw.reset()) it('should supply setError to set Error of ErrorBoundary manually', async () => { const onError = vi.fn() @@ -361,7 +360,7 @@ describe('useErrorBoundary', () => { return <> }} > - + ) ).toThrow(SuspensiveError) @@ -369,7 +368,7 @@ describe('useErrorBoundary', () => { }) describe('useErrorBoundaryFallbackProps', () => { - beforeEach(() => ThrowError.reset()) + beforeEach(() => Throw.reset()) it('should supply reset function and error to reset in fallback of ErrorBoundary', async () => { const onReset = vi.fn() @@ -383,9 +382,9 @@ describe('useErrorBoundaryFallbackProps', () => { return <>{props.error.message} }} > - + {TEXT} - + ) expect(screen.queryByText(TEXT)).toBeInTheDocument() diff --git a/packages/react/src/ErrorBoundary.test-d.tsx b/packages/react/src/ErrorBoundary.test-d.tsx index c05c23c75..3fe34c673 100644 --- a/packages/react/src/ErrorBoundary.test-d.tsx +++ b/packages/react/src/ErrorBoundary.test-d.tsx @@ -1,7 +1,6 @@ -import { CustomError, CustomNotError } from '@suspensive/test-utils' +import { type ConstructorType, CustomError, CustomNotError } from '@suspensive/utils' import type { ComponentProps, ReactNode } from 'react' import { ErrorBoundary } from './ErrorBoundary' -import type { ConstructorType } from './utility-types' describe('', () => { it('should pass only boolean or ErrorConstructor or ShouldCatchCallback or ShouldCatch[]', () => { diff --git a/packages/react/src/ErrorBoundary.tsx b/packages/react/src/ErrorBoundary.tsx index 1b3f882bf..1b1525443 100644 --- a/packages/react/src/ErrorBoundary.tsx +++ b/packages/react/src/ErrorBoundary.tsx @@ -1,3 +1,4 @@ +import type { ConstructorType, Nullable } from '@suspensive/utils' import { Component, type ErrorInfo, @@ -20,7 +21,7 @@ import { Message_useErrorBoundary_this_hook_should_be_called_in_ErrorBoundary_props_children, SuspensiveError, } from './models/SuspensiveError' -import type { ConstructorType, Nullable, PropsWithDevMode } from './utility-types' +import type { PropsWithDevMode } from './utility-types' import { hasResetKeysChanged } from './utils' export interface ErrorBoundaryFallbackProps { diff --git a/packages/react/src/ErrorBoundaryGroup.spec.tsx b/packages/react/src/ErrorBoundaryGroup.spec.tsx index 419479b10..eb0a91b0b 100644 --- a/packages/react/src/ErrorBoundaryGroup.spec.tsx +++ b/packages/react/src/ErrorBoundaryGroup.spec.tsx @@ -1,4 +1,4 @@ -import { CustomError, ERROR_MESSAGE, TEXT, ThrowError } from '@suspensive/test-utils' +import { CustomError, ERROR_MESSAGE, TEXT, Throw } from '@suspensive/utils' import { fireEvent, render, screen, waitFor } from '@testing-library/react' import ms from 'ms' import { createElement } from 'react' @@ -21,9 +21,9 @@ describe('', () => { {Array.from({ length: innerErrorBoundaryCount }).map((_, key) => (
{props.error.message}
}> - +
{TEXT}
-
+
))}
@@ -31,7 +31,7 @@ describe('', () => { expect(screen.getAllByText(TEXT).length).toBe(innerErrorBoundaryCount) await waitFor(() => expect(screen.getAllByText(ERROR_MESSAGE).length).toBe(innerErrorBoundaryCount)) - ThrowError.reset() + Throw.reset() fireEvent.click(screen.getByRole('button', { name: resetButtonText })) expect(screen.getAllByText(TEXT).length).toBe(innerErrorBoundaryCount) @@ -47,9 +47,9 @@ describe('', () => { {Array.from({ length: innerErrorBoundaryCount }).map((_, index) => (
{props.error.message}
}> - +
{TEXT}
-
+
))} @@ -58,7 +58,7 @@ describe('', () => { expect(screen.getAllByText(TEXT).length).toBe(innerErrorBoundaryCount) await waitFor(() => expect(screen.getAllByText(ERROR_MESSAGE).length).toBe(innerErrorBoundaryCount)) - ThrowError.reset() + Throw.reset() fireEvent.click(screen.getByRole('button', { name: resetButtonText })) expect(screen.getAllByText(TEXT).length).toBe(innerErrorBoundaryCount - 1) diff --git a/packages/react/src/ErrorBoundaryGroup.tsx b/packages/react/src/ErrorBoundaryGroup.tsx index 42fd77aab..b3b1e84f3 100644 --- a/packages/react/src/ErrorBoundaryGroup.tsx +++ b/packages/react/src/ErrorBoundaryGroup.tsx @@ -1,3 +1,4 @@ +import { increase } from '@suspensive/utils' import { type PropsWithChildren, type ReactNode, @@ -12,7 +13,6 @@ import { Message_useErrorBoundaryGroup_this_hook_should_be_called_in_ErrorBoundary_props_children, SuspensiveError, } from './models/SuspensiveError' -import { increase } from './utils' export const ErrorBoundaryGroupContext = createContext<{ reset: () => void; resetKey: number } | undefined>(undefined) if (process.env.NODE_ENV === 'development') { diff --git a/packages/react/src/Suspense.spec.tsx b/packages/react/src/Suspense.spec.tsx index f68e31e7a..287a012fb 100644 --- a/packages/react/src/Suspense.spec.tsx +++ b/packages/react/src/Suspense.spec.tsx @@ -1,4 +1,4 @@ -import { FALLBACK, Suspend, TEXT } from '@suspensive/test-utils' +import { FALLBACK, Suspend, TEXT } from '@suspensive/utils' import { render, screen, waitFor } from '@testing-library/react' import ms from 'ms' import { Suspense } from './Suspense' diff --git a/packages/react/src/Suspense.tsx b/packages/react/src/Suspense.tsx index def361dea..5c51c76d1 100644 --- a/packages/react/src/Suspense.tsx +++ b/packages/react/src/Suspense.tsx @@ -1,7 +1,7 @@ import { type SuspenseProps as ReactSuspenseProps, useContext } from 'react' import { SuspenseDefaultPropsContext, syncDevMode } from './contexts' import type { PropsWithDevMode } from './utility-types' -import { defineSuspense } from './utils/defineSuspense' +import { defineSuspense } from './utils' export interface SuspenseProps extends PropsWithDevMode { /** diff --git a/packages/react/src/Suspensive.spec.tsx b/packages/react/src/Suspensive.spec.tsx index ae022fa47..ec8d98158 100644 --- a/packages/react/src/Suspensive.spec.tsx +++ b/packages/react/src/Suspensive.spec.tsx @@ -1,4 +1,4 @@ -import { CustomError, FALLBACK, Suspend, TEXT } from '@suspensive/test-utils' +import { CustomError, FALLBACK, Suspend, TEXT } from '@suspensive/utils' import { render, screen, waitFor } from '@testing-library/react' import ms from 'ms' import { createElement, useContext } from 'react' diff --git a/packages/react/src/contexts/DefaultPropsContexts.ts b/packages/react/src/contexts/DefaultPropsContexts.ts index 54c270f5d..7741dd472 100644 --- a/packages/react/src/contexts/DefaultPropsContexts.ts +++ b/packages/react/src/contexts/DefaultPropsContexts.ts @@ -1,6 +1,6 @@ +import type { OmitKeyof } from '@suspensive/utils' import { createContext } from 'react' import type { DelayProps, SuspenseProps } from '..' -import type { OmitKeyof } from '../utility-types' export const DelayDefaultPropsContext = createContext>({ ms: undefined, diff --git a/packages/react/src/contexts/SuspensiveDevMode.spec.tsx b/packages/react/src/contexts/SuspensiveDevMode.spec.tsx index aa86780ba..9a31bfb98 100644 --- a/packages/react/src/contexts/SuspensiveDevMode.spec.tsx +++ b/packages/react/src/contexts/SuspensiveDevMode.spec.tsx @@ -1,4 +1,4 @@ -import { sleep } from '@suspensive/test-utils' +import { sleep } from '@suspensive/utils' import { waitFor } from '@testing-library/react' import { SuspensiveDevMode, SuspensiveDevModeOnInfoText } from './SuspensiveDevModeContext' diff --git a/packages/react/src/contexts/SuspensiveDevModeContext.tsx b/packages/react/src/contexts/SuspensiveDevModeContext.tsx index 061783613..0ec6a004b 100644 --- a/packages/react/src/contexts/SuspensiveDevModeContext.tsx +++ b/packages/react/src/contexts/SuspensiveDevModeContext.tsx @@ -1,3 +1,4 @@ +import { type Nullable, noop } from '@suspensive/utils' import { type ComponentProps, type ComponentType, @@ -8,8 +9,6 @@ import { useSyncExternalStore, } from 'react' import { Subscribable } from '../models/Subscribable' -import type { Nullable } from '../utility-types' -import { noop } from '../utils' const getNull = () => null diff --git a/packages/react/src/contexts/syncDevMode.spec.tsx b/packages/react/src/contexts/syncDevMode.spec.tsx index 1b5841e09..eb94309eb 100644 --- a/packages/react/src/contexts/syncDevMode.spec.tsx +++ b/packages/react/src/contexts/syncDevMode.spec.tsx @@ -1,4 +1,4 @@ -import { TEXT } from '@suspensive/test-utils' +import { TEXT } from '@suspensive/utils' import { render, screen, waitFor } from '@testing-library/react' import { userEvent } from '@testing-library/user-event' import { createElement } from 'react' diff --git a/packages/react/src/hooks/index.ts b/packages/react/src/hooks/index.ts index 1625e7fd1..e5c08df31 100644 --- a/packages/react/src/hooks/index.ts +++ b/packages/react/src/hooks/index.ts @@ -1,4 +1,2 @@ export { useIsChanged } from './useIsChanged' export { useIsClient } from './useIsClient' -export { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect' -export { useTimeout } from './useTimeout' diff --git a/packages/react/src/hooks/useIsClient.ts b/packages/react/src/hooks/useIsClient.ts index 3329a6390..4d2322f53 100644 --- a/packages/react/src/hooks/useIsClient.ts +++ b/packages/react/src/hooks/useIsClient.ts @@ -1,5 +1,5 @@ +import { useIsomorphicLayoutEffect } from '@suspensive/utils' import { useState } from 'react' -import { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect' export const useIsClient = () => { const [isClient, setIsClient] = useState(false) diff --git a/packages/react/src/utility-types/OmitKeyof.test-d.ts b/packages/react/src/utility-types/OmitKeyof.test-d.ts deleted file mode 100644 index 14a0900f8..000000000 --- a/packages/react/src/utility-types/OmitKeyof.test-d.ts +++ /dev/null @@ -1,175 +0,0 @@ -import type { OmitKeyof } from './OmitKeyof' - -describe('OmitKeyof', () => { - it("'s string key type check", () => { - type A = { - x: string - y: number - } - - type ExpectedType = { - x: string - } - - // Bad point - // 1. original Omit can use 'z' as type parameter with no type error - // 2. original Omit have no auto complete for 2nd type parameter - expectTypeOf>().toEqualTypeOf() - - // Solution - - // 1. strictly - expectTypeOf< - OmitKeyof< - A, - // OmitKeyof can't use 'z' as type parameter with type error because A don't have key 'z' - // @ts-expect-error Type does not satisfy the constraint keyof A - 'z' | 'y' - > - >().toEqualTypeOf - expectTypeOf< - OmitKeyof< - A, - // OmitKeyof can't use 'z' as type parameter with type error because A don't have key 'z' - // @ts-expect-error Type does not satisfy the constraint keyof A - 'z' | 'y', - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-arguments - 'strictly' - > - >().toEqualTypeOf - - // 2. safely - expectTypeOf< - OmitKeyof< - A, - // OmitKeyof can't use 'z' as type parameter type error with strictly parameter or default parameter - // @ts-expect-error Type does not satisfy the constraint keyof A - 'z' | 'y' - > - >().toEqualTypeOf - expectTypeOf< - OmitKeyof< - A, - // With 'safely', OmitKeyof can use 'z' as type parameter like original Omit but This support autocomplete too yet for DX. - 'z' | 'y', - 'safely' - > - >().toEqualTypeOf - }) - - it("'s number key type check", () => { - type A = { - [1]: string - [2]: number - } - - type ExpectedType = { - [1]: string - } - - // Bad point - // 1. original Omit can use 3 as type parameter with no type error - // 2. original Omit have no auto complete for 2nd type parameter - expectTypeOf>().toEqualTypeOf() - - // Solution - - // 1. strictly - expectTypeOf< - OmitKeyof< - A, - // OmitKeyof can't use 3 as type parameter with type error because A don't have key 3 - // @ts-expect-error Type does not satisfy the constraint keyof A - 3 | 2 - > - >().toEqualTypeOf - expectTypeOf< - OmitKeyof< - A, - // OmitKeyof can't use 3 as type parameter with type error because A don't have key 3 - // @ts-expect-error Type does not satisfy the constraint keyof A - 3 | 2, - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-arguments - 'strictly' - > - >().toEqualTypeOf - - // 2. safely - expectTypeOf< - OmitKeyof< - A, - // OmitKeyof can't use 3 as type parameter type error with strictly parameter or default parameter - // @ts-expect-error Type does not satisfy the constraint keyof A - 3 | 2 - > - >().toEqualTypeOf - expectTypeOf< - OmitKeyof< - A, - // With 'safely', OmitKeyof can use 3 as type parameter like original Omit but This support autocomplete too yet for DX. - 3 | 2, - 'safely' - > - >().toEqualTypeOf - }) - - it("'s symbol key type check", () => { - const symbol1 = Symbol() - const symbol2 = Symbol() - const symbol3 = Symbol() - - type A = { - [symbol1]: string - [symbol2]: number - } - - type ExpectedType = { - [symbol1]: string - } - - // Bad point - // 1. original Omit can use symbol3 as type parameter with no type error - // 2. original Omit have no auto complete for 2nd type parameter - expectTypeOf>().toEqualTypeOf() - - // Solution - - // 1. strictly - expectTypeOf< - OmitKeyof< - A, - // OmitKeyof can't use symbol3 as type parameter with type error because A don't have key symbol3 - // @ts-expect-error Type does not satisfy the constraint keyof A - typeof symbol3 | typeof symbol2 - > - >().toEqualTypeOf - expectTypeOf< - OmitKeyof< - A, - // OmitKeyof can't use symbol3 as type parameter with type error because A don't have key symbol3 - // @ts-expect-error Type does not satisfy the constraint keyof A - typeof symbol3 | typeof symbol2, - // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-arguments - 'strictly' - > - >().toEqualTypeOf - - // 2. safely - expectTypeOf< - OmitKeyof< - A, - // OmitKeyof can't use symbol3 as type parameter type error with strictly parameter or default parameter - // @ts-expect-error Type does not satisfy the constraint keyof A - typeof symbol3 | typeof symbol2 - > - >().toEqualTypeOf - expectTypeOf< - OmitKeyof< - A, - // With 'safely', OmitKeyof can use symbol3 as type parameter like original Omit but This support autocomplete too yet for DX. - typeof symbol3 | typeof symbol2, - 'safely' - > - >().toEqualTypeOf - }) -}) diff --git a/packages/react/src/utility-types/OmitKeyof.ts b/packages/react/src/utility-types/OmitKeyof.ts deleted file mode 100644 index 69f6be78c..000000000 --- a/packages/react/src/utility-types/OmitKeyof.ts +++ /dev/null @@ -1,11 +0,0 @@ -export type OmitKeyof< - TObject, - TKey extends TStrictly extends 'safely' - ? - | keyof TObject - | (string & Record) - | (number & Record) - | (symbol & Record) - : keyof TObject, - TStrictly extends 'strictly' | 'safely' = 'strictly', -> = Omit diff --git a/packages/react/src/utility-types/index.ts b/packages/react/src/utility-types/index.ts index dfe3ce5ed..0b58f2fe2 100644 --- a/packages/react/src/utility-types/index.ts +++ b/packages/react/src/utility-types/index.ts @@ -1,4 +1 @@ export type { PropsWithDevMode } from './PropsWithDevMode' -export type { OmitKeyof } from './OmitKeyof' -export type { ConstructorType } from './ConstructorType' -export type { Nullable } from './Nullable' diff --git a/packages/react/src/utils/index.ts b/packages/react/src/utils/index.ts index e2653b46a..73049f960 100644 --- a/packages/react/src/utils/index.ts +++ b/packages/react/src/utils/index.ts @@ -1,3 +1,2 @@ export { hasResetKeysChanged } from './hasResetKeysChanged' -export { increase } from './increase' -export { noop } from './noop' +export { defineSuspense } from './defineSuspense' diff --git a/packages/react/src/wrap.spec.tsx b/packages/react/src/wrap.spec.tsx index 658bbd02e..bbb3cc502 100644 --- a/packages/react/src/wrap.spec.tsx +++ b/packages/react/src/wrap.spec.tsx @@ -1,4 +1,4 @@ -import { ERROR_MESSAGE, FALLBACK, Suspend, TEXT, ThrowError } from '@suspensive/test-utils' +import { ERROR_MESSAGE, FALLBACK, Suspend, TEXT, Throw } from '@suspensive/utils' import { render, screen, waitFor } from '@testing-library/react' import ms from 'ms' import { createElement } from 'react' @@ -74,7 +74,7 @@ describe('wrap.Suspense({ clientOnly: true }).on', () => { }) describe('wrap.ErrorBoundary().on', () => { - beforeEach(() => ThrowError.reset()) + beforeEach(() => Throw.reset()) it("should render the wrapped component when there's no error", () => { render( @@ -97,9 +97,9 @@ describe('wrap.ErrorBoundary().on', () => { fallback: (props) => <>{props.error.message}, }) .on(() => ( - + {TEXT} - + )) ) ) diff --git a/packages/react/src/wrap.tsx b/packages/react/src/wrap.tsx index 640c4f8f7..a6b6c7a59 100644 --- a/packages/react/src/wrap.tsx +++ b/packages/react/src/wrap.tsx @@ -1,9 +1,9 @@ +import type { OmitKeyof } from '@suspensive/utils' import type { ComponentProps, ComponentType } from 'react' import { Delay } from './Delay' import { ErrorBoundary } from './ErrorBoundary' import { ErrorBoundaryGroup } from './ErrorBoundaryGroup' import { Suspense } from './Suspense' -import type { OmitKeyof } from './utility-types' type WrapperItem< TWrapperComponent extends typeof Suspense | typeof ErrorBoundary | typeof ErrorBoundaryGroup | typeof Delay, diff --git a/configs/test-utils/.eslintrc.cjs b/packages/utils/.eslintrc.cjs similarity index 84% rename from configs/test-utils/.eslintrc.cjs rename to packages/utils/.eslintrc.cjs index 40d6bff90..923a7a719 100644 --- a/configs/test-utils/.eslintrc.cjs +++ b/packages/utils/.eslintrc.cjs @@ -2,7 +2,7 @@ module.exports = { root: true, extends: ['@suspensive/eslint-config/react-ts'], - ignorePatterns: ['dist'], + ignorePatterns: ['dist', 'coverage'], parserOptions: { tsconfigRootDir: __dirname, project: 'tsconfig.json', diff --git a/packages/utils/LICENSE b/packages/utils/LICENSE new file mode 100644 index 000000000..69dc6a701 --- /dev/null +++ b/packages/utils/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2024 Viva Republica, Inc. + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/configs/test-utils/package.json b/packages/utils/package.json similarity index 60% rename from configs/test-utils/package.json rename to packages/utils/package.json index f2cb29e73..e20edae34 100644 --- a/configs/test-utils/package.json +++ b/packages/utils/package.json @@ -1,7 +1,20 @@ { - "name": "@suspensive/test-utils", - "version": "0.0.0", - "private": true, + "name": "@suspensive/utils", + "version": "2.8.0", + "description": "Useful interfaces for React Suspense", + "keywords": [ + "suspensive", + "react" + ], + "homepage": "https://suspensive.org", + "bugs": "https://github.com/toss/suspensive/issues", + "repository": { + "type": "git", + "url": "https://github.com/toss/suspensive.git", + "directory": "packages/utils" + }, + "license": "MIT", + "author": "Jonghyeon Ko ", "sideEffects": false, "type": "module", "exports": { @@ -20,11 +33,17 @@ "main": "dist/index.cjs", "module": "dist/index.js", "types": "dist/index.d.ts", + "files": [ + "dist", + "src" + ], "scripts": { "build": "tsup", "ci:attw": "attw --pack", "ci:eslint": "eslint \"**/*.{js,jsx,cjs,mjs,ts,tsx,cts,mts}\"", "ci:publint": "publint --strict", + "ci:test": "vitest run --coverage --typecheck", + "ci:test:watch": "vitest --ui --coverage --typecheck", "ci:type": "tsc --noEmit", "clean": "rimraf ./dist && rimraf ./coverage", "dev": "tsup --watch", @@ -39,5 +58,8 @@ }, "peerDependencies": { "react": "^18" + }, + "publishConfig": { + "access": "public" } } diff --git a/packages/react/src/utility-types/ConstructorType.ts b/packages/utils/src/ConstructorType.ts similarity index 100% rename from packages/react/src/utility-types/ConstructorType.ts rename to packages/utils/src/ConstructorType.ts diff --git a/packages/react/src/utility-types/Nullable.ts b/packages/utils/src/Nullable.ts similarity index 100% rename from packages/react/src/utility-types/Nullable.ts rename to packages/utils/src/Nullable.ts diff --git a/packages/react-query-4/src/utility-types/OmitKeyof.test-d.ts b/packages/utils/src/OmitKeyof.test-d.ts similarity index 100% rename from packages/react-query-4/src/utility-types/OmitKeyof.test-d.ts rename to packages/utils/src/OmitKeyof.test-d.ts diff --git a/packages/react-query-4/src/utility-types/OmitKeyof.ts b/packages/utils/src/OmitKeyof.ts similarity index 100% rename from packages/react-query-4/src/utility-types/OmitKeyof.ts rename to packages/utils/src/OmitKeyof.ts diff --git a/packages/react-query-4/src/utility-types/RequiredKeyof.ts b/packages/utils/src/RequiredKeyof.ts similarity index 100% rename from packages/react-query-4/src/utility-types/RequiredKeyof.ts rename to packages/utils/src/RequiredKeyof.ts diff --git a/packages/react/src/utils/increase.ts b/packages/utils/src/increase.ts similarity index 100% rename from packages/react/src/utils/increase.ts rename to packages/utils/src/increase.ts diff --git a/packages/utils/src/index.ts b/packages/utils/src/index.ts new file mode 100644 index 000000000..ae0f19dad --- /dev/null +++ b/packages/utils/src/index.ts @@ -0,0 +1,12 @@ +export * from './test-utils' + +export { useTimeout } from './useTimeout' +export { usePreservedCallback } from './usePreservedCallback' +export { useIsomorphicLayoutEffect } from './useIsomorphicLayoutEffect' +export { increase } from './increase' +export { noop } from './noop' + +export type { ConstructorType } from './ConstructorType' +export type { Nullable } from './Nullable' +export type { OmitKeyof } from './OmitKeyof' +export type { RequiredKeyof } from './RequiredKeyof' diff --git a/packages/react/src/utils/noop.ts b/packages/utils/src/noop.ts similarity index 100% rename from packages/react/src/utils/noop.ts rename to packages/utils/src/noop.ts diff --git a/packages/utils/src/test-utils/index.tsx b/packages/utils/src/test-utils/index.tsx new file mode 100644 index 000000000..fd2198860 --- /dev/null +++ b/packages/utils/src/test-utils/index.tsx @@ -0,0 +1,64 @@ +import { type PropsWithChildren, type ReactNode, useState } from 'react' +import { useTimeout } from '../useTimeout' + +const isNeedThrowGlobal = { current: false } + +export const Throw = { + Error: ({ message, after = 0, children }: PropsWithChildren<{ message: string; after?: number }>) => { + const [isNeedThrow, setIsNeedThrow] = useState(after === 0 ? true : isNeedThrowGlobal.current) + if (isNeedThrow) { + throw new Error(message) + } + useTimeout(() => setIsNeedThrow(true), after) + return <>{children} + }, + Null: ({ after, children }: PropsWithChildren<{ after: number }>) => { + const [isNeedError, setIsNeedError] = useState(isNeedThrowGlobal.current) + if (isNeedError) { + throw null + } + useTimeout(() => setIsNeedError(true), after) + return <>{children} + }, + reset: () => { + isNeedThrowGlobal.current = false + }, +} + +export const TEXT = 'TEXT' +export const ERROR_MESSAGE = 'ERROR_MESSAGE' +export const FALLBACK = 'FALLBACK' +export const sleep = (ms: number) => new Promise((resolve) => setTimeout(() => resolve(undefined), ms)) +export const queryKey = ['key'] as const +export const queryFn = () => sleep(10).then(() => ({ text: 'response' })) +export const boolean = Math.random() > 0.5 +export const select = (data: Awaited>) => data.text + +export class CustomError extends Error { + constructor(...args: ConstructorParameters) { + super(...args) + console.error(...args) + } +} +export class CustomNotError { + constructor(public message?: string) { + console.log(message) + } +} + +const isNeedSuspendGlobal = { current: true } + +export const Suspend = ({ during, toShow }: { during: number; toShow?: ReactNode }) => { + if (isNeedSuspendGlobal.current) { + throw new Promise((resolve) => + setTimeout(() => { + isNeedSuspendGlobal.current = false + resolve('resolved') + }, during) + ) + } + return toShow +} +Suspend.reset = () => { + isNeedSuspendGlobal.current = true +} diff --git a/packages/react/src/hooks/useIsomorphicLayoutEffect.spec.ts b/packages/utils/src/useIsomorphicLayoutEffect.spec.ts similarity index 100% rename from packages/react/src/hooks/useIsomorphicLayoutEffect.spec.ts rename to packages/utils/src/useIsomorphicLayoutEffect.spec.ts diff --git a/packages/react/src/hooks/useIsomorphicLayoutEffect.ts b/packages/utils/src/useIsomorphicLayoutEffect.ts similarity index 100% rename from packages/react/src/hooks/useIsomorphicLayoutEffect.ts rename to packages/utils/src/useIsomorphicLayoutEffect.ts diff --git a/packages/react/src/hooks/usePreservedCallback.spec.ts b/packages/utils/src/usePreservedCallback.spec.ts similarity index 100% rename from packages/react/src/hooks/usePreservedCallback.spec.ts rename to packages/utils/src/usePreservedCallback.spec.ts diff --git a/packages/react/src/hooks/usePreservedCallback.ts b/packages/utils/src/usePreservedCallback.ts similarity index 100% rename from packages/react/src/hooks/usePreservedCallback.ts rename to packages/utils/src/usePreservedCallback.ts diff --git a/packages/react/src/hooks/useTimeout.spec.tsx b/packages/utils/src/useTimeout.spec.tsx similarity index 95% rename from packages/react/src/hooks/useTimeout.spec.tsx rename to packages/utils/src/useTimeout.spec.tsx index f82f267e6..6db254b0e 100644 --- a/packages/react/src/hooks/useTimeout.spec.tsx +++ b/packages/utils/src/useTimeout.spec.tsx @@ -1,8 +1,8 @@ -import { sleep } from '@suspensive/test-utils' import { render, renderHook, screen } from '@testing-library/react' import ms from 'ms' import { useState } from 'react' -import { useTimeout } from '.' +import { sleep } from './test-utils' +import { useTimeout } from './useTimeout' describe('useTimeout', () => { it('should run given function once after given timeout', async () => { diff --git a/packages/react/src/hooks/useTimeout.ts b/packages/utils/src/useTimeout.ts similarity index 100% rename from packages/react/src/hooks/useTimeout.ts rename to packages/utils/src/useTimeout.ts diff --git a/configs/test-utils/tsconfig.json b/packages/utils/tsconfig.json similarity index 58% rename from configs/test-utils/tsconfig.json rename to packages/utils/tsconfig.json index c4a264bb3..f39554bc8 100644 --- a/configs/test-utils/tsconfig.json +++ b/packages/utils/tsconfig.json @@ -1,8 +1,7 @@ { "extends": "@suspensive/tsconfig/react-library.json", "include": [".", "./.eslintrc.cjs"], - "exclude": ["dist", "node_modules"], "compilerOptions": { - "types": ["@testing-library/jest-dom/vitest"] + "types": ["@testing-library/jest-dom/vitest", "vitest/globals"] } } diff --git a/configs/test-utils/tsup.config.ts b/packages/utils/tsup.config.ts similarity index 100% rename from configs/test-utils/tsup.config.ts rename to packages/utils/tsup.config.ts diff --git a/packages/utils/vitest.config.ts b/packages/utils/vitest.config.ts new file mode 100644 index 000000000..4bfcf0df6 --- /dev/null +++ b/packages/utils/vitest.config.ts @@ -0,0 +1,19 @@ +import codspeedPlugin from '@codspeed/vitest-plugin' +import { defineConfig } from 'vitest/config' +import packageJson from './package.json' + +export default defineConfig({ + plugins: process.env.CI === 'true' ? [codspeedPlugin()] : [], + test: { + name: packageJson.name, + dir: './src', + exclude: ['**/*.production.*'], + environment: 'jsdom', + globals: true, + setupFiles: './vitest.setup.ts', + benchmark: { outputJson: `benchmarks/${packageJson.version}.json` }, + coverage: { + provider: 'istanbul', + }, + }, +}) diff --git a/packages/utils/vitest.setup.ts b/packages/utils/vitest.setup.ts new file mode 100644 index 000000000..f07a27021 --- /dev/null +++ b/packages/utils/vitest.setup.ts @@ -0,0 +1,8 @@ +import '@testing-library/jest-dom/vitest' +import { cleanup } from '@testing-library/react' +import { afterEach, vi } from 'vitest' + +vi.stubEnv('NODE_ENV', 'development') +afterEach(() => { + cleanup() +}) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f7d6e21ca..41e0101dd 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -180,24 +180,6 @@ importers: specifier: ^5.1.3 version: 5.1.3(@types/eslint@8.56.10)(eslint-config-prettier@9.1.0(eslint@8.57.0))(eslint@8.57.0)(prettier@3.3.2) - configs/test-utils: - devDependencies: - '@suspensive/eslint-config': - specifier: workspace:* - version: link:../eslint-config - '@suspensive/tsconfig': - specifier: workspace:* - version: link:../tsconfig - '@suspensive/tsup': - specifier: workspace:* - version: link:../tsup - '@types/react': - specifier: ^18.3.3 - version: 18.3.3 - react: - specifier: ^18.3.1 - version: 18.3.1 - configs/tsconfig: {} configs/tsup: @@ -338,6 +320,10 @@ importers: version: 8.4.38 packages/cache: + dependencies: + '@suspensive/utils': + specifier: workspace:* + version: link:../utils devDependencies: '@suspensive/eslint-config': specifier: workspace:* @@ -345,9 +331,6 @@ importers: '@suspensive/react': specifier: workspace:* version: link:../react - '@suspensive/test-utils': - specifier: workspace:* - version: link:../../configs/test-utils '@suspensive/tsconfig': specifier: workspace:* version: link:../../configs/tsconfig @@ -368,6 +351,10 @@ importers: version: 18.3.1(react@18.3.1) packages/jotai: + dependencies: + '@suspensive/utils': + specifier: workspace:* + version: link:../utils devDependencies: '@suspensive/eslint-config': specifier: workspace:* @@ -395,13 +382,14 @@ importers: version: 18.3.1(react@18.3.1) packages/react: + dependencies: + '@suspensive/utils': + specifier: workspace:* + version: link:../utils devDependencies: '@suspensive/eslint-config': specifier: workspace:* version: link:../../configs/eslint-config - '@suspensive/test-utils': - specifier: workspace:* - version: link:../../configs/test-utils '@suspensive/tsconfig': specifier: workspace:* version: link:../../configs/tsconfig @@ -422,6 +410,10 @@ importers: version: 18.3.1(react@18.3.1) packages/react-await: + dependencies: + '@suspensive/utils': + specifier: workspace:* + version: link:../utils devDependencies: '@suspensive/eslint-config': specifier: workspace:* @@ -429,9 +421,6 @@ importers: '@suspensive/react': specifier: workspace:* version: link:../react - '@suspensive/test-utils': - specifier: workspace:* - version: link:../../configs/test-utils '@suspensive/tsconfig': specifier: workspace:* version: link:../../configs/tsconfig @@ -452,13 +441,14 @@ importers: version: 18.3.1(react@18.3.1) packages/react-image: + dependencies: + '@suspensive/utils': + specifier: workspace:* + version: link:../utils devDependencies: '@suspensive/eslint-config': specifier: workspace:* version: link:../../configs/eslint-config - '@suspensive/test-utils': - specifier: workspace:* - version: link:../../configs/test-utils '@suspensive/tsconfig': specifier: workspace:* version: link:../../configs/tsconfig @@ -489,6 +479,9 @@ importers: '@suspensive/react-query-5': specifier: workspace:^2.8.0 version: link:../react-query-5 + '@suspensive/utils': + specifier: workspace:* + version: link:../utils cli-table3: specifier: ^0.6.5 version: 0.6.5 @@ -502,9 +495,6 @@ importers: '@suspensive/react': specifier: workspace:* version: link:../react - '@suspensive/test-utils': - specifier: workspace:* - version: link:../../configs/test-utils '@suspensive/tsconfig': specifier: workspace:* version: link:../../configs/tsconfig @@ -528,6 +518,10 @@ importers: version: 18.3.1(react@18.3.1) packages/react-query-4: + dependencies: + '@suspensive/utils': + specifier: workspace:* + version: link:../utils devDependencies: '@suspensive/eslint-config': specifier: workspace:* @@ -535,9 +529,6 @@ importers: '@suspensive/react': specifier: workspace:* version: link:../react - '@suspensive/test-utils': - specifier: workspace:* - version: link:../../configs/test-utils '@suspensive/tsconfig': specifier: workspace:* version: link:../../configs/tsconfig @@ -561,6 +552,10 @@ importers: version: 18.3.1(react@18.3.1) packages/react-query-5: + dependencies: + '@suspensive/utils': + specifier: workspace:* + version: link:../utils devDependencies: '@suspensive/eslint-config': specifier: workspace:* @@ -568,9 +563,6 @@ importers: '@suspensive/react': specifier: workspace:* version: link:../react - '@suspensive/test-utils': - specifier: workspace:* - version: link:../../configs/test-utils '@suspensive/tsconfig': specifier: workspace:* version: link:../../configs/tsconfig @@ -593,6 +585,24 @@ importers: specifier: ^18.3.1 version: 18.3.1(react@18.3.1) + packages/utils: + devDependencies: + '@suspensive/eslint-config': + specifier: workspace:* + version: link:../../configs/eslint-config + '@suspensive/tsconfig': + specifier: workspace:* + version: link:../../configs/tsconfig + '@suspensive/tsup': + specifier: workspace:* + version: link:../../configs/tsup + '@types/react': + specifier: ^18.3.3 + version: 18.3.3 + react: + specifier: ^18.3.1 + version: 18.3.1 + websites/visualization: dependencies: '@suspensive/cache': @@ -1439,72 +1449,84 @@ packages: engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-arm@1.0.2': resolution: {integrity: sha512-iLWCvrKgeFoglQxdEwzu1eQV04o8YeYGFXtfWU26Zr2wWT3q3MTzC+QTCO3ZQfWd3doKHT4Pm2kRmLbupT+sZw==} engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-s390x@1.0.2': resolution: {integrity: sha512-cmhQ1J4qVhfmS6szYW7RT+gLJq9dH2i4maq+qyXayUSn9/3iY2ZeWpbAgSpSVbV2E1JUL2Gg7pwnYQ1h8rQIog==} engines: {glibc: '>=2.28', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-libvips-linux-x64@1.0.2': resolution: {integrity: sha512-E441q4Qdb+7yuyiADVi5J+44x8ctlrqn8XgkDTwr4qPJzWkaHwD489iZ4nGDgcuya4iMN3ULV6NwbhRZJ9Z7SQ==} engines: {glibc: '>=2.26', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-libvips-linuxmusl-arm64@1.0.2': resolution: {integrity: sha512-3CAkndNpYUrlDqkCM5qhksfE+qSIREVpyoeHIU6jd48SJZViAmznoQQLAv4hVXF7xyUB9zf+G++e2v1ABjCbEQ==} engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-libvips-linuxmusl-x64@1.0.2': resolution: {integrity: sha512-VI94Q6khIHqHWNOh6LLdm9s2Ry4zdjWJwH56WoiJU7NTeDwyApdZZ8c+SADC8OH98KWNQXnE01UdJ9CSfZvwZw==} engines: {musl: '>=1.2.2', npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-linux-arm64@0.33.4': resolution: {integrity: sha512-2800clwVg1ZQtxwSoTlHvtm9ObgAax7V6MTAB/hDT945Tfyy3hVkmiHpeLPCKYqYR1Gcmv1uDZ3a4OFwkdBL7Q==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] + libc: [glibc] '@img/sharp-linux-arm@0.33.4': resolution: {integrity: sha512-RUgBD1c0+gCYZGCCe6mMdTiOFS0Zc/XrN0fYd6hISIKcDUbAW5NtSQW9g/powkrXYm6Vzwd6y+fqmExDuCdHNQ==} engines: {glibc: '>=2.28', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm] os: [linux] + libc: [glibc] '@img/sharp-linux-s390x@0.33.4': resolution: {integrity: sha512-h3RAL3siQoyzSoH36tUeS0PDmb5wINKGYzcLB5C6DIiAn2F3udeFAum+gj8IbA/82+8RGCTn7XW8WTFnqag4tQ==} engines: {glibc: '>=2.31', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [s390x] os: [linux] + libc: [glibc] '@img/sharp-linux-x64@0.33.4': resolution: {integrity: sha512-GoR++s0XW9DGVi8SUGQ/U4AeIzLdNjHka6jidVwapQ/JebGVQIpi52OdyxCNVRE++n1FCLzjDovJNozif7w/Aw==} engines: {glibc: '>=2.26', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] + libc: [glibc] '@img/sharp-linuxmusl-arm64@0.33.4': resolution: {integrity: sha512-nhr1yC3BlVrKDTl6cO12gTpXMl4ITBUZieehFvMntlCXFzH2bvKG76tBL2Y/OqhupZt81pR7R+Q5YhJxW0rGgQ==} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [arm64] os: [linux] + libc: [musl] '@img/sharp-linuxmusl-x64@0.33.4': resolution: {integrity: sha512-uCPTku0zwqDmZEOi4ILyGdmW76tH7dm8kKlOIV1XC5cLyJ71ENAAqarOHQh0RLfpIpbV5KOpXzdU6XkJtS0daw==} engines: {musl: '>=1.2.2', node: ^18.17.0 || ^20.3.0 || >=21.0.0, npm: '>=9.6.5', pnpm: '>=7.1.0', yarn: '>=3.2.0'} cpu: [x64] os: [linux] + libc: [musl] '@img/sharp-wasm32@0.33.4': resolution: {integrity: sha512-Bmmauh4sXUsUqkleQahpdNXKvo+wa1V9KhT2pDA4VJGKwnKMJXiSTGphn0gnJrlooda0QxCtXc6RX1XAU6hMnQ==} @@ -1640,24 +1662,28 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@napi-rs/simple-git-linux-arm64-musl@0.1.9': resolution: {integrity: sha512-KQozUoNXrxrB8k741ncWXSiMbjl1AGBGfZV21PANzUM8wH4Yem2bg3kfglYS/QIx3udspsT35I9abu49n7D1/w==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@napi-rs/simple-git-linux-x64-gnu@0.1.9': resolution: {integrity: sha512-O/Niui5mnHPcK3iYC3ui8wgERtJWsQ3Y74W/09t0bL/3dgzGMl4oQt0qTj9dWCsnoGsIEYHPzwCBp/2vqYp/pw==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@napi-rs/simple-git-linux-x64-musl@0.1.9': resolution: {integrity: sha512-L9n+e8Wn3hKr3RsIdY8GaB+ry4xZ4BaGwyKExgoB8nDGQuRUY9oP6p0WA4hWfJvJnU1H6hvo36a5UFPReyBO7A==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@napi-rs/simple-git-win32-arm64-msvc@0.1.9': resolution: {integrity: sha512-Z6Ja/SZK+lMvRWaxj7wjnvSbAsGrH006sqZo8P8nxKUdZfkVvoCaAWr1r0cfkk2Z3aijLLtD+vKeXGlUPH6gGQ==} @@ -1698,24 +1724,28 @@ packages: engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [glibc] '@next/swc-linux-arm64-musl@14.2.3': resolution: {integrity: sha512-0D4/oMM2Y9Ta3nGuCcQN8jjJjmDPYpHX9OJzqk42NZGJocU2MqhBq5tWkJrUQOQY9N+In9xOdymzapM09GeiZw==} engines: {node: '>= 10'} cpu: [arm64] os: [linux] + libc: [musl] '@next/swc-linux-x64-gnu@14.2.3': resolution: {integrity: sha512-ENPiNnBNDInBLyUU5ii8PMQh+4XLr4pG51tOp6aJ9xqFQ2iRI6IH0Ds2yJkAzNV1CfyagcyzPfROMViS2wOZ9w==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [glibc] '@next/swc-linux-x64-musl@14.2.3': resolution: {integrity: sha512-BTAbq0LnCbF5MtoM7I/9UeUu/8ZBY0i8SFjUMCbPDOLv+un67e2JgyN4pmgfXBwy/I+RHu8q+k+MCkDN6P9ViQ==} engines: {node: '>= 10'} cpu: [x64] os: [linux] + libc: [musl] '@next/swc-win32-arm64-msvc@14.2.3': resolution: {integrity: sha512-AEHIw/dhAMLNFJFJIJIyOFDzrzI5bAjI9J26gbO5xhAKHYTZ9Or04BesFPXiAYXDNdrwTP2dQceYA4dL1geu8A==} @@ -1818,46 +1848,55 @@ packages: resolution: {integrity: sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==} cpu: [arm] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm-musleabihf@4.18.0': resolution: {integrity: sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==} cpu: [arm] os: [linux] + libc: [musl] '@rollup/rollup-linux-arm64-gnu@4.18.0': resolution: {integrity: sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==} cpu: [arm64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-arm64-musl@4.18.0': resolution: {integrity: sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==} cpu: [arm64] os: [linux] + libc: [musl] '@rollup/rollup-linux-powerpc64le-gnu@4.18.0': resolution: {integrity: sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==} cpu: [ppc64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-riscv64-gnu@4.18.0': resolution: {integrity: sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==} cpu: [riscv64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-s390x-gnu@4.18.0': resolution: {integrity: sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==} cpu: [s390x] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-gnu@4.18.0': resolution: {integrity: sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==} cpu: [x64] os: [linux] + libc: [glibc] '@rollup/rollup-linux-x64-musl@4.18.0': resolution: {integrity: sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==} cpu: [x64] os: [linux] + libc: [musl] '@rollup/rollup-win32-arm64-msvc@4.18.0': resolution: {integrity: sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==}