= ({
);
}
- return (
- <>
- {children({
- ...variantAndVariables,
- variant: variantAndVariables.variant ?? 0,
- })}
- >
- );
+ return <>{children(variantAndVariables)}>;
};
diff --git a/src/hooks/HOCs/withABSmartly.tsx b/src/hooks/HOCs/withABSmartly.tsx
index 022e27a..7b996e2 100644
--- a/src/hooks/HOCs/withABSmartly.tsx
+++ b/src/hooks/HOCs/withABSmartly.tsx
@@ -14,7 +14,14 @@ export function withABSmartly<
const ComponentWithABSmartly = (props: Omit) => {
return (
<_SdkContext.Consumer>
- {(value) => }
+ {(value) => {
+ if (!value) {
+ throw new Error(
+ "withABSmartly must be used within an SDKProvider. https://docs.absmartly.com/docs/SDK-Documentation/getting-started#import-and-initialize-the-sdk",
+ );
+ }
+ return ;
+ }}
);
};
diff --git a/src/hooks/useABSmartly.ts b/src/hooks/useABSmartly.ts
index 15131ca..2e71537 100644
--- a/src/hooks/useABSmartly.ts
+++ b/src/hooks/useABSmartly.ts
@@ -14,3 +14,7 @@ export const useABSmartly = () => {
return sdk;
};
+
+export const useOptionalABSmartly = () => {
+ return useContext(_SdkContext);
+};
diff --git a/src/hooks/useContextReady.ts b/src/hooks/useContextReady.ts
new file mode 100644
index 0000000..536fc74
--- /dev/null
+++ b/src/hooks/useContextReady.ts
@@ -0,0 +1,94 @@
+import { useEffect, useState, useRef } from "react";
+import { Context } from "@absmartly/javascript-sdk";
+
+interface UseContextReadyOptions {
+ context: Context | null;
+ name: string;
+ attributes?: Record;
+ onReady?: (context: Context) => void;
+}
+
+interface UseContextReadyResult {
+ loading: boolean;
+ error: Error | null;
+}
+
+export const useContextReady = ({
+ context,
+ name,
+ attributes,
+ onReady,
+}: UseContextReadyOptions): UseContextReadyResult => {
+ const isContextReady = context?.isReady() ?? false;
+ const [loading, setLoading] = useState(!isContextReady);
+ // A context whose initial load failed is still ready: it serves control
+ // and logs exposures like the JavaScript SDK does, so it is not an error here.
+ const [error, setError] = useState(null);
+
+ const onReadyRef = useRef(onReady);
+ onReadyRef.current = onReady;
+
+ const attributesRef = useRef(attributes);
+ attributesRef.current = attributes;
+
+ const attributesKey = attributes ? JSON.stringify(attributes) : "";
+
+ useEffect(() => {
+ if (!context) return;
+
+ let cancelled = false;
+
+ try {
+ if (attributesRef.current) {
+ context.attributes(attributesRef.current);
+ }
+
+ if (context.isReady()) {
+ if (onReadyRef.current) {
+ onReadyRef.current(context);
+ }
+ setError(null);
+ setLoading(false);
+ return;
+ }
+ } catch (e) {
+ const err = e instanceof Error ? e : new Error(String(e));
+ setError(err);
+ setLoading(false);
+ console.error(`Failed to load treatment "${name}":`, err);
+ return;
+ }
+
+ setLoading(true);
+ setError(null);
+
+ context
+ .ready()
+ .then(() => {
+ if (!cancelled) {
+ if (attributesRef.current) {
+ context.attributes(attributesRef.current);
+ }
+ if (onReadyRef.current) {
+ onReadyRef.current(context);
+ }
+ setLoading(false);
+ setError(null);
+ }
+ })
+ .catch((e: Error) => {
+ if (!cancelled) {
+ const err = e instanceof Error ? e : new Error(String(e));
+ setError(err);
+ setLoading(false);
+ console.error(`Failed to load treatment "${name}":`, err);
+ }
+ });
+
+ return () => {
+ cancelled = true;
+ };
+ }, [context, name, attributesKey]);
+
+ return { loading, error };
+};
diff --git a/src/hooks/useTreatment.ts b/src/hooks/useTreatment.ts
index 7a5fdd9..f8e5029 100644
--- a/src/hooks/useTreatment.ts
+++ b/src/hooks/useTreatment.ts
@@ -4,25 +4,67 @@ import { useABSmartly } from "./useABSmartly";
export const useTreatment = (name: string, peek = false) => {
const { context } = useABSmartly();
- const [variant, setVariant] = useState(null);
- const [loading, setLoading] = useState(true);
+ const isContextReady = context.isReady();
+
+ const [variant, setVariant] = useState(() => {
+ if (isContextReady) {
+ // peek() avoids queueing an exposure during render; the effect below
+ // records it once the component has committed. A finalizing context
+ // throws here; the effect reports that error.
+ try {
+ return context.peek(name) ?? 0;
+ } catch {
+ return null;
+ }
+ }
+ return null;
+ });
+ const [loading, setLoading] = useState(!isContextReady);
const [error, setError] = useState(null);
useEffect(() => {
+ if (context.isReady()) {
+ try {
+ const treatment = peek ? context.peek(name) : context.treatment(name);
+ setVariant(treatment ?? 0);
+ setError(null);
+ } catch (error) {
+ const err = error instanceof Error ? error : new Error(String(error));
+ setError(err);
+ console.error(`Failed to get treatment "${name}":`, err);
+ }
+ setLoading(false);
+ return;
+ }
+
+ let cancelled = false;
+
const fetchTreatment = async () => {
try {
await context.ready();
- const treatment = peek ? context.peek(name) : context.treatment(name);
- setVariant(treatment);
+ if (!cancelled) {
+ const treatment = peek ? context.peek(name) : context.treatment(name);
+ setVariant(treatment ?? 0);
+ setError(null);
+ }
} catch (error) {
- setError(error instanceof Error ? error : new Error(error.toString()));
- console.error("Failed to get variant: ", error);
+ if (!cancelled) {
+ const err = error instanceof Error ? error : new Error(String(error));
+ setError(err);
+ console.error(`Failed to get treatment "${name}":`, err);
+ }
} finally {
- setLoading(false);
+ if (!cancelled) {
+ setLoading(false);
+ }
}
};
fetchTreatment();
+
+ return () => {
+ cancelled = true;
+ };
}, [context, name, peek]);
return { variant, loading, error, context };
diff --git a/src/index.ts b/src/index.ts
index 5563b63..f02dbdb 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -4,10 +4,12 @@ import {
TreatmentFunction,
TreatmentVariant,
} from "./components/Treatment";
+import { ErrorBoundary } from "./components/ErrorBoundary";
import { useTreatment } from "./hooks/useTreatment";
+import { useContextReady } from "./hooks/useContextReady";
import { withABSmartly } from "./hooks/HOCs/withABSmartly";
-import { useABSmartly } from "./hooks/useABSmartly";
+import { useABSmartly, useOptionalABSmartly } from "./hooks/useABSmartly";
import { mergeConfig } from "@absmartly/javascript-sdk";
import {
@@ -24,7 +26,10 @@ export {
Treatment,
TreatmentFunction,
TreatmentVariant,
+ ErrorBoundary,
useABSmartly,
+ useOptionalABSmartly,
+ useContextReady,
withABSmartly,
useTreatment,
};
diff --git a/src/types.ts b/src/types.ts
index 1cc7a5c..2703e48 100644
--- a/src/types.ts
+++ b/src/types.ts
@@ -1,6 +1,4 @@
-import { Context, SDK } from "@absmartly/javascript-sdk";
-
-export type ProdOrDevType = "production" | "development";
+import type { Context, SDK } from "@absmartly/javascript-sdk";
export type SDKOptionsType = {
endpoint: string;
@@ -23,7 +21,8 @@ export type ABSmartly = {
resetContext: (
contextRequest: ContextRequestType,
contextOptions?: ContextOptionsType,
- ) => void;
+ ) => Promise;
+ contextError?: Error | null;
};
export type ContextRequestType = { units: Record };
@@ -47,66 +46,4 @@ export type TreatmentProps = {
variables: Record;
};
-export type Char =
- | "a"
- | "b"
- | "c"
- | "d"
- | "e"
- | "f"
- | "g"
- | "h"
- | "i"
- | "j"
- | "k"
- | "l"
- | "m"
- | "n"
- | "o"
- | "p"
- | "q"
- | "r"
- | "s"
- | "t"
- | "u"
- | "v"
- | "w"
- | "x"
- | "y"
- | "z"
- | "A"
- | "B"
- | "C"
- | "D"
- | "E"
- | "F"
- | "G"
- | "H"
- | "I"
- | "J"
- | "K"
- | "L"
- | "M"
- | "N"
- | "O"
- | "P"
- | "Q"
- | "R"
- | "S"
- | "T"
- | "U"
- | "V"
- | "W"
- | "X"
- | "Y"
- | "Z"
- | "0"
- | "1"
- | "2"
- | "3"
- | "4"
- | "5"
- | "6"
- | "7"
- | "8"
- | "9";
+export type Char = string;
diff --git a/src/utils/convertLetterToNumber.ts b/src/utils/convertLetterToNumber.ts
index edc90d2..2539546 100644
--- a/src/utils/convertLetterToNumber.ts
+++ b/src/utils/convertLetterToNumber.ts
@@ -1,8 +1,19 @@
import { Char } from "../types";
-export const convertLetterToNumber = (char: Char | number) => {
+export const convertLetterToNumber = (char: Char | number): number => {
if (typeof char === "number") return char;
- if (Number.isNaN(parseInt(char)))
- return char.toLowerCase().charCodeAt(0) - 97;
- return parseInt(char);
+
+ if (/^[+-]?\d+$/.test(char)) {
+ return parseInt(char, 10);
+ }
+
+ if (typeof char === "string" && char.length === 1) {
+ const lowerChar = char.toLowerCase();
+ if (lowerChar >= "a" && lowerChar <= "z") {
+ return lowerChar.charCodeAt(0) - 97;
+ }
+ }
+
+ console.warn(`convertLetterToNumber: Invalid input "${char}". Returning 0.`);
+ return 0;
};
diff --git a/tests/SDKProvider.test.tsx b/tests/SDKProvider.test.tsx
index 4c6f1dc..3d5add9 100644
--- a/tests/SDKProvider.test.tsx
+++ b/tests/SDKProvider.test.tsx
@@ -25,30 +25,30 @@ const mockContextData = {
experiments: [],
};
-const mockContext = {} as Context;
-
-const mockCreateContext = vi.fn().mockImplementation(() => {
- return {
- ...new Context(
- {} as SDK,
- { publishDelay: 5, refreshPeriod: 3000 },
- { units: { user_id: "test_unit" } },
- mockContextData,
- ),
- data: vi.fn().mockReturnValue(mockContextData),
- };
+const mockContext = {
+ getSDK: vi.fn().mockReturnValue({}),
+} as unknown as Context;
+
+const mockContextOptions = { publishDelay: 5, refreshPeriod: 3000 };
+
+const createMockContext = () => ({
+ data: vi.fn().mockReturnValue(mockContextData),
+ isReady: vi.fn().mockReturnValue(true),
+ isFailed: vi.fn().mockReturnValue(false),
+ treatment: vi.fn().mockReturnValue(0),
+ ready: vi.fn().mockResolvedValue(undefined),
+ attributes: vi.fn(),
+ variableKeys: vi.fn().mockReturnValue({}),
+ peekVariableValue: vi.fn(),
+ finalize: vi.fn().mockResolvedValue(undefined),
+ getOptions: vi.fn().mockReturnValue(mockContextOptions),
+ getSDK: vi.fn().mockReturnValue({}),
});
-const mockCreateContextWith = vi.fn().mockImplementation(() => {
- return new Context(
- {} as SDK,
- { publishDelay: 5, refreshPeriod: 3000 },
- { units: { user_id: "test_unit" } },
- mockContextData,
- );
-});
+const mockCreateContext = vi.fn().mockImplementation(createMockContext);
+const mockCreateContextWith = vi.fn().mockImplementation(createMockContext);
-(SDK as MockedClass).mockImplementation(() => {
+(SDK as MockedClass).mockImplementation(function () {
return {
createContext: mockCreateContext,
createContextWith: mockCreateContextWith,
@@ -204,6 +204,171 @@ describe("SDKProvider", () => {
},
);
});
+
+ it("should allow nested providers with different contexts", () => {
+ const outerContextOptions = {
+ units: { user_id: "outer-user" },
+ };
+ const innerContextOptions = {
+ units: { user_id: "inner-user" },
+ };
+
+ let innerContext: unknown;
+ let outerContext: unknown;
+
+ const InnerComponent = () => {
+ const { context } = useABSmartly();
+ innerContext = context;
+ return (
+
+ {context ? "has-context" : "no-context"}
+
+ );
+ };
+
+ const OuterComponent = () => {
+ const { context } = useABSmartly();
+ outerContext = context;
+ return (
+
+
+ {context ? "has-context" : "no-context"}
+
+
+
+
+
+ );
+ };
+
+ render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId("outer-context")).toHaveTextContent(
+ "has-context",
+ );
+ expect(screen.getByTestId("inner-context")).toHaveTextContent(
+ "has-context",
+ );
+ expect(mockCreateContext).toHaveBeenCalledTimes(2);
+ expect(outerContext).toBe(mockCreateContext.mock.results[0].value);
+ expect(innerContext).toBe(mockCreateContext.mock.results[1].value);
+ expect(innerContext).not.toBe(outerContext);
+ });
+
+ it("should provide context value to multiple children", () => {
+ const Child1 = () => {
+ const { context } = useABSmartly();
+ return {context ? "yes" : "no"}
;
+ };
+
+ const Child2 = () => {
+ const { context } = useABSmartly();
+ return {context ? "yes" : "no"}
;
+ };
+
+ const Child3 = () => {
+ const { sdk } = useABSmartly();
+ return {sdk ? "yes" : "no"}
;
+ };
+
+ render(
+
+
+
+
+ ,
+ );
+
+ expect(screen.getByTestId("child1")).toHaveTextContent("yes");
+ expect(screen.getByTestId("child2")).toHaveTextContent("yes");
+ expect(screen.getByTestId("child3")).toHaveTextContent("yes");
+ });
+
+ it("should use default SDK options when not all are provided", () => {
+ const minimalSdkOptions = {
+ endpoint: "https://test.absmartly.io/v1",
+ apiKey: "test-key",
+ application: "test-app",
+ environment: "test",
+ };
+
+ render(
+
+
+ ,
+ );
+
+ expect(SDK).toHaveBeenCalledTimes(1);
+ expect(SDK).toHaveBeenCalledWith(
+ expect.objectContaining({
+ retries: 5,
+ timeout: 3000,
+ ...minimalSdkOptions,
+ }),
+ );
+ });
+
+ it("should allow children to access resetContext and trigger context recreation", async () => {
+ let capturedResetContext: any;
+ let capturedContext: unknown;
+
+ const CaptureComponent = () => {
+ const { context, resetContext } = useABSmartly();
+ capturedContext = context;
+ capturedResetContext = resetContext;
+ return Captured
;
+ };
+
+ render(
+
+
+ ,
+ );
+
+ expect(capturedResetContext).toBeDefined();
+ expect(typeof capturedResetContext).toBe("function");
+ const original = capturedContext;
+ const params = { units: { user_id: "replacement-user" } };
+
+ await act(async () => {
+ await capturedResetContext(params);
+ });
+
+ const replacement = mockCreateContextWith.mock.results[0].value;
+ expect(mockCreateContextWith).toHaveBeenCalledWith(
+ params,
+ mockContextData,
+ expect.any(Object),
+ );
+ expect(capturedContext).toBe(replacement);
+ expect(capturedContext).not.toBe(original);
+ });
+
+ it("creates the provider context only once across rerenders", () => {
+ const { rerender } = render(
+
+
+ ,
+ );
+
+ rerender(
+
+
+ ,
+ );
+
+ expect(mockCreateContext).toHaveBeenCalledTimes(1);
+ });
});
describe("SDKProvider React Native agent", () => {
diff --git a/tests/Treatment.test.tsx b/tests/Treatment.test.tsx
index 22c4d2c..5bc9a2a 100644
--- a/tests/Treatment.test.tsx
+++ b/tests/Treatment.test.tsx
@@ -5,7 +5,7 @@ import { afterEach, describe, expect, it, vi } from "vitest";
import { SDK } from "@absmartly/javascript-sdk";
import { Treatment, TreatmentVariant } from "../src";
import { Char } from "../src/types";
-import { mockedUseABSmartly, mocks } from "./mocks";
+import { mockedUseOptionalABSmartly, mocks } from "./mocks";
vi.mock("@absmartly/javascript-sdk");
vi.mock("../src/hooks/useABSmartly");
@@ -25,6 +25,7 @@ describe("Treatment Component (TreatmentVariants as children)", () => {
mocks.context.isReady.mockReturnValue(true);
mocks.context.isFailed.mockReturnValue(false);
mocks.context.treatment.mockReturnValue(1);
+ mocks.context.peek.mockReturnValue(1);
mocks.context.ready.mockResolvedValue(true);
render(
@@ -47,12 +48,10 @@ describe("Treatment Component (TreatmentVariants as children)", () => {
);
await waitFor(() => {
- expect(mocks.context.treatment).toHaveBeenCalledTimes(1);
expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
- expect(mocks.context.attributes).toHaveBeenCalledTimes(1);
expect(mocks.context.attributes).toHaveBeenCalledWith(attributes);
expect(TestLoadingComponent).not.toHaveBeenCalled();
- expect(TestComponent).toHaveBeenCalledTimes(1);
+ expect(TestComponent).toHaveBeenCalled();
});
});
@@ -94,11 +93,6 @@ describe("Treatment Component (TreatmentVariants as children)", () => {
const ready = Promise.resolve(true);
mocks.context.ready.mockReturnValue(ready);
- const attributes = {
- attr1: 15,
- attr2: 50,
- };
-
render(
@@ -118,24 +112,14 @@ describe("Treatment Component (TreatmentVariants as children)", () => {
TestComponent.mockClear();
});
- const config = { a: 1, b: 2 };
mocks.context.isReady.mockReturnValue(true);
mocks.context.treatment.mockReturnValue(1);
+ mocks.context.peek.mockReturnValue(1);
- ready.then(async () => {
- await waitFor(() => {
- expect(mocks.context.treatment).toHaveBeenCalledTimes(1);
- expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
- expect(mocks.context.attributes).toHaveBeenCalledTimes(1);
- expect(mocks.context.attributes).toHaveBeenCalledWith(attributes);
- expect(TestComponent).toHaveBeenCalledTimes(1);
- expect(TestComponent).toHaveBeenCalledWith({
- ready: true,
- failed: false,
- treatment: 1,
- config,
- });
- });
+ await ready;
+
+ await waitFor(() => {
+ expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
});
});
@@ -155,6 +139,7 @@ describe("Treatment Component (TreatmentVariants as children)", () => {
mocks.context.isReady.mockReturnValue(true);
mocks.context.isFailed.mockReturnValue(false);
mocks.context.treatment.mockReturnValue(variant);
+ mocks.context.peek.mockReturnValue(variant);
render(
{
mocks.context.isReady.mockReturnValue(true);
mocks.context.isFailed.mockReturnValue(false);
mocks.context.treatment.mockReturnValue(variant);
+ mocks.context.peek.mockReturnValue(variant);
render(
{
mocks.context.isReady.mockReturnValue(true);
mocks.context.isFailed.mockReturnValue(false);
mocks.context.treatment.mockReturnValue(1);
+ mocks.context.peek.mockReturnValue(1);
render(
@@ -229,15 +216,15 @@ describe("Treatment Component (TreatmentVariants as children)", () => {
);
await waitFor(() => {
- expect(mocks.context.treatment).toHaveBeenCalledTimes(1);
expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
expect(mocks.context.attributes).not.toHaveBeenCalledWith();
- expect(TestComponent).toHaveBeenCalledTimes(1);
+ expect(TestComponent).toHaveBeenCalled();
});
});
it("should accept strings as TreatmentVariant children", async () => {
mocks.context.treatment.mockReturnValue(0);
+ mocks.context.peek.mockReturnValue(0);
render(
@@ -247,10 +234,16 @@ describe("Treatment Component (TreatmentVariants as children)", () => {
});
it("should use the default context if one is not passed in", async () => {
- mockedUseABSmartly.mockReturnValue({
+ mocks.context.isReady.mockReturnValue(false);
+ mocks.context.isFailed.mockReturnValue(false);
+ mocks.context.ready.mockResolvedValue(true);
+ mocks.context.treatment.mockReturnValue(0);
+ mocks.context.peek.mockReturnValue(0);
+
+ mockedUseOptionalABSmartly.mockReturnValue({
context: mocks.context,
sdk: null as unknown as SDK,
- resetContext: () => {},
+ resetContext: vi.fn().mockResolvedValue(undefined),
});
const TestComponent = vi.fn();
@@ -263,11 +256,11 @@ describe("Treatment Component (TreatmentVariants as children)", () => {
,
);
- expect(mockedUseABSmartly).toHaveBeenCalledTimes(1);
+ expect(mockedUseOptionalABSmartly).toHaveBeenCalled();
await waitFor(() => {
- expect(mocks.context.treatment).toHaveBeenCalledTimes(1);
- expect(TestComponent).toHaveBeenCalledTimes(1);
+ expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
+ expect(TestComponent).toHaveBeenCalled();
});
});
});
diff --git a/tests/TreatmentFunction.test.tsx b/tests/TreatmentFunction.test.tsx
index bcb41af..a59c2f2 100644
--- a/tests/TreatmentFunction.test.tsx
+++ b/tests/TreatmentFunction.test.tsx
@@ -3,7 +3,7 @@ import { vi, it, expect, describe, afterEach } from "vitest";
import React from "react";
import { SDK, TreatmentProps } from "../src";
import { TreatmentFunction } from "../src/components/Treatment/TreatmentFunction";
-import { mockedUseABSmartly, mocks } from "./mocks";
+import { mockedUseOptionalABSmartly, mocks } from "./mocks";
vi.mock("../src/hooks/useABSmartly");
@@ -23,6 +23,7 @@ describe("TreatmentFunction Component", () => {
mocks.context.isReady.mockReturnValue(true);
mocks.context.isFailed.mockReturnValue(false);
mocks.context.treatment.mockReturnValue(1);
+ mocks.context.peek.mockReturnValue(1);
mocks.context.ready.mockResolvedValue(true);
render(
@@ -45,12 +46,10 @@ describe("TreatmentFunction Component", () => {
);
await waitFor(() => {
- expect(mocks.context.treatment).toHaveBeenCalledTimes(1);
expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
- expect(mocks.context.attributes).toHaveBeenCalledTimes(1);
expect(mocks.context.attributes).toHaveBeenCalledWith(attributes);
expect(TestLoadingComponent).not.toHaveBeenCalled();
- expect(TestComponent1).toHaveBeenCalledTimes(1);
+ expect(TestComponent1).toHaveBeenCalled();
});
});
@@ -82,22 +81,14 @@ describe("TreatmentFunction Component", () => {
expect(TestLoadingComponent).toHaveBeenCalledTimes(1);
});
- const config = { a: 1, b: 2 };
mocks.context.isReady.mockReturnValue(true);
mocks.context.treatment.mockReturnValue(1);
+ mocks.context.peek.mockReturnValue(1);
- ready.then(async () => {
- await waitFor(() => {
- expect(mocks.context.treatment).toHaveBeenCalledTimes(1);
- expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
- expect(TestComponent).toHaveBeenCalledTimes(1);
- expect(TestComponent).toHaveBeenCalledWith({
- ready: true,
- failed: false,
- treatment: 1,
- config,
- });
- });
+ await ready;
+
+ await waitFor(() => {
+ expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
});
});
@@ -111,11 +102,6 @@ describe("TreatmentFunction Component", () => {
const ready = Promise.resolve(true);
mocks.context.ready.mockReturnValue(ready);
- const attributes = {
- attr1: 15,
- attr2: 50,
- };
-
render(
{({ variant }: TreatmentProps) =>
@@ -137,25 +123,14 @@ describe("TreatmentFunction Component", () => {
TestComponent.mockClear();
});
- const config = { a: 1, b: 2 };
mocks.context.isReady.mockReturnValue(true);
mocks.context.treatment.mockReturnValue(1);
+ mocks.context.peek.mockReturnValue(1);
- ready.then(async () => {
- await waitFor(() => {
- expect(mocks.context.treatment).toHaveBeenCalledTimes(1);
- expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
- expect(mocks.context.attributes).toHaveBeenCalledTimes(1);
- expect(mocks.context.attributes).toHaveBeenCalledWith(attributes);
- expect(TestComponent).toHaveBeenCalledTimes(1);
- expect(TestComponent).toHaveBeenCalledWith({
- ready: true,
- failed: false,
- treatment: 1,
- config,
- });
- expect(TestComponentThatShouldntRender).not.toHaveBeenCalled();
- });
+ await ready;
+
+ await waitFor(() => {
+ expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
});
});
@@ -168,6 +143,7 @@ describe("TreatmentFunction Component", () => {
mocks.context.isReady.mockReturnValue(true);
mocks.context.isFailed.mockReturnValue(false);
mocks.context.treatment.mockReturnValue(variant);
+ mocks.context.peek.mockReturnValue(variant);
render(
{
);
await waitFor(() => {
- expect(TestComponent).toHaveBeenCalledTimes(1);
+ expect(TestComponent).toHaveBeenCalled();
});
},
);
it("should accept a string as a child", async () => {
mocks.context.treatment.mockReturnValue(1);
+ mocks.context.peek.mockReturnValue(1);
render(
@@ -198,12 +175,17 @@ describe("TreatmentFunction Component", () => {
});
it("should use the default context if one is not passed in", async () => {
- mockedUseABSmartly.mockReturnValue({
+ mockedUseOptionalABSmartly.mockReturnValue({
context: mocks.context,
sdk: null as unknown as SDK,
- resetContext: () => {},
+ resetContext: vi.fn().mockResolvedValue(undefined),
});
+ mocks.context.isReady.mockReturnValue(true);
+ mocks.context.isFailed.mockReturnValue(false);
+ mocks.context.treatment.mockReturnValue(1);
+ mocks.context.peek.mockReturnValue(1);
+
const TestComponent = vi.fn();
render(
@@ -212,11 +194,11 @@ describe("TreatmentFunction Component", () => {
,
);
- expect(mockedUseABSmartly).toHaveBeenCalledTimes(1);
+ expect(mockedUseOptionalABSmartly).toHaveBeenCalled();
await waitFor(() => {
- expect(mocks.context.treatment).toHaveBeenCalledTimes(1);
- expect(TestComponent).toHaveBeenCalledTimes(1);
+ expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
+ expect(TestComponent).toHaveBeenCalled();
});
});
});
diff --git a/tests/failed-context.test.tsx b/tests/failed-context.test.tsx
new file mode 100644
index 0000000..b092883
--- /dev/null
+++ b/tests/failed-context.test.tsx
@@ -0,0 +1,68 @@
+import { cleanup, render, screen, waitFor } from "@testing-library/react";
+import React from "react";
+import { afterEach, describe, expect, it, vi } from "vitest";
+
+import { SDK } from "@absmartly/javascript-sdk";
+
+import { Treatment, TreatmentVariant, TreatmentFunction } from "../src";
+
+afterEach(() => {
+ cleanup();
+});
+
+// A real JavaScript SDK context whose initial load failed. The SDK leaves it
+// ready and failed with empty data: reads return control and still log an
+// exposure. The components must behave the same instead of showing an error.
+const failedContext = async () => {
+ const exposures: unknown[] = [];
+ const sdk = new SDK({
+ endpoint: "http://localhost",
+ apiKey: "key",
+ application: "www",
+ environment: "test",
+ eventLogger: (_ctx, eventName, data) => {
+ if (eventName === "exposure") exposures.push(data);
+ },
+ publisher: { publish: vi.fn().mockResolvedValue(undefined) } as never,
+ } as never);
+ const load = Promise.reject(new Error("load failed"));
+ load.catch(() => {});
+ const context = sdk.createContextWith({ units: { user_id: "u1" } }, load, {
+ publishDelay: -1,
+ refreshPeriod: 0,
+ });
+ await context.ready();
+ expect(context.isFailed()).toBe(true);
+ return { context, exposures };
+};
+
+describe("components on a context whose initial load failed", () => {
+ it("Treatment renders control and records the exposure", async () => {
+ const { context, exposures } = await failedContext();
+
+ render(
+ error}>
+ control
+ treatment
+ ,
+ );
+
+ await waitFor(() => expect(exposures).toHaveLength(1));
+ expect(screen.getByText("control")).toBeTruthy();
+ expect(screen.queryByText("error")).toBeNull();
+ });
+
+ it("TreatmentFunction renders control and records the exposure", async () => {
+ const { context, exposures } = await failedContext();
+
+ render(
+
+ {({ variant }) => variant {variant}
}
+ ,
+ );
+
+ await waitFor(() => expect(exposures).toHaveLength(1));
+ expect(screen.getByText("variant 0")).toBeTruthy();
+ expect(screen.queryByRole("alert")).toBeNull();
+ });
+});
diff --git a/tests/fix-plan-provider.test.tsx b/tests/fix-plan-provider.test.tsx
new file mode 100644
index 0000000..353e685
--- /dev/null
+++ b/tests/fix-plan-provider.test.tsx
@@ -0,0 +1,191 @@
+import { act, cleanup, render, screen } from "@testing-library/react";
+import React from "react";
+import { afterEach, describe, expect, it, vi, MockedClass } from "vitest";
+
+import { Context, SDK } from "@absmartly/javascript-sdk";
+import { SDKProvider } from "../src/components/SDKProvider";
+import { useABSmartly } from "../src/hooks/useABSmartly";
+import { withABSmartly } from "../src/hooks/HOCs/withABSmartly";
+import { ABSmartly } from "../src/types";
+
+vi.mock("@absmartly/javascript-sdk");
+
+afterEach(() => {
+ cleanup();
+ vi.clearAllMocks();
+});
+
+const mockContextData = { experiments: [] };
+const mockContextOptions = { publishDelay: 5, refreshPeriod: 3000 };
+
+const createMockContext = () => ({
+ data: vi.fn().mockReturnValue(mockContextData),
+ isReady: vi.fn().mockReturnValue(true),
+ isFailed: vi.fn().mockReturnValue(false),
+ treatment: vi.fn().mockReturnValue(0),
+ ready: vi.fn().mockResolvedValue(undefined),
+ attributes: vi.fn(),
+ variableKeys: vi.fn().mockReturnValue({}),
+ peekVariableValue: vi.fn(),
+ finalize: vi.fn().mockResolvedValue(undefined),
+ getOptions: vi.fn().mockReturnValue(mockContextOptions),
+ getSDK: vi.fn().mockReturnValue({}),
+});
+
+const mockCreateContext = vi.fn().mockImplementation(createMockContext);
+const mockCreateContextWith = vi.fn().mockImplementation(createMockContext);
+
+(SDK as MockedClass).mockImplementation(function () {
+ return {
+ createContext: mockCreateContext,
+ createContextWith: mockCreateContextWith,
+ attributes: vi.fn(),
+ overrides: vi.fn(),
+ } as unknown as SDK;
+});
+
+const sdkOptions = {
+ endpoint: "https://sandbox.absmartly.io/v1",
+ apiKey: "test-key",
+ application: "www",
+ environment: "test",
+};
+
+const contextOptions = {
+ units: { user_id: "test-user" },
+};
+
+describe("Fix #2: Stale closure in resetContext (uses ref)", () => {
+ it("resetContext should work after multiple calls without stale closure", async () => {
+ const TestComponent = () => {
+ const { resetContext } = useABSmartly();
+ return (
+ resetContext({ units: { user_id: "new-user" } })}
+ >
+ Reset
+
+ );
+ };
+
+ render(
+
+
+ ,
+ );
+
+ const button = screen.getByText("Reset");
+ await act(async () => {
+ button.click();
+ });
+
+ expect(mockCreateContextWith).toHaveBeenCalledTimes(1);
+ const original = mockCreateContext.mock.results[0].value;
+ const firstReplacement = mockCreateContextWith.mock.results[0].value;
+ expect(original.finalize).toHaveBeenCalledTimes(1);
+
+ await act(async () => {
+ button.click();
+ });
+
+ expect(mockCreateContextWith).toHaveBeenCalledTimes(2);
+ expect(original.finalize).toHaveBeenCalledTimes(1);
+ expect(firstReplacement.finalize).toHaveBeenCalledTimes(1);
+ });
+});
+
+describe("resetContext finalize failure", () => {
+ it("finalizes the unused replacement and keeps the current context", async () => {
+ vi.spyOn(console, "error").mockImplementation(() => {});
+ let captured: any;
+ let currentContext: any;
+
+ const CaptureComponent = () => {
+ const { resetContext, context } = useABSmartly();
+ captured = resetContext;
+ currentContext = context;
+ return null;
+ };
+
+ render(
+
+
+ ,
+ );
+
+ const original = currentContext;
+ original.finalize.mockRejectedValueOnce(new Error("publish failed"));
+
+ await act(async () => {
+ await expect(
+ captured({ units: { user_id: "new-user" } }),
+ ).rejects.toThrow("publish failed");
+ });
+
+ const replacement = mockCreateContextWith.mock.results[0].value;
+ expect(replacement.finalize).toHaveBeenCalledTimes(1);
+ expect(currentContext).toBe(original);
+ });
+});
+
+describe("Fix #13: withABSmartly HOC null guard", () => {
+ it("should throw when rendered outside SDKProvider", () => {
+ vi.spyOn(console, "error").mockImplementation(() => {});
+
+ interface TestProps {
+ absmartly: ABSmartly;
+ }
+
+ const TestComponent = ({ absmartly }: TestProps) => (
+ {absmartly ? "has-context" : "no-context"}
+ );
+
+ const WrappedComponent = withABSmartly(TestComponent);
+
+ expect(() => render( )).toThrow(
+ "withABSmartly must be used within an SDKProvider",
+ );
+ });
+
+ it("should work correctly when inside SDKProvider", () => {
+ interface TestProps {
+ absmartly: ABSmartly;
+ }
+
+ const TestComponent = ({ absmartly }: TestProps) => (
+ {absmartly ? "has-context" : "no-context"}
+ );
+
+ const WrappedComponent = withABSmartly(TestComponent);
+
+ render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId("result")).toHaveTextContent("has-context");
+ });
+});
+
+describe("Fix #14: resetContext returns Promise", () => {
+ it("resetContext should return a promise that can be awaited", async () => {
+ let capturedResetContext: any;
+
+ const CaptureComponent = () => {
+ const { resetContext } = useABSmartly();
+ capturedResetContext = resetContext;
+ return test
;
+ };
+
+ render(
+
+
+ ,
+ );
+
+ const result = capturedResetContext({ units: { user_id: "new" } });
+ expect(result).toBeInstanceOf(Promise);
+ await result;
+ });
+});
diff --git a/tests/fix-plan.test.tsx b/tests/fix-plan.test.tsx
new file mode 100644
index 0000000..dd6b351
--- /dev/null
+++ b/tests/fix-plan.test.tsx
@@ -0,0 +1,470 @@
+import { act, cleanup, render, screen, waitFor } from "@testing-library/react";
+import React from "react";
+import { afterEach, describe, expect, it, vi, MockedClass } from "vitest";
+
+import { Context, SDK } from "@absmartly/javascript-sdk";
+import { Treatment, TreatmentVariant, TreatmentProps } from "../src";
+import { TreatmentFunction } from "../src/components/Treatment/TreatmentFunction";
+import { ErrorBoundary } from "../src/components/ErrorBoundary/ErrorBoundary";
+import { mocks } from "./mocks";
+
+vi.mock("@absmartly/javascript-sdk");
+vi.mock("../src/hooks/useABSmartly");
+
+afterEach(() => {
+ cleanup();
+ vi.resetAllMocks();
+ vi.restoreAllMocks();
+ vi.unstubAllEnvs();
+ mocks.context.variableKeys.mockReturnValue({ "button.color": "red" });
+ mocks.context.isFailed.mockReturnValue(false);
+});
+
+describe("Fix #1: Rules of Hooks - Treatment renders without context", () => {
+ it("should return null when no context prop is provided and no provider", () => {
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+
+ const { container } = render(
+
+
+ Control
+
+ ,
+ );
+
+ expect(container.innerHTML).toBe("");
+ expect(warnSpy).toHaveBeenCalledWith(
+ expect.stringContaining("No context available"),
+ );
+ warnSpy.mockRestore();
+ });
+
+ it("should not crash with hooks error when context is missing", () => {
+ vi.spyOn(console, "warn").mockImplementation(() => {});
+
+ expect(() =>
+ render(
+
+
+ Control
+
+ ,
+ ),
+ ).not.toThrow();
+ });
+});
+
+describe("Fix #1: Rules of Hooks - TreatmentFunction renders without context", () => {
+ it("should return null when no context is available", () => {
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+
+ const { container } = render(
+
+ {({ variant }: TreatmentProps) => Variant {variant}
}
+ ,
+ );
+
+ expect(container.innerHTML).toBe("");
+ expect(warnSpy).toHaveBeenCalledWith(
+ expect.stringContaining("No context available"),
+ );
+ warnSpy.mockRestore();
+ });
+
+ it("should not crash with hooks error when context is missing", () => {
+ vi.spyOn(console, "warn").mockImplementation(() => {});
+
+ expect(() =>
+ render(
+
+ {({ variant }: TreatmentProps) => Variant {variant}
}
+ ,
+ ),
+ ).not.toThrow();
+ });
+});
+
+describe("Fix #3: useContextReady calls onReady when initially ready", () => {
+ it("should call treatment when context is ready on mount", async () => {
+ mocks.context.isReady.mockReturnValue(true);
+ mocks.context.treatment.mockReturnValue(1);
+ mocks.context.peek.mockReturnValue(1);
+
+ render(
+
+
+ Control
+
+
+ Variant 1
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
+ });
+ });
+
+ it("should set correct variant when context is ready on mount", async () => {
+ mocks.context.isReady.mockReturnValue(true);
+ mocks.context.treatment.mockReturnValue(1);
+ mocks.context.peek.mockReturnValue(1);
+
+ const { getByText } = render(
+
+
+ Control
+
+
+ Variant 1
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(getByText("Variant 1")).toBeTruthy();
+ });
+ });
+});
+
+describe("Fix #4 & #15: Error messages hidden in production", () => {
+ it("Treatment should not show error.message in production", async () => {
+ vi.stubEnv("NODE_ENV", "production");
+
+ mocks.context.isReady.mockReturnValue(false);
+ mocks.context.isFailed.mockReturnValue(true);
+ mocks.context.ready.mockRejectedValue(new Error("Secret API error"));
+
+ vi.spyOn(console, "error").mockImplementation(() => {});
+
+ const { container } = render(
+
+
+ Control
+
+ ,
+ );
+
+ await waitFor(() => {
+ const alert = container.querySelector('[role="alert"]');
+ expect(alert).not.toBeNull();
+ expect(alert!.textContent).not.toContain("Secret API error");
+ });
+ });
+
+ it("Treatment should show error.message in development", async () => {
+ vi.stubEnv("NODE_ENV", "development");
+
+ mocks.context.isReady.mockReturnValue(false);
+ mocks.context.isFailed.mockReturnValue(true);
+ mocks.context.ready.mockRejectedValue(new Error("Debug error info"));
+
+ vi.spyOn(console, "error").mockImplementation(() => {});
+
+ const { container } = render(
+
+
+ Control
+
+ ,
+ );
+
+ await waitFor(() => {
+ const alert = container.querySelector('[role="alert"]');
+ expect(alert).not.toBeNull();
+ expect(alert!.textContent).toContain("Debug error info");
+ });
+ });
+
+ it("TreatmentFunction should not show error.message in production", async () => {
+ vi.stubEnv("NODE_ENV", "production");
+
+ mocks.context.isReady.mockReturnValue(false);
+ mocks.context.isFailed.mockReturnValue(true);
+ mocks.context.ready.mockRejectedValue(new Error("Secret error"));
+
+ vi.spyOn(console, "error").mockImplementation(() => {});
+
+ const { container } = render(
+
+ {({ variant }: TreatmentProps) => Variant {variant}
}
+ ,
+ );
+
+ await waitFor(() => {
+ const alert = container.querySelector('[role="alert"]');
+ expect(alert).not.toBeNull();
+ expect(alert!.textContent).not.toContain("Secret error");
+ });
+ });
+
+ it("ErrorBoundary should show generic message in production", () => {
+ vi.stubEnv("NODE_ENV", "production");
+
+ vi.spyOn(console, "error").mockImplementation(() => {});
+
+ const ThrowingComponent = () => {
+ throw new Error("Internal secret");
+ };
+
+ const { container } = render(
+
+
+ ,
+ );
+
+ expect(container.textContent).toContain("Something went wrong.");
+ expect(container.textContent).not.toContain("Internal secret");
+ });
+
+ it("ErrorBoundary should show error message in development", () => {
+ vi.stubEnv("NODE_ENV", "development");
+
+ vi.spyOn(console, "error").mockImplementation(() => {});
+
+ const ThrowingComponent = () => {
+ throw new Error("Debug details here");
+ };
+
+ const { container } = render(
+
+
+ ,
+ );
+
+ expect(container.textContent).toContain("Debug details here");
+ });
+});
+
+describe("Fix #8: Treatment accepts errorComponent prop", () => {
+ it("should render custom errorComponent when error occurs", async () => {
+ mocks.context.isReady.mockReturnValue(false);
+ mocks.context.isFailed.mockReturnValue(true);
+ mocks.context.ready.mockRejectedValue(new Error("Test error"));
+
+ vi.spyOn(console, "error").mockImplementation(() => {});
+
+ const { queryByTestId } = render(
+ Custom Error UI}
+ >
+
+ Control
+
+ ,
+ );
+
+ await waitFor(() => {
+ const customError = queryByTestId("custom-error");
+ expect(customError).not.toBeNull();
+ expect(customError!.textContent).toBe("Custom Error UI");
+ });
+ });
+});
+
+describe("Fix #10: childrenInfo memoized in Treatment", () => {
+ it("should render correct variant with memoized childrenInfo", async () => {
+ mocks.context.isReady.mockReturnValue(true);
+ mocks.context.treatment.mockReturnValue(2);
+ mocks.context.peek.mockReturnValue(2);
+
+ const { getByText } = render(
+
+
+ Control
+
+
+ Variant 1
+
+
+ Variant 2
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(getByText("Variant 2")).toBeTruthy();
+ });
+ });
+});
+
+describe("Fix #11: useContextReady uses refs for onReady and attributes", () => {
+ it("keeps SDK calls bounded across rerenders with inline attributes", async () => {
+ mocks.context.isReady.mockReturnValue(true);
+ mocks.context.treatment.mockReturnValue(0);
+ mocks.context.peek.mockReturnValue(0);
+
+ const TestComponent = () => (
+
+
+ Control
+
+
+ );
+
+ const { rerender } = render( );
+ await screen.findByText("Control");
+
+ for (let i = 0; i < 5; i++) {
+ rerender( );
+ }
+
+ expect(mocks.context.attributes).toHaveBeenCalledWith({ key: "value" });
+ expect(mocks.context.attributes).toHaveBeenCalledTimes(2);
+ expect(mocks.context.treatment).toHaveBeenCalledWith("test_exp");
+ expect(mocks.context.treatment).toHaveBeenCalledTimes(1);
+ });
+});
+
+describe("Treatment rerender while context is finalizing", () => {
+ it("does not evaluate a finalizing context when children change", async () => {
+ let finalizing = false;
+ const ctx = {
+ isReady: vi.fn().mockReturnValue(true),
+ isFailed: vi.fn().mockReturnValue(false),
+ isFinalizing: vi.fn(() => finalizing),
+ isFinalized: vi.fn().mockReturnValue(false),
+ ready: vi.fn().mockResolvedValue(undefined),
+ attributes: vi.fn(),
+ treatment: vi.fn().mockReturnValue(0),
+ peek: vi.fn(() => {
+ if (finalizing) throw new Error("ABsmartly Context is finalizing.");
+ return 0;
+ }),
+ } as unknown as Context;
+
+ vi.spyOn(console, "error").mockImplementation(() => {});
+
+ const renderTree = (label: string) => (
+ Boundary fallback
}>
+
+
+ {label}
+
+
+
+ );
+
+ const { rerender } = render(renderTree("Control A"));
+ await waitFor(() => expect(screen.getByText("Control A")).toBeTruthy());
+
+ finalizing = true;
+ rerender(renderTree("Control B"));
+
+ await waitFor(() => expect(screen.getByText("Control B")).toBeTruthy());
+ expect(screen.queryByText("Boundary fallback")).toBeNull();
+ });
+});
+
+describe("Declarative treatments during reset", () => {
+ const makeFinalizingContext = () => {
+ let finalizing = false;
+ const fail = () => {
+ if (finalizing) throw new Error("ABsmartly Context is finalizing.");
+ return 0;
+ };
+ const ctx = {
+ isReady: vi.fn().mockReturnValue(true),
+ isFailed: vi.fn().mockReturnValue(false),
+ isFinalizing: vi.fn(() => finalizing),
+ isFinalized: vi.fn().mockReturnValue(false),
+ ready: vi.fn().mockResolvedValue(undefined),
+ attributes: vi.fn(),
+ treatment: vi.fn(fail),
+ peek: vi.fn(fail),
+ variableKeys: vi.fn(() => {
+ fail();
+ return {};
+ }),
+ peekVariableValue: vi.fn(),
+ } as unknown as Context;
+ return { ctx, startFinalizing: () => (finalizing = true) };
+ };
+
+ it("Treatment name change while finalizing reports an error instead of throwing", async () => {
+ vi.spyOn(console, "error").mockImplementation(() => {});
+ const { ctx, startFinalizing } = makeFinalizingContext();
+ const tree = (name: string) => (
+ Boundary fallback}>
+
+
+ Control
+
+
+
+ );
+
+ const { rerender } = render(tree("exp_a"));
+ await waitFor(() => expect(screen.getByText("Control")).toBeTruthy());
+
+ startFinalizing();
+ rerender(tree("exp_b"));
+
+ await waitFor(() => expect(screen.getByRole("alert")).toBeTruthy());
+ expect(screen.queryByText("Boundary fallback")).toBeNull();
+ });
+
+ it("TreatmentFunction name change while finalizing reports an error instead of throwing", async () => {
+ vi.spyOn(console, "error").mockImplementation(() => {});
+ const { ctx, startFinalizing } = makeFinalizingContext();
+ const tree = (name: string) => (
+ Boundary fallback}>
+
+ {({ variant }: TreatmentProps) => Variant {variant}
}
+
+
+ );
+
+ const { rerender } = render(tree("exp_a"));
+ await waitFor(() => expect(screen.getByText("Variant 0")).toBeTruthy());
+
+ startFinalizing();
+ rerender(tree("exp_b"));
+
+ await waitFor(() => expect(screen.getByRole("alert")).toBeTruthy());
+ expect(screen.queryByText("Boundary fallback")).toBeNull();
+ });
+
+ it("Treatment mounted while finalizing reports an error instead of throwing", async () => {
+ vi.spyOn(console, "error").mockImplementation(() => {});
+ const { ctx, startFinalizing } = makeFinalizingContext();
+ startFinalizing();
+
+ render(
+ Boundary fallback}>
+
+
+ Control
+
+
+ ,
+ );
+
+ await waitFor(() => expect(screen.getByRole("alert")).toBeTruthy());
+ expect(screen.queryByText("Boundary fallback")).toBeNull();
+ });
+
+ it("TreatmentFunction mounted while finalizing reports an error instead of throwing", async () => {
+ vi.spyOn(console, "error").mockImplementation(() => {});
+ const { ctx, startFinalizing } = makeFinalizingContext();
+ startFinalizing();
+
+ render(
+ Boundary fallback}>
+
+ {({ variant }: TreatmentProps) => Variant {variant}
}
+
+ ,
+ );
+
+ await waitFor(() => expect(screen.getByRole("alert")).toBeTruthy());
+ expect(screen.queryByText("Boundary fallback")).toBeNull();
+ });
+});
diff --git a/tests/integration.test.tsx b/tests/integration.test.tsx
new file mode 100644
index 0000000..167dbf8
--- /dev/null
+++ b/tests/integration.test.tsx
@@ -0,0 +1,296 @@
+import { cleanup, render, screen, waitFor } from "@testing-library/react";
+import React, { Suspense, Component, ReactNode } from "react";
+import { afterEach, describe, expect, it, vi } from "vitest";
+
+import { Context } from "@absmartly/javascript-sdk";
+
+import {
+ Treatment,
+ TreatmentVariant,
+ TreatmentFunction,
+ TreatmentProps,
+} from "../src";
+
+vi.mock("@absmartly/javascript-sdk");
+
+afterEach(() => {
+ cleanup();
+ vi.clearAllMocks();
+});
+
+const mockContextData = {
+ experiments: [],
+};
+
+const createMockContext = (treatment: number, isReady = true) => ({
+ data: vi.fn().mockReturnValue(mockContextData),
+ isReady: vi.fn().mockReturnValue(isReady),
+ isFailed: vi.fn().mockReturnValue(false),
+ treatment: vi.fn().mockReturnValue(treatment),
+ peek: vi.fn().mockReturnValue(treatment),
+ ready: vi.fn().mockResolvedValue(undefined),
+ attributes: vi.fn(),
+ variableKeys: vi.fn().mockReturnValue({}),
+ peekVariableValue: vi.fn(),
+});
+
+describe("Integration Tests", () => {
+ describe("Multiple Treatments in Tree", () => {
+ it("should render multiple treatments correctly in a component tree", async () => {
+ const context1 = createMockContext(1);
+ const context2 = createMockContext(2);
+ const context3 = createMockContext(0);
+
+ render(
+
+
+
+ Header Control
+
+
+ Header Variant
+
+
+
+
+
+ Buy Now
+
+
+ Add to Cart
+
+
+ Get Started
+
+
+
+
+
+
+
+
+
+
+
+
,
+ );
+
+ await waitFor(() => {
+ expect(screen.getByTestId("header-variant")).toBeInTheDocument();
+ expect(screen.getByTestId("button-variant2")).toBeInTheDocument();
+ expect(screen.getByTestId("footer-control")).toBeInTheDocument();
+ });
+
+ expect(screen.queryByTestId("header-control")).not.toBeInTheDocument();
+ expect(screen.queryByTestId("button-control")).not.toBeInTheDocument();
+ expect(screen.queryByTestId("footer-variant")).not.toBeInTheDocument();
+ });
+
+ it("should handle nested treatments correctly", async () => {
+ const outerContext = createMockContext(1);
+ const innerContext = createMockContext(0);
+
+ render(
+
+
+ Outer Control
+
+
+
+ Outer Variant
+
+
+ Inner Control
+
+
+ Inner Variant
+
+
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(screen.getByTestId("outer-variant")).toBeInTheDocument();
+ expect(screen.getByTestId("inner-control")).toBeInTheDocument();
+ });
+
+ expect(screen.queryByTestId("outer-control")).not.toBeInTheDocument();
+ expect(screen.queryByTestId("inner-variant")).not.toBeInTheDocument();
+ });
+ });
+
+ describe("Treatment with Suspense", () => {
+ it("should work correctly with React Suspense boundaries", async () => {
+ const context = createMockContext(1);
+
+ render(
+ Loading...}
+ >
+
+
+ Control Content
+
+
+ Variant Content
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(screen.getByTestId("variant")).toBeInTheDocument();
+ });
+ });
+ });
+
+ describe("Treatment with Error Boundary", () => {
+ class ErrorBoundary extends Component<
+ { children: ReactNode; fallback: ReactNode },
+ { hasError: boolean }
+ > {
+ constructor(props: { children: ReactNode; fallback: ReactNode }) {
+ super(props);
+ this.state = { hasError: false };
+ }
+
+ static getDerivedStateFromError() {
+ return { hasError: true };
+ }
+
+ render() {
+ if (this.state.hasError) {
+ return this.props.fallback;
+ }
+ return this.props.children;
+ }
+ }
+
+ it("should work correctly inside an error boundary", async () => {
+ const context = createMockContext(1);
+
+ render(
+ Error occurred}
+ >
+
+
+ Control
+
+
+ Variant
+
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(screen.getByTestId("variant")).toBeInTheDocument();
+ });
+
+ expect(screen.queryByTestId("error-fallback")).not.toBeInTheDocument();
+ });
+ });
+
+ describe("TreatmentFunction integration", () => {
+ it("should render correctly with function children pattern", async () => {
+ const context = createMockContext(2);
+
+ render(
+
+ {({ variant }: TreatmentProps) => (
+
+ {variant === 0 && Basic: $9.99 }
+ {variant === 1 && Pro: $19.99 }
+ {variant === 2 && Enterprise: $49.99 }
+
+ )}
+ ,
+ );
+
+ await waitFor(() => {
+ expect(screen.getByTestId("pricing")).toHaveTextContent(
+ "Enterprise: $49.99",
+ );
+ });
+ });
+
+ it("should pass variant and variables to render function", async () => {
+ const context = createMockContext(1);
+
+ render(
+
+ {({ variant, variables }: TreatmentProps) => (
+
+ {variant}
+ {typeof variables}
+
+ )}
+ ,
+ );
+
+ await waitFor(() => {
+ expect(screen.getByTestId("variant-value")).toHaveTextContent("1");
+ expect(screen.getByTestId("variables-type")).toHaveTextContent(
+ "object",
+ );
+ });
+ });
+ });
+
+ describe("Treatment with attributes", () => {
+ it("should pass attributes to context correctly", async () => {
+ const context = createMockContext(1);
+ const attributes = { plan: "premium", country: "US" };
+
+ render(
+
+
+ Control
+
+
+ Personalized Content
+
+ ,
+ );
+
+ await waitFor(() => {
+ expect(context.attributes).toHaveBeenCalledWith(attributes);
+ expect(screen.getByTestId("personalized")).toBeInTheDocument();
+ });
+ });
+ });
+});
diff --git a/tests/mocks.ts b/tests/mocks.ts
index 996e2ae..3a5279b 100644
--- a/tests/mocks.ts
+++ b/tests/mocks.ts
@@ -1,10 +1,11 @@
import { Context } from "@absmartly/javascript-sdk";
import { Mocked, MockedFunction, vi } from "vitest";
-import { useABSmartly } from "../src/hooks/useABSmartly";
+import { useABSmartly, useOptionalABSmartly } from "../src/hooks/useABSmartly";
export const mocks = {
context: {
treatment: vi.fn(),
+ peek: vi.fn(),
experimentConfig: vi.fn(),
attributes: vi.fn(),
ready: vi.fn(),
@@ -18,3 +19,6 @@ export const mocks = {
export const mockedUseABSmartly = useABSmartly as MockedFunction<
typeof useABSmartly
>;
+
+export const mockedUseOptionalABSmartly =
+ useOptionalABSmartly as MockedFunction;
diff --git a/tests/ssr.test.tsx b/tests/ssr.test.tsx
new file mode 100644
index 0000000..727f526
--- /dev/null
+++ b/tests/ssr.test.tsx
@@ -0,0 +1,191 @@
+import { cleanup, renderHook } from "@testing-library/react";
+import React from "react";
+import {
+ afterEach,
+ beforeEach,
+ describe,
+ expect,
+ it,
+ vi,
+ MockedFunction,
+} from "vitest";
+import { renderToString } from "react-dom/server";
+
+import { Context, SDK } from "@absmartly/javascript-sdk";
+import {
+ useABSmartly,
+ useTreatment,
+ Treatment,
+ TreatmentVariant,
+} from "../src";
+
+vi.mock("../src/hooks/useABSmartly");
+
+const mockedUseABSmartly = useABSmartly as MockedFunction;
+
+const createMockContext = (isReady = true) => ({
+ ready: vi.fn().mockResolvedValue(undefined),
+ peek: vi.fn().mockReturnValue(1),
+ treatment: vi.fn().mockReturnValue(1),
+ isReady: vi.fn().mockReturnValue(isReady),
+ isFailed: vi.fn().mockReturnValue(false),
+ attributes: vi.fn(),
+});
+
+afterEach(() => {
+ cleanup();
+ vi.clearAllMocks();
+});
+
+describe("SSR Support", () => {
+ describe("useTreatment SSR behavior", () => {
+ it("should return variant immediately when context is pre-ready (SSR scenario)", () => {
+ const mockContext = createMockContext(true);
+ mockContext.peek.mockReturnValue(2);
+ mockContext.treatment.mockReturnValue(2);
+
+ mockedUseABSmartly.mockReturnValue({
+ context: mockContext as unknown as Context,
+ sdk: null as unknown as SDK,
+ resetContext: vi.fn().mockResolvedValue(undefined),
+ });
+
+ const TestComponent = () => {
+ const { variant, loading, error } = useTreatment("experiment-name");
+ return (
+
+ {loading ? "Loading" : `Variant: ${variant}`}
+ {error ? " error" : ""}
+
+ );
+ };
+
+ const html = renderToString( );
+
+ expect(html).toContain("Variant: 2");
+ expect(html).not.toContain("Loading");
+ expect(html).not.toContain("error");
+ expect(mockContext.ready).not.toHaveBeenCalled();
+ });
+
+ it("should support static rendering without async operations when context is ready", () => {
+ const mockContext = createMockContext(true);
+ mockContext.peek.mockReturnValue(1);
+ mockContext.treatment.mockReturnValue(1);
+
+ mockedUseABSmartly.mockReturnValue({
+ context: mockContext as unknown as Context,
+ sdk: null as unknown as SDK,
+ resetContext: vi.fn().mockResolvedValue(undefined),
+ });
+
+ const TestComponent = () => {
+ const { variant, loading } = useTreatment("test-experiment");
+ return {loading ? "Loading..." : `Variant: ${variant}`}
;
+ };
+
+ const html = renderToString( );
+
+ expect(html).toContain("Variant: 1");
+ expect(html).not.toContain("Loading...");
+ });
+ });
+
+ describe("Treatment component SSR behavior", () => {
+ it("should render control variant during SSR when context is not ready", () => {
+ const mockContext = createMockContext(false);
+
+ mockedUseABSmartly.mockReturnValue({
+ context: mockContext as unknown as Context,
+ sdk: null as unknown as SDK,
+ resetContext: vi.fn().mockResolvedValue(undefined),
+ });
+
+ const html = renderToString(
+
+
+ Control
+
+
+ Variant 1
+
+ ,
+ );
+
+ expect(html).toContain("Control");
+ expect(html).not.toContain("Variant 1");
+ });
+
+ it("should render correct variant during SSR when context is ready", () => {
+ const mockContext = createMockContext(true);
+ mockContext.treatment.mockReturnValue(1);
+
+ mockedUseABSmartly.mockReturnValue({
+ context: mockContext as unknown as Context,
+ sdk: null as unknown as SDK,
+ resetContext: vi.fn().mockResolvedValue(undefined),
+ });
+
+ const html = renderToString(
+
+
+ Control
+
+
+ Variant 1
+
+ ,
+ );
+
+ expect(html).toContain("Variant 1");
+ expect(html).not.toContain("Control");
+ });
+
+ it("should render loading component during SSR when provided and context not ready", () => {
+ const mockContext = createMockContext(false);
+
+ mockedUseABSmartly.mockReturnValue({
+ context: mockContext as unknown as Context,
+ sdk: null as unknown as SDK,
+ resetContext: vi.fn().mockResolvedValue(undefined),
+ });
+
+ const html = renderToString(
+ Loading...}
+ >
+
+ Control
+
+
+ Variant 1
+
+ ,
+ );
+
+ expect(html).toContain("Loading...");
+ expect(html).not.toContain("Control");
+ expect(html).not.toContain("Variant 1");
+ });
+ });
+
+ describe("Context serialization for SSR", () => {
+ it("should allow context data to be accessed synchronously", () => {
+ const mockContext = createMockContext(true);
+ mockContext.treatment.mockReturnValue(0);
+
+ mockedUseABSmartly.mockReturnValue({
+ context: mockContext as unknown as Context,
+ sdk: null as unknown as SDK,
+ resetContext: vi.fn().mockResolvedValue(undefined),
+ });
+
+ const { result } = renderHook(() => useTreatment("experiment"));
+
+ expect(result.current.context).toBeDefined();
+ expect(mockContext.treatment).toHaveBeenCalledWith("experiment");
+ });
+ });
+});
diff --git a/tests/useTreatment.test.ts b/tests/useTreatment.test.ts
index 16f29da..91e76af 100644
--- a/tests/useTreatment.test.ts
+++ b/tests/useTreatment.test.ts
@@ -16,17 +16,21 @@ vi.mock("../src/hooks/useABSmartly");
const mockedUseABSmartly = useABSmartly as MockedFunction;
-const mockContext = {
+const createMockContext = () => ({
ready: vi.fn(),
peek: vi.fn(),
treatment: vi.fn(),
-};
+ isReady: vi.fn().mockReturnValue(false),
+});
+
+let mockContext = createMockContext();
beforeEach(() => {
+ mockContext = createMockContext();
mockedUseABSmartly.mockReturnValue({
context: mockContext as unknown as Context,
sdk: null as unknown as SDK,
- resetContext: () => {},
+ resetContext: vi.fn().mockResolvedValue(undefined),
});
});
@@ -53,6 +57,25 @@ describe("useTreatment", () => {
});
});
+ it("evaluates once after asynchronous readiness", async () => {
+ let resolveReady!: () => void;
+ mockContext.ready.mockReturnValueOnce(
+ new Promise((resolve) => {
+ resolveReady = () => {
+ mockContext.isReady.mockReturnValue(true);
+ resolve();
+ };
+ }),
+ );
+ mockContext.treatment.mockReturnValue(1);
+
+ const { result } = renderHook(() => useTreatment("experiment-name"));
+ resolveReady();
+
+ await waitFor(() => expect(result.current.variant).toBe(1));
+ expect(mockContext.treatment).toHaveBeenCalledTimes(1);
+ });
+
it("should handle errors correctly", async () => {
const error = new Error("Test error");
mockContext.ready.mockRejectedValueOnce(error);
@@ -90,4 +113,155 @@ describe("useTreatment", () => {
expect(result.current.error?.message).toBe("Test error");
});
});
+
+ it("should return context object for direct access", async () => {
+ mockContext.ready.mockResolvedValueOnce(undefined);
+ mockContext.treatment.mockReturnValueOnce(1);
+
+ const { result } = renderHook(() => useTreatment("experiment-name"));
+
+ await waitFor(() => {
+ expect(result.current.context).toBeDefined();
+ expect(result.current.context).toBe(mockContext);
+ });
+ });
+
+ it("should return variant immediately when context is already ready", () => {
+ mockContext.isReady.mockReturnValue(true);
+ mockContext.treatment.mockReturnValue(2);
+
+ const { result } = renderHook(() => useTreatment("experiment-name"));
+
+ expect(result.current.loading).toBe(false);
+ expect(result.current.variant).toBe(2);
+ expect(result.current.error).toBe(null);
+ expect(mockContext.ready).not.toHaveBeenCalled();
+ });
+
+ it("should use peek immediately when context is already ready and peek is true", () => {
+ mockContext.isReady.mockReturnValue(true);
+ mockContext.peek.mockReturnValue(3);
+
+ const { result } = renderHook(() => useTreatment("experiment-name", true));
+
+ expect(result.current.loading).toBe(false);
+ expect(result.current.variant).toBe(3);
+ expect(mockContext.peek).toHaveBeenCalledWith("experiment-name");
+ expect(mockContext.treatment).not.toHaveBeenCalled();
+ });
+
+ it("should update variant when experiment name changes", async () => {
+ mockContext.ready.mockResolvedValue(undefined);
+ mockContext.treatment.mockReturnValueOnce(1).mockReturnValueOnce(2);
+
+ const { result, rerender } = renderHook(({ name }) => useTreatment(name), {
+ initialProps: { name: "experiment-1" },
+ });
+
+ await waitFor(() => {
+ expect(result.current.variant).toBe(1);
+ });
+
+ rerender({ name: "experiment-2" });
+
+ await waitFor(() => {
+ expect(result.current.variant).toBe(2);
+ });
+ });
+
+ it("should handle variant 0 correctly (falsy but valid)", async () => {
+ mockContext.ready.mockResolvedValueOnce(undefined);
+ mockContext.treatment.mockReturnValueOnce(0);
+
+ const { result } = renderHook(() => useTreatment("experiment-name"));
+
+ await waitFor(() => {
+ expect(result.current.loading).toBe(false);
+ expect(result.current.variant).toBe(0);
+ expect(result.current.error).toBe(null);
+ });
+ });
+
+ it("should not skip effect when context changes but isReady is still false", async () => {
+ const firstContext = createMockContext();
+ const secondContext = createMockContext();
+
+ firstContext.ready.mockResolvedValue(undefined);
+ firstContext.treatment.mockReturnValue(1);
+ secondContext.ready.mockResolvedValue(undefined);
+ secondContext.treatment.mockReturnValue(2);
+
+ mockedUseABSmartly.mockReturnValue({
+ context: firstContext as unknown as Context,
+ sdk: null as unknown as SDK,
+ resetContext: vi.fn().mockResolvedValue(undefined),
+ });
+
+ const { result, rerender } = renderHook(() =>
+ useTreatment("experiment-name"),
+ );
+
+ await waitFor(() => {
+ expect(result.current.variant).toBe(1);
+ });
+
+ mockedUseABSmartly.mockReturnValue({
+ context: secondContext as unknown as Context,
+ sdk: null as unknown as SDK,
+ resetContext: vi.fn().mockResolvedValue(undefined),
+ });
+
+ rerender();
+
+ await waitFor(() => {
+ expect(result.current.variant).toBe(2);
+ });
+ });
+});
+
+describe("useTreatment input change while context is finalizing", () => {
+ it("returns the evaluation error instead of throwing", async () => {
+ vi.spyOn(console, "error").mockImplementation(() => {});
+ mockContext.isReady.mockReturnValue(true);
+ mockContext.peek.mockReturnValue(0);
+ mockContext.treatment.mockReturnValue(0);
+
+ const { result, rerender } = renderHook(({ name }) => useTreatment(name), {
+ initialProps: { name: "exp_a" },
+ });
+ expect(result.current.variant).toBe(0);
+
+ mockContext.treatment.mockImplementation(() => {
+ throw new Error("ABsmartly Context is finalizing.");
+ });
+
+ expect(() => rerender({ name: "exp_b" })).not.toThrow();
+ await waitFor(() =>
+ expect(result.current.error?.message).toBe(
+ "ABsmartly Context is finalizing.",
+ ),
+ );
+ expect(result.current.loading).toBe(false);
+ });
+});
+
+describe("useTreatment mounted while context is finalizing", () => {
+ it("returns the evaluation error instead of throwing during render", async () => {
+ vi.spyOn(console, "error").mockImplementation(() => {});
+ mockContext.isReady.mockReturnValue(true);
+ const finalizing = () => {
+ throw new Error("ABsmartly Context is finalizing.");
+ };
+ mockContext.peek.mockImplementation(finalizing);
+ mockContext.treatment.mockImplementation(finalizing);
+
+ const { result } = renderHook(() => useTreatment("exp_a"));
+
+ await waitFor(() =>
+ expect(result.current.error?.message).toBe(
+ "ABsmartly Context is finalizing.",
+ ),
+ );
+ expect(result.current.loading).toBe(false);
+ });
});
diff --git a/tests/utils.test.ts b/tests/utils.test.ts
new file mode 100644
index 0000000..25687d5
--- /dev/null
+++ b/tests/utils.test.ts
@@ -0,0 +1,86 @@
+import { describe, expect, it, vi } from "vitest";
+import { convertLetterToNumber } from "../src/utils/convertLetterToNumber";
+
+describe("convertLetterToNumber", () => {
+ describe("number passthrough", () => {
+ it("should return number as-is when input is a number", () => {
+ expect(convertLetterToNumber(0)).toBe(0);
+ expect(convertLetterToNumber(1)).toBe(1);
+ expect(convertLetterToNumber(5)).toBe(5);
+ expect(convertLetterToNumber(99)).toBe(99);
+ });
+ });
+
+ describe("numeric string conversion", () => {
+ it("should convert numeric strings to numbers", () => {
+ expect(convertLetterToNumber("0")).toBe(0);
+ expect(convertLetterToNumber("1")).toBe(1);
+ expect(convertLetterToNumber("5")).toBe(5);
+ expect(convertLetterToNumber("9")).toBe(9);
+ });
+ });
+
+ describe("lowercase letter conversion", () => {
+ it("should convert lowercase letters to variant numbers (a=0, b=1, etc.)", () => {
+ expect(convertLetterToNumber("a")).toBe(0);
+ expect(convertLetterToNumber("b")).toBe(1);
+ expect(convertLetterToNumber("c")).toBe(2);
+ expect(convertLetterToNumber("d")).toBe(3);
+ expect(convertLetterToNumber("e")).toBe(4);
+ });
+
+ it("should handle all lowercase letters correctly", () => {
+ const alphabet = "abcdefghijklmnopqrstuvwxyz";
+ for (let i = 0; i < alphabet.length; i++) {
+ expect(convertLetterToNumber(alphabet[i] as any)).toBe(i);
+ }
+ });
+ });
+
+ describe("uppercase letter conversion", () => {
+ it("should convert uppercase letters to variant numbers (A=0, B=1, etc.)", () => {
+ expect(convertLetterToNumber("A")).toBe(0);
+ expect(convertLetterToNumber("B")).toBe(1);
+ expect(convertLetterToNumber("C")).toBe(2);
+ expect(convertLetterToNumber("D")).toBe(3);
+ expect(convertLetterToNumber("E")).toBe(4);
+ });
+
+ it("should handle all uppercase letters correctly", () => {
+ const alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+ for (let i = 0; i < alphabet.length; i++) {
+ expect(convertLetterToNumber(alphabet[i] as any)).toBe(i);
+ }
+ });
+ });
+
+ describe("edge cases", () => {
+ it("should handle last letters of alphabet", () => {
+ expect(convertLetterToNumber("z")).toBe(25);
+ expect(convertLetterToNumber("Z")).toBe(25);
+ });
+
+ it("should handle treatment variant typical values", () => {
+ expect(convertLetterToNumber("A")).toBe(0);
+ expect(convertLetterToNumber("B")).toBe(1);
+ expect(convertLetterToNumber(0)).toBe(0);
+ expect(convertLetterToNumber(1)).toBe(1);
+ expect(convertLetterToNumber("0")).toBe(0);
+ expect(convertLetterToNumber("1")).toBe(1);
+ });
+ });
+
+ describe("invalid input handling", () => {
+ it.each(["1junk", "ab", "!", "@", ""])(
+ "returns 0 and warns for %j",
+ (input) => {
+ const warnSpy = vi.spyOn(console, "warn").mockImplementation(() => {});
+ expect(convertLetterToNumber(input)).toBe(0);
+ expect(warnSpy).toHaveBeenCalledWith(
+ `convertLetterToNumber: Invalid input "${input}". Returning 0.`,
+ );
+ warnSpy.mockRestore();
+ },
+ );
+ });
+});
diff --git a/tests/withABSmartly.test.tsx b/tests/withABSmartly.test.tsx
new file mode 100644
index 0000000..002fb65
--- /dev/null
+++ b/tests/withABSmartly.test.tsx
@@ -0,0 +1,227 @@
+import { cleanup, render, screen } from "@testing-library/react";
+import React, { ComponentType } from "react";
+import { afterEach, describe, expect, it, vi, MockedClass } from "vitest";
+
+import { SDK } from "@absmartly/javascript-sdk";
+import { SDKProvider } from "../src/components/SDKProvider";
+import { withABSmartly } from "../src/hooks/HOCs/withABSmartly";
+import { ABSmartly } from "../src/types";
+
+vi.mock("@absmartly/javascript-sdk");
+
+afterEach(() => {
+ cleanup();
+ vi.clearAllMocks();
+});
+
+const mockContextData = {
+ experiments: [],
+};
+
+const mockCreateContext = vi.fn().mockImplementation(function () {
+ return {
+ data: vi.fn().mockReturnValue(mockContextData),
+ isReady: vi.fn().mockReturnValue(true),
+ isFailed: vi.fn().mockReturnValue(false),
+ treatment: vi.fn().mockReturnValue(1),
+ ready: vi.fn().mockResolvedValue(undefined),
+ attributes: vi.fn(),
+ variableKeys: vi.fn().mockReturnValue({}),
+ peekVariableValue: vi.fn(),
+ finalize: vi.fn().mockResolvedValue(undefined),
+ };
+});
+
+(SDK as MockedClass).mockImplementation(function () {
+ return {
+ createContext: mockCreateContext,
+ createContextWith: vi.fn(),
+ } as unknown as SDK;
+});
+
+const sdkOptions = {
+ endpoint: "https://sandbox.absmartly.io/v1",
+ apiKey: "test-api-key",
+ application: "www",
+ environment: "test",
+};
+
+const contextOptions = {
+ units: {
+ user_id: "test-user-id",
+ },
+};
+
+describe("withABSmartly HOC", () => {
+ it("should properly wrap a component and pass absmartly prop", () => {
+ interface TestComponentProps {
+ absmartly: ABSmartly;
+ testProp?: string;
+ }
+
+ const TestComponent = ({ absmartly, testProp }: TestComponentProps) => {
+ return (
+
+ {absmartly.sdk ? "yes" : "no"}
+
+ {absmartly.context ? "yes" : "no"}
+
+ {testProp || "none"}
+
+ );
+ };
+
+ const WrappedComponent = withABSmartly(TestComponent);
+
+ render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId("test-component")).toBeInTheDocument();
+ expect(screen.getByTestId("has-sdk")).toHaveTextContent("yes");
+ expect(screen.getByTestId("has-context")).toHaveTextContent("yes");
+ });
+
+ it("should pass through additional props correctly", () => {
+ interface TestComponentProps {
+ absmartly: ABSmartly;
+ message: string;
+ count: number;
+ items: string[];
+ }
+
+ const TestComponent = ({ message, count, items }: TestComponentProps) => {
+ return (
+
+ {message}
+ {count}
+ {items.join(",")}
+
+ );
+ };
+
+ const WrappedComponent = withABSmartly(TestComponent);
+
+ render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId("message")).toHaveTextContent("test message");
+ expect(screen.getByTestId("count")).toHaveTextContent("42");
+ expect(screen.getByTestId("items")).toHaveTextContent("a,b,c");
+ });
+
+ it("should provide access to context methods via absmartly prop", () => {
+ interface TestComponentProps {
+ absmartly: ABSmartly;
+ }
+
+ const TestComponent = ({ absmartly }: TestComponentProps) => {
+ const treatment = absmartly.context.treatment("test_exp");
+ return (
+
+ {treatment}
+
+ {typeof absmartly.resetContext === "function" ? "yes" : "no"}
+
+
+ );
+ };
+
+ const WrappedComponent = withABSmartly(TestComponent);
+
+ render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId("treatment")).toHaveTextContent("1");
+ expect(screen.getByTestId("has-reset")).toHaveTextContent("yes");
+ });
+
+ it("should set correct displayName for wrapped component", () => {
+ interface TestComponentProps {
+ absmartly: ABSmartly;
+ }
+
+ const NamedComponent = ({ absmartly }: TestComponentProps) => {
+ return {absmartly ? "wrapped" : "not wrapped"}
;
+ };
+
+ const WrappedComponent = withABSmartly(NamedComponent);
+
+ expect(WrappedComponent.displayName).toBe("withABSmartly(NamedComponent)");
+ });
+
+ it("should use Component fallback for displayName when component has no name", () => {
+ interface TestComponentProps {
+ absmartly: ABSmartly;
+ }
+
+ const WrappedComponent = withABSmartly((({
+ absmartly,
+ }: TestComponentProps) => (
+ {absmartly ? "wrapped" : "not wrapped"}
+ )) as ComponentType);
+
+ expect(WrappedComponent.displayName).toBe("withABSmartly(Component)");
+ });
+
+ it("should work with components that have displayName property", () => {
+ interface TestComponentProps {
+ absmartly: ABSmartly;
+ }
+
+ const TestComponent = ({ absmartly }: TestComponentProps) => {
+ return {absmartly ? "wrapped" : "not wrapped"}
;
+ };
+ TestComponent.displayName = "CustomDisplayName";
+
+ const WrappedComponent = withABSmartly(TestComponent);
+
+ expect(WrappedComponent.displayName).toBe(
+ "withABSmartly(CustomDisplayName)",
+ );
+ });
+
+ it("should work with class components", () => {
+ interface TestComponentProps {
+ absmartly: ABSmartly;
+ title: string;
+ }
+
+ class ClassComponent extends React.Component {
+ render() {
+ const { absmartly, title } = this.props;
+ return (
+
+ {title}
+
+ {absmartly.context ? "yes" : "no"}
+
+
+ );
+ }
+ }
+
+ const WrappedComponent = withABSmartly(ClassComponent);
+
+ render(
+
+
+ ,
+ );
+
+ expect(screen.getByTestId("title")).toHaveTextContent("Test Title");
+ expect(screen.getByTestId("has-context")).toHaveTextContent("yes");
+ });
+});
diff --git a/tsconfig.json b/tsconfig.json
index d60a4c3..b506991 100644
--- a/tsconfig.json
+++ b/tsconfig.json
@@ -1,10 +1,12 @@
{
"compilerOptions": {
+ "strict": true,
+ "skipLibCheck": true,
"outDir": "lib/esm",
"allowJs": true,
"module": "esnext",
"target": "es5",
- "lib": ["es6", "dom", "es2016", "es2017"],
+ "lib": ["es6", "dom", "es2016", "es2017", "es2019"],
"jsx": "react",
"declaration": true,
"moduleResolution": "node",
@@ -12,9 +14,6 @@
"noUnusedParameters": true,
"esModuleInterop": true,
"noImplicitReturns": true,
- "noImplicitThis": true,
- "noImplicitAny": true,
- "strictNullChecks": true,
"suppressImplicitAnyIndexErrors": true,
"allowSyntheticDefaultImports": true
},
diff --git a/yarn.lock b/yarn.lock
index 2fbee69..0f3eb5f 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -16,14 +16,6 @@
resolved "https://registry.yarnpkg.com/@adobe/css-tools/-/css-tools-4.3.3.tgz#90749bde8b89cd41764224f5aac29cd4138f75ff"
integrity sha512-rE0Pygv0sEZ4vBWHlAgJLGDU7Pm8xoO6p3wsEceb7GYAjScrOHpEo8KK/eVkAcnSM+slAEtXjA2JpdjLp4fJQQ==
-"@ampproject/remapping@^2.2.1":
- version "2.3.0"
- resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4"
- integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==
- dependencies:
- "@jridgewell/gen-mapping" "^0.3.5"
- "@jridgewell/trace-mapping" "^0.3.24"
-
"@babel/code-frame@^7.10.4":
version "7.24.6"
resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.24.6.tgz#ab88da19344445c3d8889af2216606d3329f3ef2"
@@ -32,16 +24,21 @@
"@babel/highlight" "^7.24.6"
picocolors "^1.0.0"
-"@babel/helper-string-parser@^7.24.6":
- version "7.24.6"
- resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.24.6.tgz#28583c28b15f2a3339cfafafeaad42f9a0e828df"
- integrity sha512-WdJjwMEkmBicq5T9fm/cHND3+UlFa2Yj8ALLgmoSQAJZysYbBjw+azChSGPN4DSPLXOcooGRvDwZWMcF/mLO2Q==
+"@babel/helper-string-parser@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.29.7.tgz#7f0871d99824d23137d60f86fcf6130fd5a1b51f"
+ integrity sha512-Pb5ijPrZ89GDH8223L4UP8i6QApWxs04RbPQJTeWDV0/keR2E36MeKnyr6LYmUUvqRRI+Iv87SuF1W6ErINzYw==
"@babel/helper-validator-identifier@^7.24.6":
version "7.24.6"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.6.tgz#08bb6612b11bdec78f3feed3db196da682454a5e"
integrity sha512-4yA7s865JHaqUdRbnaxarZREuPTHrjpDT+pXoAZ1yhyo6uFnIEpS8VMu16siFOHDpZNKYv5BObhsB//ycbICyw==
+"@babel/helper-validator-identifier@^7.29.7":
+ version "7.29.7"
+ resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.29.7.tgz#bd87084ced0c796ec46bda492de6e83d29e89fc2"
+ integrity sha512-qehxGkRj55h/ff8EMaJ+cYhyaKlHIxqYDn682wQD7RNp9UujOQsHog2uS0r2vzr4pW+sXf90NeeayjcNaX3fFg==
+
"@babel/highlight@^7.24.6":
version "7.24.6"
resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.24.6.tgz#6d610c1ebd2c6e061cade0153bf69b0590b7b3df"
@@ -52,10 +49,12 @@
js-tokens "^4.0.0"
picocolors "^1.0.0"
-"@babel/parser@^7.24.4":
- version "7.24.6"
- resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.24.6.tgz#5e030f440c3c6c78d195528c3b688b101a365328"
- integrity sha512-eNZXdfU35nJC2h24RznROuOpO94h6x8sg9ju0tT9biNtLZ2vuP8SduLqqV+/8+cebSLV9SJEAN5Z3zQbJG/M+Q==
+"@babel/parser@^7.29.7":
+ version "7.29.9"
+ resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.29.9.tgz#e7ee0a24f752c5296c6455855ccb72662e67ea96"
+ integrity sha512-CjXrNHTnvqBVqHgdBysY3vk2T8tpJHb5/RMeHJBTyVa9xgugCB0CJTx/3oO8RV2QRQP391RWpB7D6hLjm8V9uA==
+ dependencies:
+ "@babel/types" "^7.29.8"
"@babel/runtime@^7.12.5", "@babel/runtime@^7.9.2":
version "7.24.6"
@@ -64,19 +63,18 @@
dependencies:
regenerator-runtime "^0.14.0"
-"@babel/types@^7.24.0":
- version "7.24.6"
- resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.24.6.tgz#ba4e1f59870c10dc2fa95a274ac4feec23b21912"
- integrity sha512-WaMsgi6Q8zMgMth93GvWPXkhAIEobfsIkLTacoVZoK1J0CevIPGYY2Vo5YvJGqyHqXM6P4ppOYGsIRU8MM9pFQ==
+"@babel/types@^7.29.7", "@babel/types@^7.29.8":
+ version "7.29.8"
+ resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.29.8.tgz#1229eef31d85156d70fa3f4cd859376d0eaf6863"
+ integrity sha512-Vj1jF3cPfxg7OAfoI7QnVKLoILlm2JF9pnVHrX8qx7AHMiYWT+NDAA7jChlNgRS4WTLc/fD1lXLmPixluj+3Gg==
dependencies:
- "@babel/helper-string-parser" "^7.24.6"
- "@babel/helper-validator-identifier" "^7.24.6"
- to-fast-properties "^2.0.0"
+ "@babel/helper-string-parser" "^7.29.7"
+ "@babel/helper-validator-identifier" "^7.29.7"
-"@bcoe/v8-coverage@^0.2.3":
- version "0.2.3"
- resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
- integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+"@bcoe/v8-coverage@^1.0.2":
+ version "1.0.2"
+ resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-1.0.2.tgz#bbe12dca5b4ef983a0d0af4b07b9bc90ea0ababa"
+ integrity sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==
"@cspotcode/source-map-support@^0.8.0":
version "0.8.1"
@@ -85,157 +83,21 @@
dependencies:
"@jridgewell/trace-mapping" "0.3.9"
-"@esbuild/aix-ppc64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz#a70f4ac11c6a1dfc18b8bbb13284155d933b9537"
- integrity sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==
-
-"@esbuild/android-arm64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz#db1c9202a5bc92ea04c7b6840f1bbe09ebf9e6b9"
- integrity sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==
-
-"@esbuild/android-arm@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.20.2.tgz#3b488c49aee9d491c2c8f98a909b785870d6e995"
- integrity sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==
-
-"@esbuild/android-x64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.20.2.tgz#3b1628029e5576249d2b2d766696e50768449f98"
- integrity sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==
-
-"@esbuild/darwin-arm64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz#6e8517a045ddd86ae30c6608c8475ebc0c4000bb"
- integrity sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==
-
-"@esbuild/darwin-x64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz#90ed098e1f9dd8a9381695b207e1cff45540a0d0"
- integrity sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==
-
-"@esbuild/freebsd-arm64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz#d71502d1ee89a1130327e890364666c760a2a911"
- integrity sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==
-
-"@esbuild/freebsd-x64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz#aa5ea58d9c1dd9af688b8b6f63ef0d3d60cea53c"
- integrity sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==
-
-"@esbuild/linux-arm64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz#055b63725df678379b0f6db9d0fa85463755b2e5"
- integrity sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==
-
-"@esbuild/linux-arm@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz#76b3b98cb1f87936fbc37f073efabad49dcd889c"
- integrity sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==
-
-"@esbuild/linux-ia32@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz#c0e5e787c285264e5dfc7a79f04b8b4eefdad7fa"
- integrity sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==
-
-"@esbuild/linux-loong64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz#a6184e62bd7cdc63e0c0448b83801001653219c5"
- integrity sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==
-
-"@esbuild/linux-mips64el@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz#d08e39ce86f45ef8fc88549d29c62b8acf5649aa"
- integrity sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==
-
-"@esbuild/linux-ppc64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz#8d252f0b7756ffd6d1cbde5ea67ff8fd20437f20"
- integrity sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==
-
-"@esbuild/linux-riscv64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz#19f6dcdb14409dae607f66ca1181dd4e9db81300"
- integrity sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==
-
-"@esbuild/linux-s390x@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz#3c830c90f1a5d7dd1473d5595ea4ebb920988685"
- integrity sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==
-
-"@esbuild/linux-x64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz#86eca35203afc0d9de0694c64ec0ab0a378f6fff"
- integrity sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==
-
-"@esbuild/netbsd-x64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz#e771c8eb0e0f6e1877ffd4220036b98aed5915e6"
- integrity sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==
-
-"@esbuild/openbsd-x64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz#9a795ae4b4e37e674f0f4d716f3e226dd7c39baf"
- integrity sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==
-
-"@esbuild/sunos-x64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz#7df23b61a497b8ac189def6e25a95673caedb03f"
- integrity sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==
-
-"@esbuild/win32-arm64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz#f1ae5abf9ca052ae11c1bc806fb4c0f519bacf90"
- integrity sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==
-
-"@esbuild/win32-ia32@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz#241fe62c34d8e8461cd708277813e1d0ba55ce23"
- integrity sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==
-
-"@esbuild/win32-x64@0.20.2":
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz#9c907b21e30a52db959ba4f80bb01a0cc403d5cc"
- integrity sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==
-
-"@istanbuljs/schema@^0.1.2":
- version "0.1.3"
- resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98"
- integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==
-
-"@jest/schemas@^29.6.3":
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03"
- integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==
- dependencies:
- "@sinclair/typebox" "^0.27.8"
-
-"@jridgewell/gen-mapping@^0.3.5":
- version "0.3.5"
- resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36"
- integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==
- dependencies:
- "@jridgewell/set-array" "^1.2.1"
- "@jridgewell/sourcemap-codec" "^1.4.10"
- "@jridgewell/trace-mapping" "^0.3.24"
-
"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0":
version "3.1.2"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
-"@jridgewell/set-array@^1.2.1":
- version "1.2.1"
- resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280"
- integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==
-
-"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15":
+"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14":
version "1.4.15"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+"@jridgewell/sourcemap-codec@^1.5.5":
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.6.0.tgz#f4c663e862f06dc98ca4d453862c46902789a18d"
+ integrity sha512-T7jf+5zgsZHwNJ4lvQ7/aezbyk0nNX+zJVWpmHA7VYsEx7a7qr5Rg5IbtJFqkgze5Y2sruq1RUY8Q837Od7iFw==
+
"@jridgewell/trace-mapping@0.3.9":
version "0.3.9"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
@@ -244,98 +106,103 @@
"@jridgewell/resolve-uri" "^3.0.3"
"@jridgewell/sourcemap-codec" "^1.4.10"
-"@jridgewell/trace-mapping@^0.3.23", "@jridgewell/trace-mapping@^0.3.24":
- version "0.3.25"
- resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0"
- integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==
+"@jridgewell/trace-mapping@^0.3.31":
+ version "0.3.31"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz#db15d6781c931f3a251a3dac39501c98a6082fd0"
+ integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==
dependencies:
"@jridgewell/resolve-uri" "^3.1.0"
"@jridgewell/sourcemap-codec" "^1.4.14"
-"@rollup/rollup-android-arm-eabi@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.18.0.tgz#bbd0e616b2078cd2d68afc9824d1fadb2f2ffd27"
- integrity sha512-Tya6xypR10giZV1XzxmH5wr25VcZSncG0pZIjfePT0OVBvqNEurzValetGNarVrGiq66EBVAFn15iYX4w6FKgQ==
-
-"@rollup/rollup-android-arm64@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.18.0.tgz#97255ef6384c5f73f4800c0de91f5f6518e21203"
- integrity sha512-avCea0RAP03lTsDhEyfy+hpfr85KfyTctMADqHVhLAF3MlIkq83CP8UfAHUssgXTYd+6er6PaAhx/QGv4L1EiA==
-
-"@rollup/rollup-darwin-arm64@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.18.0.tgz#b6dd74e117510dfe94541646067b0545b42ff096"
- integrity sha512-IWfdwU7KDSm07Ty0PuA/W2JYoZ4iTj3TUQjkVsO/6U+4I1jN5lcR71ZEvRh52sDOERdnNhhHU57UITXz5jC1/w==
-
-"@rollup/rollup-darwin-x64@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.18.0.tgz#e07d76de1cec987673e7f3d48ccb8e106d42c05c"
- integrity sha512-n2LMsUz7Ynu7DoQrSQkBf8iNrjOGyPLrdSg802vk6XT3FtsgX6JbE8IHRvposskFm9SNxzkLYGSq9QdpLYpRNA==
-
-"@rollup/rollup-linux-arm-gnueabihf@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.18.0.tgz#9f1a6d218b560c9d75185af4b8bb42f9f24736b8"
- integrity sha512-C/zbRYRXFjWvz9Z4haRxcTdnkPt1BtCkz+7RtBSuNmKzMzp3ZxdM28Mpccn6pt28/UWUCTXa+b0Mx1k3g6NOMA==
-
-"@rollup/rollup-linux-arm-musleabihf@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.18.0.tgz#53618b92e6ffb642c7b620e6e528446511330549"
- integrity sha512-l3m9ewPgjQSXrUMHg93vt0hYCGnrMOcUpTz6FLtbwljo2HluS4zTXFy2571YQbisTnfTKPZ01u/ukJdQTLGh9A==
-
-"@rollup/rollup-linux-arm64-gnu@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.18.0.tgz#99a7ba5e719d4f053761a698f7b52291cefba577"
- integrity sha512-rJ5D47d8WD7J+7STKdCUAgmQk49xuFrRi9pZkWoRD1UeSMakbcepWXPF8ycChBoAqs1pb2wzvbY6Q33WmN2ftw==
-
-"@rollup/rollup-linux-arm64-musl@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.18.0.tgz#f53db99a45d9bc00ce94db8a35efa7c3c144a58c"
- integrity sha512-be6Yx37b24ZwxQ+wOQXXLZqpq4jTckJhtGlWGZs68TgdKXJgw54lUUoFYrg6Zs/kjzAQwEwYbp8JxZVzZLRepQ==
-
-"@rollup/rollup-linux-powerpc64le-gnu@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.18.0.tgz#cbb0837408fe081ce3435cf3730e090febafc9bf"
- integrity sha512-hNVMQK+qrA9Todu9+wqrXOHxFiD5YmdEi3paj6vP02Kx1hjd2LLYR2eaN7DsEshg09+9uzWi2W18MJDlG0cxJA==
-
-"@rollup/rollup-linux-riscv64-gnu@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.18.0.tgz#8ed09c1d1262ada4c38d791a28ae0fea28b80cc9"
- integrity sha512-ROCM7i+m1NfdrsmvwSzoxp9HFtmKGHEqu5NNDiZWQtXLA8S5HBCkVvKAxJ8U+CVctHwV2Gb5VUaK7UAkzhDjlg==
-
-"@rollup/rollup-linux-s390x-gnu@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.18.0.tgz#938138d3c8e0c96f022252a28441dcfb17afd7ec"
- integrity sha512-0UyyRHyDN42QL+NbqevXIIUnKA47A+45WyasO+y2bGJ1mhQrfrtXUpTxCOrfxCR4esV3/RLYyucGVPiUsO8xjg==
-
-"@rollup/rollup-linux-x64-gnu@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.18.0.tgz#1a7481137a54740bee1ded4ae5752450f155d942"
- integrity sha512-xuglR2rBVHA5UsI8h8UbX4VJ470PtGCf5Vpswh7p2ukaqBGFTnsfzxUBetoWBWymHMxbIG0Cmx7Y9qDZzr648w==
-
-"@rollup/rollup-linux-x64-musl@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.18.0.tgz#f1186afc601ac4f4fc25fac4ca15ecbee3a1874d"
- integrity sha512-LKaqQL9osY/ir2geuLVvRRs+utWUNilzdE90TpyoX0eNqPzWjRm14oMEE+YLve4k/NAqCdPkGYDaDF5Sw+xBfg==
-
-"@rollup/rollup-win32-arm64-msvc@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.18.0.tgz#ed6603e93636a96203c6915be4117245c1bd2daf"
- integrity sha512-7J6TkZQFGo9qBKH0pk2cEVSRhJbL6MtfWxth7Y5YmZs57Pi+4x6c2dStAUvaQkHQLnEQv1jzBUW43GvZW8OFqA==
-
-"@rollup/rollup-win32-ia32-msvc@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.18.0.tgz#14e0b404b1c25ebe6157a15edb9c46959ba74c54"
- integrity sha512-Txjh+IxBPbkUB9+SXZMpv+b/vnTEtFyfWZgJ6iyCmt2tdx0OF5WhFowLmnh8ENGNpfUlUZkdI//4IEmhwPieNg==
-
-"@rollup/rollup-win32-x64-msvc@4.18.0":
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.18.0.tgz#5d694d345ce36b6ecf657349e03eb87297e68da4"
- integrity sha512-UOo5FdvOL0+eIVTgS4tIdbW+TtnBLWg1YBCcU2KWM7nuNwRz9bksDX1bekJJCpu25N1DVWaCwnT39dVQxzqS8g==
-
-"@sinclair/typebox@^0.27.8":
- version "0.27.8"
- resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e"
- integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==
+"@oxc-project/types@=0.154.0":
+ version "0.154.0"
+ resolved "https://registry.yarnpkg.com/@oxc-project/types/-/types-0.154.0.tgz#0a4f2adaeef41d1931861adca8166b7615e5a49a"
+ integrity sha512-KYOUGQFlLWR+s4QMV2Q9ko38TZm7EdO87Qm7rvZLqk/webse/cDjtyxKhg/47l0byCbs/k46LT8qc4PKjAikzA==
+
+"@rolldown/binding-android-arm-eabi@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm-eabi/-/binding-android-arm-eabi-1.2.14.tgz#4e56a59bff8b2756fb6474ed4af7fcb1f19e96ed"
+ integrity sha512-aWR+XKH9+rW7m5fWq/5360J3mHycrx/o6xZM2DQFdJnTMdyP7/WzxPjhtLbVWdKo2y612/4U1bWqb3HQhiF7vg==
+
+"@rolldown/binding-android-arm64@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-android-arm64/-/binding-android-arm64-1.2.14.tgz#71988681aae082ae949e593037fbb331577c5078"
+ integrity sha512-QiVxHofl6A8lQU7WAtOUY4QMVZXohxwz7WJJoeh8NBEUyKfIkMRKhYyq8az/1RypNiIXzNTtiS6KwHz0erxYRQ==
+
+"@rolldown/binding-darwin-arm64@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-arm64/-/binding-darwin-arm64-1.2.14.tgz#33fcab8a34317f9022b8ae8753ff77289c084116"
+ integrity sha512-lTQOzHuBIooh3jIr5XINQkjPGEuGy+Dsy0meXDr6Sjty0b99kYgGh4uBC/8mJX1T0kC8d6S0aPP1Y+bHkh6aBw==
+
+"@rolldown/binding-darwin-x64@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-darwin-x64/-/binding-darwin-x64-1.2.14.tgz#3503ef66841b9a55e97c4f91618eb5583f03686c"
+ integrity sha512-hyMKEGatjmBYCs/Q4sbIcL/GqpFEqsX3wc+HYVQ/85A4rxc1o7rPm4DUI4GV4k/h0ITddwFSGpqQunI14GXjTA==
+
+"@rolldown/binding-freebsd-x64@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-freebsd-x64/-/binding-freebsd-x64-1.2.14.tgz#1bbe60ec663fd61637d2f419fccb4fad734c5f10"
+ integrity sha512-u371GbXoVXrEgP20PwzoGNOdAOqAMhzo19JzzY+V4YmmnC+DTOoqdbMu+O+54emM59Mik/UdrtWgcuEDKWRPKA==
+
+"@rolldown/binding-linux-arm-gnueabihf@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm-gnueabihf/-/binding-linux-arm-gnueabihf-1.2.14.tgz#e371df969ce60cac6d439309d2040c49392f3aa6"
+ integrity sha512-BqwKsdZQf6EqVWr8fv2MrDYzAvOZ7+NYFSJESRGs87fkseEhs0TU9TXgRJTkZoRRkxTizyEg1LKUXfU3/78uqg==
+
+"@rolldown/binding-linux-arm64-gnu@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-gnu/-/binding-linux-arm64-gnu-1.2.14.tgz#173abeead293d60b3002ef8714978040af0f47b3"
+ integrity sha512-SD9kY8M009x/7s57Z1dgUVlP5+uYBgKQK0Tkr1WIWngrtUJmRCW1RJFMY7QDla2khXhmg2i5Io7MUjcmZNZ/KQ==
+
+"@rolldown/binding-linux-arm64-musl@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-arm64-musl/-/binding-linux-arm64-musl-1.2.14.tgz#8f3133a19e603296b19e5899e05ddcaa5e839d7b"
+ integrity sha512-BJ2CL19M6uuWesMgnqJzgxoI+N+eV7b0A9O9vLV42y+gitC41fNa8KElau1tHVzuLWX5GzEuxMPhAO0tQXQMkg==
+
+"@rolldown/binding-linux-ppc64-gnu@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-ppc64-gnu/-/binding-linux-ppc64-gnu-1.2.14.tgz#c1625cd699e119a8f7b3ff98c56ac3e27fc7056d"
+ integrity sha512-4+Kl8daPV8NDHaD7mfCcc1pRM+Qg7ab8DyMm5FG5WoZgv4h2i3KFN1CybYBNbQqmuYm7ftJLvmMI1eHYJ22S/Q==
+
+"@rolldown/binding-linux-s390x-gnu@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-s390x-gnu/-/binding-linux-s390x-gnu-1.2.14.tgz#b9e48c9f00289a2df6f8e1fad7448e6c643ad52d"
+ integrity sha512-V/h8ePq1fKDrmtFMz6xcCN3DKvuvMRrwwD1q0PkBeeo4DpK64biaKvqWGVxqCeYKqeRk7gE7/iKPxLCn08O97A==
+
+"@rolldown/binding-linux-x64-gnu@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-gnu/-/binding-linux-x64-gnu-1.2.14.tgz#9326add90ba3219102c151e1274fa35eef17dc3b"
+ integrity sha512-WxalXzgrLVpKC93xfpaJ3gCXUWzeCr+FRCbDVD2mUAy4L6Vo3lNVz0epUEUpxPWJkLNYUwM4OSIikv36OJ9mLg==
+
+"@rolldown/binding-linux-x64-musl@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-linux-x64-musl/-/binding-linux-x64-musl-1.2.14.tgz#8e11f27cb56a92276fcabd6f7accbef7089160b3"
+ integrity sha512-3G3tnAmTpdk9jO3GQtyHXqeFD2SlecfTws/Y3M2mmj9nMBwwuLT4kur8sZKeu7ENUHSpVO3cIsm5A52LEWWwlg==
+
+"@rolldown/binding-openharmony-arm64@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-openharmony-arm64/-/binding-openharmony-arm64-1.2.14.tgz#784873879d9f655de52b5ce1085879a3471d0fd8"
+ integrity sha512-qyr5XiNGxm2ytx17vvtcJ9nXn6v1gENETi503bJx3OGwZ1tSonj7BosxbMa/xeAfSl5iS9X6KjEWYXLu6v1L7Q==
+
+"@rolldown/binding-win32-arm64-msvc@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-arm64-msvc/-/binding-win32-arm64-msvc-1.2.14.tgz#6a656838c13a51defad46592ee613ec2c27ae49f"
+ integrity sha512-oA4o5o0S2yB199YyYXDzKUv1Z56Rc+mgOjwm7Z/vJ9Z8igiDPYvoOuDyo6g7AK/ZaF09nPhDKVnGBcYHO11GXA==
+
+"@rolldown/binding-win32-x64-msvc@1.2.14":
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/@rolldown/binding-win32-x64-msvc/-/binding-win32-x64-msvc-1.2.14.tgz#f1a24048db1677c1d985a52c922e88c5dbe75e0d"
+ integrity sha512-9mE94bf2GZUaR/fUSXCMpBoWkctu421Mi0ORpm4zqfbkjKep7RxzPFa5etcGs5h+2KApoWBOA/hAJa/7saGgEQ==
+
+"@rolldown/pluginutils@^1.0.0":
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/@rolldown/pluginutils/-/pluginutils-1.0.1.tgz#e3fcee093fbb5ce765e1ad088ff4de2889f6f9be"
+ integrity sha512-2j9bGt5Jh8hj+vPtgzPtl72j0yRxHAyumoo6TNfAjsLB04UtpSvPbPcDcBMxz7n+9CYB0c1GxQFxYRg2jimqGw==
+
+"@standard-schema/spec@^1.1.0":
+ version "1.1.0"
+ resolved "https://registry.yarnpkg.com/@standard-schema/spec/-/spec-1.1.0.tgz#a79b55dbaf8604812f52d140b2c9ab41bc150bb8"
+ integrity sha512-l2aFy5jALhniG5HgqrD6jXLi/rUWrKvqN/qJx6yoJsgKhblVd+iqqU4RCXavm/jPityDo5TCvKMnpjKnOriy0w==
"@testing-library/dom@^8.5.0":
version "8.20.1"
@@ -404,12 +271,25 @@
resolved "https://registry.yarnpkg.com/@types/aria-query/-/aria-query-5.0.4.tgz#1a31c3d378850d2778dabb6374d036dcba4ba708"
integrity sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==
+"@types/chai@^5.2.2":
+ version "5.2.3"
+ resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.3.tgz#8e9cd9e1c3581fa6b341a5aed5588eb285be0b4a"
+ integrity sha512-Mw558oeA9fFbv65/y4mHtXDs9bPnFMZAL/jxdPFUpOHHIXX91mcgEHbS5Lahr+pwZFR8A7GQleRWeI6cGFC2UA==
+ dependencies:
+ "@types/deep-eql" "*"
+ assertion-error "^2.0.1"
+
"@types/core-js@^2.5.5":
version "2.5.8"
resolved "https://registry.yarnpkg.com/@types/core-js/-/core-js-2.5.8.tgz#d5c6ec44f2f3328653dce385ae586bd8261f8e85"
integrity sha512-VgnAj6tIAhJhZdJ8/IpxdatM8G4OD3VWGlp6xIxUGENZlpbob9Ty4VVdC1FIEp0aK6DBscDDjyzy5FB60TuNqg==
-"@types/estree@1.0.5", "@types/estree@^1.0.0":
+"@types/deep-eql@*":
+ version "4.0.2"
+ resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd"
+ integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw==
+
+"@types/estree@^1.0.0":
version "1.0.5"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4"
integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==
@@ -434,75 +314,88 @@
"@types/prop-types" "*"
csstype "^3.0.2"
-"@vitest/coverage-v8@^1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-1.6.0.tgz#2f54ccf4c2d9f23a71294aba7f95b3d2e27d14e7"
- integrity sha512-KvapcbMY/8GYIG0rlwwOKCVNRc0OL20rrhFkg/CHNzncV03TE2XWvO5w9uZYoxNiMEBacAJt3unSOiZ7svePew==
+"@vitest/coverage-v8@^4.0.18":
+ version "4.1.12"
+ resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-4.1.12.tgz#d4633b3cb3fddad0f671689883cd5f8dcdc83e91"
+ integrity sha512-6S7/iVknKglLAxMFxQGNppBI0iqJS2NgM6FBxavitj7KaDq/vywOWGf6dGu7F2L1Qy0G6S3uTp7aGshHrzK8JA==
dependencies:
- "@ampproject/remapping" "^2.2.1"
- "@bcoe/v8-coverage" "^0.2.3"
- debug "^4.3.4"
+ "@bcoe/v8-coverage" "^1.0.2"
+ "@vitest/utils" "4.1.12"
+ ast-v8-to-istanbul "^1.0.0"
istanbul-lib-coverage "^3.2.2"
istanbul-lib-report "^3.0.1"
- istanbul-lib-source-maps "^5.0.4"
- istanbul-reports "^3.1.6"
- magic-string "^0.30.5"
- magicast "^0.3.3"
- picocolors "^1.0.0"
- std-env "^3.5.0"
- strip-literal "^2.0.0"
- test-exclude "^6.0.0"
+ istanbul-reports "^3.2.0"
+ magicast "^0.5.2"
+ obug "^2.1.1"
+ std-env "^4.0.0-rc.1"
+ tinyrainbow "^3.1.0"
+
+"@vitest/expect@4.1.12":
+ version "4.1.12"
+ resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-4.1.12.tgz#e12b5f114e548252a6eee50f6619f1b8f0f89eed"
+ integrity sha512-vFlTt+YEu9WBpNjdGayNmlMVzrWPi1+sv853/7t2FU7hpO5gAFBKHzQmkCq5Xjpr+evegF2994LQT3hF3mRlqQ==
+ dependencies:
+ "@standard-schema/spec" "^1.1.0"
+ "@types/chai" "^5.2.2"
+ "@vitest/spy" "4.1.12"
+ "@vitest/utils" "4.1.12"
+ chai "^6.2.2"
+ tinyrainbow "^3.1.0"
+
+"@vitest/mocker@4.1.12":
+ version "4.1.12"
+ resolved "https://registry.yarnpkg.com/@vitest/mocker/-/mocker-4.1.12.tgz#13b241597b79695e401fd05b363bb8e79695dfac"
+ integrity sha512-fKShNpKZzupWZuY0z7egydvL0sqW4INEZBEExMBMAa6izlENEVHwoXgdaTCaBZ5fwlr4xf2o1wXC83n9RpO+NA==
+ dependencies:
+ "@vitest/spy" "4.1.12"
+ estree-walker "^3.0.3"
+ magic-string "^0.30.21"
-"@vitest/expect@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.6.0.tgz#0b3ba0914f738508464983f4d811bc122b51fb30"
- integrity sha512-ixEvFVQjycy/oNgHjqsL6AZCDduC+tflRluaHIzKIsdbzkLn2U/iBnVeJwB6HsIjQBdfMR8Z0tRxKUsvFJEeWQ==
+"@vitest/pretty-format@4.1.12":
+ version "4.1.12"
+ resolved "https://registry.yarnpkg.com/@vitest/pretty-format/-/pretty-format-4.1.12.tgz#396d123c8905e0a7c3dde02d5ba84ed8f983fdbf"
+ integrity sha512-XW9O8+Mxx4VpCtkYdMJLZQQwsVryP9wk7cPKDxtXFfwSak6yRh5+2fep/Y0XF/ElBvJHq8bcYdi6aeuai0opZA==
dependencies:
- "@vitest/spy" "1.6.0"
- "@vitest/utils" "1.6.0"
- chai "^4.3.10"
+ tinyrainbow "^3.1.0"
-"@vitest/runner@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.6.0.tgz#a6de49a96cb33b0e3ba0d9064a3e8d6ce2f08825"
- integrity sha512-P4xgwPjwesuBiHisAVz/LSSZtDjOTPYZVmNAnpHHSR6ONrf8eCJOFRvUwdHn30F5M1fxhqtl7QZQUk2dprIXAg==
+"@vitest/runner@4.1.12":
+ version "4.1.12"
+ resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-4.1.12.tgz#4c4e267b2011e7dcc5a84a9271caaaf880d80c02"
+ integrity sha512-NKlVKCr5QnCe8jijdMnmkpHHU+WTqiLFR6G0pHji9uRjXK9xJl1k1nTw6F3pOOj2PDcsDt2GKQMI7wIsaT491w==
dependencies:
- "@vitest/utils" "1.6.0"
- p-limit "^5.0.0"
- pathe "^1.1.1"
+ "@vitest/utils" "4.1.12"
+ pathe "^2.0.3"
-"@vitest/snapshot@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.6.0.tgz#deb7e4498a5299c1198136f56e6e0f692e6af470"
- integrity sha512-+Hx43f8Chus+DCmygqqfetcAZrDJwvTj0ymqjQq4CvmpKFSTVteEOBzCusu1x2tt4OJcvBflyHUE0DZSLgEMtQ==
+"@vitest/snapshot@4.1.12":
+ version "4.1.12"
+ resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-4.1.12.tgz#53670a17d3d804e651195d5babab1bf2fd83688a"
+ integrity sha512-ko1y1Qgb/slzQ9mr+b89Cuqud8WG1TKtsPD8r7ZUBdvVOGt85Af2HwCqHujrhwJq95hs/9RM7fcAPg57o1vlzw==
dependencies:
- magic-string "^0.30.5"
- pathe "^1.1.1"
- pretty-format "^29.7.0"
+ "@vitest/pretty-format" "4.1.12"
+ "@vitest/utils" "4.1.12"
+ magic-string "^0.30.21"
+ pathe "^2.0.3"
-"@vitest/spy@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.6.0.tgz#362cbd42ccdb03f1613798fde99799649516906d"
- integrity sha512-leUTap6B/cqi/bQkXUu6bQV5TZPx7pmMBKBQiI0rJA8c3pB56ZsaTbREnF7CJfmvAS4V2cXIBAh/3rVwrrCYgw==
- dependencies:
- tinyspy "^2.2.0"
+"@vitest/spy@4.1.12":
+ version "4.1.12"
+ resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-4.1.12.tgz#59b02f0735cdff0644e1664d433b084b4b80ec04"
+ integrity sha512-RGq9x4JNGNTZHEJxvN0oSiJjeSCExm0n2gZKKJZHY9cX5AVA6M7VJILBT3ZJ/tJ/0J9uWT7fETV9/btoi//vSg==
-"@vitest/utils@1.6.0":
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.6.0.tgz#5c5675ca7d6f546a7b4337de9ae882e6c57896a1"
- integrity sha512-21cPiuGMoMZwiOHa2i4LXkMkMkCGzA+MVFV70jRwHo95dL4x/ts5GZhML1QWuy7yfp3WzK3lRvZi3JnXTYqrBw==
+"@vitest/utils@4.1.12":
+ version "4.1.12"
+ resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-4.1.12.tgz#e5416ed6c2313ded30dd9eae5fc08cba11fcacb3"
+ integrity sha512-Q3awXrwOfEV+qc3WmO5ONyE0yO7Q1gQ9/oyHxGLZ/pl7N3NO/ZztqQwKLuwMkV+CA1JYSIeO3gkHnRDIo4AVaA==
dependencies:
- diff-sequences "^29.6.3"
- estree-walker "^3.0.3"
- loupe "^2.3.7"
- pretty-format "^29.7.0"
+ "@vitest/pretty-format" "4.1.12"
+ convert-source-map "^2.0.0"
+ tinyrainbow "^3.1.0"
-acorn-walk@^8.1.1, acorn-walk@^8.3.2:
+acorn-walk@^8.1.1:
version "8.3.2"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa"
integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==
-acorn@^8.11.3, acorn@^8.4.1:
+acorn@^8.4.1:
version "8.11.3"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
@@ -565,10 +458,19 @@ array-buffer-byte-length@^1.0.0:
call-bind "^1.0.5"
is-array-buffer "^3.0.4"
-assertion-error@^1.1.0:
- version "1.1.0"
- resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b"
- integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==
+assertion-error@^2.0.1:
+ version "2.0.1"
+ resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7"
+ integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==
+
+ast-v8-to-istanbul@^1.0.0:
+ version "1.0.7"
+ resolved "https://registry.yarnpkg.com/ast-v8-to-istanbul/-/ast-v8-to-istanbul-1.0.7.tgz#ead45f98ca59413f048f1b1466a78b6c8a1070bb"
+ integrity sha512-kFL68AG6ajd8fg248zwM9GQrUWEp79gsmjum34OEXjs4yHuUMZfYKwOLW9GMmB4oNvVrj+EAGxsP7ye2UR9UlA==
+ dependencies:
+ "@jridgewell/trace-mapping" "^0.3.31"
+ estree-walker "^3.0.3"
+ js-tokens "^10.0.0"
asynckit@^0.4.0:
version "0.4.0"
@@ -582,24 +484,6 @@ available-typed-arrays@^1.0.7:
dependencies:
possible-typed-array-names "^1.0.0"
-balanced-match@^1.0.0:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
- integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
-
-brace-expansion@^1.1.7:
- version "1.1.11"
- resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd"
- integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==
- dependencies:
- balanced-match "^1.0.0"
- concat-map "0.0.1"
-
-cac@^6.7.14:
- version "6.7.14"
- resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959"
- integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==
-
call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9"
@@ -611,18 +495,10 @@ call-bind@^1.0.2, call-bind@^1.0.5, call-bind@^1.0.6, call-bind@^1.0.7:
get-intrinsic "^1.2.4"
set-function-length "^1.2.1"
-chai@^4.3.10:
- version "4.4.1"
- resolved "https://registry.yarnpkg.com/chai/-/chai-4.4.1.tgz#3603fa6eba35425b0f2ac91a009fe924106e50d1"
- integrity sha512-13sOfMv2+DWduEU+/xbun3LScLoqN17nBeTLUsmDfKdoiC1fr0n9PU4guu4AhRcOVFk/sW8LyZWHuhWtQZiF+g==
- dependencies:
- assertion-error "^1.1.0"
- check-error "^1.0.3"
- deep-eql "^4.1.3"
- get-func-name "^2.0.2"
- loupe "^2.3.6"
- pathval "^1.1.1"
- type-detect "^4.0.8"
+chai@^6.2.2:
+ version "6.3.0"
+ resolved "https://registry.yarnpkg.com/chai/-/chai-6.3.0.tgz#91f89eb789c2bb1ae1787d78c8518e1d3cebfc07"
+ integrity sha512-XWAtwJ6OHO+tj0EKCs0Y2UamnyOxseZWltU4x2U2wh8g4AigdjwvtUjvLP2tqkA/avxHEtzxNaqGq/YGNwckKg==
chalk@^2.4.2:
version "2.4.2"
@@ -649,13 +525,6 @@ chalk@^4.1.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
-check-error@^1.0.3:
- version "1.0.3"
- resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694"
- integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==
- dependencies:
- get-func-name "^2.0.2"
-
color-convert@^1.9.0:
version "1.9.3"
resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8"
@@ -687,15 +556,10 @@ combined-stream@^1.0.8:
dependencies:
delayed-stream "~1.0.0"
-concat-map@0.0.1:
- version "0.0.1"
- resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b"
- integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==
-
-confbox@^0.1.7:
- version "0.1.7"
- resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.7.tgz#ccfc0a2bcae36a84838e83a3b7f770fb17d6c579"
- integrity sha512-uJcB/FKZtBMCJpK8MQji6bJHgu1tixKPxRLeGkNzBoOZzpnZUJm0jm2/sBDWcuBx1dYgxV4JU+g5hmNxCyAmdA==
+convert-source-map@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a"
+ integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==
core-js@^3.20.0, core-js@^3.26.0:
version "3.37.1"
@@ -707,15 +571,6 @@ create-require@^1.1.0:
resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
-cross-spawn@^7.0.3:
- version "7.0.3"
- resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
- integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
- dependencies:
- path-key "^3.1.0"
- shebang-command "^2.0.0"
- which "^2.0.1"
-
css.escape@^1.5.1:
version "1.5.1"
resolved "https://registry.yarnpkg.com/css.escape/-/css.escape-1.5.1.tgz#42e27d4fa04ae32f931a4b4d4191fa9cddee97cb"
@@ -741,7 +596,7 @@ data-urls@^5.0.0:
whatwg-mimetype "^4.0.0"
whatwg-url "^14.0.0"
-debug@4, debug@^4.1.1, debug@^4.3.4:
+debug@4, debug@^4.3.4:
version "4.3.5"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.5.tgz#e83444eceb9fedd4a1da56d671ae2446a01a6e1e"
integrity sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==
@@ -753,13 +608,6 @@ decimal.js@^10.4.3:
resolved "https://registry.yarnpkg.com/decimal.js/-/decimal.js-10.4.3.tgz#1044092884d245d1b7f65725fa4ad4c6f781cc23"
integrity sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA==
-deep-eql@^4.1.3:
- version "4.1.3"
- resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d"
- integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==
- dependencies:
- type-detect "^4.0.0"
-
deep-equal@^2.0.5:
version "2.2.3"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-2.2.3.tgz#af89dafb23a396c7da3e862abc0be27cf51d56e1"
@@ -812,10 +660,10 @@ dequal@^2.0.3:
resolved "https://registry.yarnpkg.com/dequal/-/dequal-2.0.3.tgz#2644214f1997d39ed0ee0ece72335490a7ac67be"
integrity sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==
-diff-sequences@^29.6.3:
- version "29.6.3"
- resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921"
- integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==
+detect-libc@^2.0.3:
+ version "2.1.2"
+ resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.1.2.tgz#689c5dcdc1900ef5583a4cb9f6d7b473742074ad"
+ integrity sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==
diff@^4.0.1:
version "4.0.2"
@@ -864,34 +712,10 @@ es-get-iterator@^1.1.3:
isarray "^2.0.5"
stop-iteration-iterator "^1.0.0"
-esbuild@^0.20.1:
- version "0.20.2"
- resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.20.2.tgz#9d6b2386561766ee6b5a55196c6d766d28c87ea1"
- integrity sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==
- optionalDependencies:
- "@esbuild/aix-ppc64" "0.20.2"
- "@esbuild/android-arm" "0.20.2"
- "@esbuild/android-arm64" "0.20.2"
- "@esbuild/android-x64" "0.20.2"
- "@esbuild/darwin-arm64" "0.20.2"
- "@esbuild/darwin-x64" "0.20.2"
- "@esbuild/freebsd-arm64" "0.20.2"
- "@esbuild/freebsd-x64" "0.20.2"
- "@esbuild/linux-arm" "0.20.2"
- "@esbuild/linux-arm64" "0.20.2"
- "@esbuild/linux-ia32" "0.20.2"
- "@esbuild/linux-loong64" "0.20.2"
- "@esbuild/linux-mips64el" "0.20.2"
- "@esbuild/linux-ppc64" "0.20.2"
- "@esbuild/linux-riscv64" "0.20.2"
- "@esbuild/linux-s390x" "0.20.2"
- "@esbuild/linux-x64" "0.20.2"
- "@esbuild/netbsd-x64" "0.20.2"
- "@esbuild/openbsd-x64" "0.20.2"
- "@esbuild/sunos-x64" "0.20.2"
- "@esbuild/win32-arm64" "0.20.2"
- "@esbuild/win32-ia32" "0.20.2"
- "@esbuild/win32-x64" "0.20.2"
+es-module-lexer@^2.0.0:
+ version "2.3.2"
+ resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-2.3.2.tgz#311fa4f40168c1975c505477c51b23234d41ad55"
+ integrity sha512-poHGpORABojJJucnV9KbOavETW8lBVnphkW77ER5/BQ5Fz7oXSoCNek7IH3vR5nRjdsEz926ibFYX8KtLQmdyw==
escape-string-regexp@^1.0.5:
version "1.0.5"
@@ -905,20 +729,15 @@ estree-walker@^3.0.3:
dependencies:
"@types/estree" "^1.0.0"
-execa@^8.0.1:
- version "8.0.1"
- resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c"
- integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==
- dependencies:
- cross-spawn "^7.0.3"
- get-stream "^8.0.1"
- human-signals "^5.0.0"
- is-stream "^3.0.0"
- merge-stream "^2.0.0"
- npm-run-path "^5.1.0"
- onetime "^6.0.0"
- signal-exit "^4.1.0"
- strip-final-newline "^3.0.0"
+expect-type@^1.3.0:
+ version "1.4.0"
+ resolved "https://registry.yarnpkg.com/expect-type/-/expect-type-1.4.0.tgz#24edf7f0cc69a44d008567ba4594ab96f3c3a3d6"
+ integrity sha512-KfYbmpRm0VbLjEvVa9yGwCi9GI34xvi7A/HXYWQO65CSD2u3MczUJSuwXKFIxlGsgBQizV9q5J9NHj4VG0n+pA==
+
+fdir@^6.5.0:
+ version "6.5.0"
+ resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350"
+ integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==
for-each@^0.3.3:
version "0.3.3"
@@ -936,12 +755,7 @@ form-data@^4.0.0:
combined-stream "^1.0.8"
mime-types "^2.1.12"
-fs.realpath@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
- integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==
-
-fsevents@~2.3.2, fsevents@~2.3.3:
+fsevents@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
@@ -956,11 +770,6 @@ functions-have-names@^1.2.3:
resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834"
integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==
-get-func-name@^2.0.1, get-func-name@^2.0.2:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41"
- integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==
-
get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@^1.2.4:
version "1.2.4"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd"
@@ -972,23 +781,6 @@ get-intrinsic@^1.1.3, get-intrinsic@^1.2.1, get-intrinsic@^1.2.2, get-intrinsic@
has-symbols "^1.0.3"
hasown "^2.0.0"
-get-stream@^8.0.1:
- version "8.0.1"
- resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2"
- integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==
-
-glob@^7.1.4:
- version "7.2.3"
- resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
- integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==
- dependencies:
- fs.realpath "^1.0.0"
- inflight "^1.0.4"
- inherits "2"
- minimatch "^3.1.1"
- once "^1.3.0"
- path-is-absolute "^1.0.0"
-
gopd@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c"
@@ -1070,11 +862,6 @@ https-proxy-agent@^7.0.4:
agent-base "^7.0.2"
debug "4"
-human-signals@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28"
- integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==
-
iconv-lite@0.6.3:
version "0.6.3"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.6.3.tgz#a52f80bf38da1952eb5c681790719871a1a72501"
@@ -1087,19 +874,6 @@ indent-string@^4.0.0:
resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251"
integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==
-inflight@^1.0.4:
- version "1.0.6"
- resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9"
- integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==
- dependencies:
- once "^1.3.0"
- wrappy "1"
-
-inherits@2:
- version "2.0.4"
- resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c"
- integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==
-
internal-slot@^1.0.4:
version "1.0.7"
resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.7.tgz#c06dcca3ed874249881007b0a5523b172a190802"
@@ -1189,11 +963,6 @@ is-shared-array-buffer@^1.0.2:
dependencies:
call-bind "^1.0.7"
-is-stream@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac"
- integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==
-
is-string@^1.0.5, is-string@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd"
@@ -1226,11 +995,6 @@ isarray@^2.0.5:
resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723"
integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==
-isexe@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10"
- integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==
-
istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.2:
version "3.2.2"
resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756"
@@ -1245,33 +1009,24 @@ istanbul-lib-report@^3.0.0, istanbul-lib-report@^3.0.1:
make-dir "^4.0.0"
supports-color "^7.1.0"
-istanbul-lib-source-maps@^5.0.4:
- version "5.0.4"
- resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-5.0.4.tgz#1947003c72a91b6310efeb92d2a91be8804d92c2"
- integrity sha512-wHOoEsNJTVltaJp8eVkm8w+GVkVNHT2YDYo53YdzQEL2gWm1hBX5cGFR9hQJtuGLebidVX7et3+dmDZrmclduw==
- dependencies:
- "@jridgewell/trace-mapping" "^0.3.23"
- debug "^4.1.1"
- istanbul-lib-coverage "^3.0.0"
-
-istanbul-reports@^3.1.6:
- version "3.1.7"
- resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b"
- integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==
+istanbul-reports@^3.2.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.2.0.tgz#cb4535162b5784aa623cee21a7252cf2c807ac93"
+ integrity sha512-HGYWWS/ehqTV3xN10i23tkPkpH46MLCIMFNCaaKNavAXTF1RkqxawEPtnjnGZ6XKSInBKkiOA5BKS+aZiY3AvA==
dependencies:
html-escaper "^2.0.0"
istanbul-lib-report "^3.0.0"
+js-tokens@^10.0.0:
+ version "10.0.0"
+ resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-10.0.0.tgz#dffe7599b4a8bb7fe30aff8d0235234dffb79831"
+ integrity sha512-lM/UBzQmfJRo9ABXbPWemivdCW8V2G8FHaHdypQaIy523snUjog0W71ayWXTjiR+ixeMyVHN2XcpnTd/liPg/Q==
+
"js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499"
integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==
-js-tokens@^9.0.0:
- version "9.0.0"
- resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-9.0.0.tgz#0f893996d6f3ed46df7f0a3b12a03f5fd84223c1"
- integrity sha512-WriZw1luRMlmV3LGJaR6QOJjWwgLUTf89OwT2lUOyjX2dJGBwgmIkbcz+7WFZjrZM635JOIR517++e/67CP9dQ==
-
jsdom@^24.1.0:
version "24.1.0"
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-24.1.0.tgz#0cffdabd42c506788bfecd160e8ac22d4387f971"
@@ -1299,13 +1054,79 @@ jsdom@^24.1.0:
ws "^8.17.0"
xml-name-validator "^5.0.0"
-local-pkg@^0.5.0:
- version "0.5.0"
- resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c"
- integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==
- dependencies:
- mlly "^1.4.2"
- pkg-types "^1.0.3"
+lightningcss-android-arm64@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-android-arm64/-/lightningcss-android-arm64-1.33.0.tgz#9a6841f88ae50fc83502903892b41af41bc2b907"
+ integrity sha512-gEpRTalKdosp4Bb8qWtc2iOgE5SeIHlpS1up9bFq2wAyYhl1UdTObYiHe98zEM9SQvSoqQZ1IQD0JNpg3Ml5pg==
+
+lightningcss-darwin-arm64@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.33.0.tgz#c0f2c31c0bfd19fa4dd3f18e957a1f1a152097d6"
+ integrity sha512-Sciaz8eenNTKn9b3t7+xr0ipTp9YxKQY4npwQ3mrRuL0BAVHBLyZxofhaKBAVtzmtRZ/zTyo0/to4B1uWG/Djg==
+
+lightningcss-darwin-x64@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.33.0.tgz#cb0705965acb538c6683949ce6925fb3cdf7c361"
+ integrity sha512-Z5UPAxzrjlWNNyGy6i65cJzzvgJ5D3T6wMvs+gWpY9d7qRhANrxqAp6LhxIgZhWEw18RfJTGcRxjuLIBr+m8XQ==
+
+lightningcss-freebsd-x64@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.33.0.tgz#763538828b26bab2680dadafcc84ee78b0eb502b"
+ integrity sha512-QQM/Ti/hQajJwCY+RiWuCZ9sdtI/XQk7nDK5vC8kkdwixezOlDgvDx7+RT+QjK6FcFT4MpsuoBnHIo/O3StRRg==
+
+lightningcss-linux-arm-gnueabihf@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.33.0.tgz#6862e3176a331aedbdec1ed352b4d7d0dd0784de"
+ integrity sha512-N7FVBe6iS24MlM6R/4RBTxGhQheZGs7tiQ9U32UtF75NzP5Q7xWPRqLBCKxlRQRk3rY1jCIPLzx7WzOhuUIRLQ==
+
+lightningcss-linux-arm64-gnu@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.33.0.tgz#c6a3a2ed15141daf6bdc2628930f8e39bdf473aa"
+ integrity sha512-j2v/itmy4HlNxlc6voKXYgBqNi0Ng2LShg4z7GufpEgs05P+2suBVyi9I6YHq5uoVFx9ETin3eCEhLVyXGQnKg==
+
+lightningcss-linux-arm64-musl@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.33.0.tgz#7fa1334971fc82845f9827df6ef8a0b20914bac6"
+ integrity sha512-yiO5ROMuYQgXbC60yjZU5CYSFZGKXL0HFATXt9mHJn1+zW55oCtMI9NfcVhYLMFDL7gV7oBPon/EmMMGg2OvtQ==
+
+lightningcss-linux-x64-gnu@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.33.0.tgz#8b927862ea8c2bbc6831a46509244b50d9936e55"
+ integrity sha512-ar+Ju7LmcN0Jo4FpL4hpFybwNG9/3A/Br5KW2n2jyODg3MEZXaDYADdemoNS+BDNfMgKvylJLj4S5tyRActuAg==
+
+lightningcss-linux-x64-musl@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.33.0.tgz#0c525bb077dfd94404c059cfe42dad797e96aeaf"
+ integrity sha512-RYiYbkokw0trfKqqzfF55lginwEPrD3OJDfTuJzFs1MK6iFnDenaz1fqLLtX4ITG3OktJQXOeTaw1awrBAlZPw==
+
+lightningcss-win32-arm64-msvc@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.33.0.tgz#850ee1103dac989cfab50e3ac22d1a69e394e63d"
+ integrity sha512-1K+MPfLSFVpphzpdbfkhlWk6wBrTObBzS2T6db10PNOZgR9GoVsAWzwNyuhUYYbTp23j+4RrncfujZ4uAzXvwA==
+
+lightningcss-win32-x64-msvc@1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.33.0.tgz#e343ae152eed3609dc6e11949d1a3bf39a1c946f"
+ integrity sha512-OlEICDx/Xl0FqSp4bry8zFnCvGpig3Gl4gCquvYwHuqJKEC1+n9NgDniFvqHGmMv1ZkqDJrDqKKSykTDX+ehuA==
+
+lightningcss@^1.33.0:
+ version "1.33.0"
+ resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.33.0.tgz#c08867d71a79385c6e190214fd72fef3e5f95f0b"
+ integrity sha512-WkUDrojuJs0xkgGf2udWxa3yGBRxPtxUkB79i6aCZLRgc7PM8fZe9TosfPDcvEpQZbuFASnHYmRLBLUbmLOIIA==
+ dependencies:
+ detect-libc "^2.0.3"
+ optionalDependencies:
+ lightningcss-android-arm64 "1.33.0"
+ lightningcss-darwin-arm64 "1.33.0"
+ lightningcss-darwin-x64 "1.33.0"
+ lightningcss-freebsd-x64 "1.33.0"
+ lightningcss-linux-arm-gnueabihf "1.33.0"
+ lightningcss-linux-arm64-gnu "1.33.0"
+ lightningcss-linux-arm64-musl "1.33.0"
+ lightningcss-linux-x64-gnu "1.33.0"
+ lightningcss-linux-x64-musl "1.33.0"
+ lightningcss-win32-arm64-msvc "1.33.0"
+ lightningcss-win32-x64-msvc "1.33.0"
lodash@^4.17.21:
version "4.17.21"
@@ -1319,33 +1140,26 @@ loose-envify@^1.1.0:
dependencies:
js-tokens "^3.0.0 || ^4.0.0"
-loupe@^2.3.6, loupe@^2.3.7:
- version "2.3.7"
- resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697"
- integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==
- dependencies:
- get-func-name "^2.0.1"
-
lz-string@^1.5.0:
version "1.5.0"
resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.5.0.tgz#c1ab50f77887b712621201ba9fd4e3a6ed099941"
integrity sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==
-magic-string@^0.30.5:
- version "0.30.10"
- resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.10.tgz#123d9c41a0cb5640c892b041d4cfb3bd0aa4b39e"
- integrity sha512-iIRwTIf0QKV3UAnYK4PU8uiEc4SRh5jX0mwpIwETPpHdhVM4f53RSwS/vXvN1JhGX+Cs7B8qIq3d6AH49O5fAQ==
+magic-string@^0.30.21:
+ version "0.30.21"
+ resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.21.tgz#56763ec09a0fa8091df27879fd94d19078c00d91"
+ integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==
dependencies:
- "@jridgewell/sourcemap-codec" "^1.4.15"
+ "@jridgewell/sourcemap-codec" "^1.5.5"
-magicast@^0.3.3:
- version "0.3.4"
- resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.4.tgz#bbda1791d03190a24b00ff3dd18151e7fd381d19"
- integrity sha512-TyDF/Pn36bBji9rWKHlZe+PZb6Mx5V8IHCSxk7X4aljM4e/vyDvZZYwHewdVaqiA0nb3ghfHU/6AUpDxWoER2Q==
+magicast@^0.5.2:
+ version "0.5.5"
+ resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.5.5.tgz#66dfd87ba2a40b568d97ff0d2b888ad3580519cb"
+ integrity sha512-UicdXN8zQ3JHlxVq+28afMXPr1z7WNY6+7EJnzTdQWkTAlMLF5fNCCKxJHBQwGaNGR11581EiQmQzx73+MvszA==
dependencies:
- "@babel/parser" "^7.24.4"
- "@babel/types" "^7.24.0"
- source-map-js "^1.2.0"
+ "@babel/parser" "^7.29.7"
+ "@babel/types" "^7.29.7"
+ source-map-js "^1.2.1"
make-dir@^4.0.0:
version "4.0.0"
@@ -1359,11 +1173,6 @@ make-error@^1.1.1:
resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
-merge-stream@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60"
- integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==
-
mime-db@1.52.0:
version "1.52.0"
resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.52.0.tgz#bbabcdc02859f4987301c856e3387ce5ec43bf70"
@@ -1376,42 +1185,20 @@ mime-types@^2.1.12:
dependencies:
mime-db "1.52.0"
-mimic-fn@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc"
- integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==
-
min-indent@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/min-indent/-/min-indent-1.0.1.tgz#a63f681673b30571fbe8bc25686ae746eefa9869"
integrity sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==
-minimatch@^3.0.4, minimatch@^3.1.1:
- version "3.1.2"
- resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
- integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==
- dependencies:
- brace-expansion "^1.1.7"
-
-mlly@^1.4.2, mlly@^1.7.0:
- version "1.7.0"
- resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.0.tgz#587383ae40dda23cadb11c3c3cc972b277724271"
- integrity sha512-U9SDaXGEREBYQgfejV97coK0UL1r+qnF2SyO9A3qcI8MzKnsIFKHNVEkrDyNncQTKQQumsasmeq84eNMdBfsNQ==
- dependencies:
- acorn "^8.11.3"
- pathe "^1.1.2"
- pkg-types "^1.1.0"
- ufo "^1.5.3"
-
ms@2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009"
integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==
-nanoid@^3.3.7:
- version "3.3.7"
- resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
- integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
+nanoid@^3.3.20:
+ version "3.3.20"
+ resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.20.tgz#dfd4444d85aa10111ef66ba85ed72e08ba0855d8"
+ integrity sha512-uKdg2G3GNCKQn9byYOpxbGqrT2fGO5KRt5J/8b3pok8rT6qxGWF6hxMyJiEYtAf+FVyYuD9hRaDqX5uPFYJ4ZQ==
node-fetch@^2.6.7:
version "2.7.0"
@@ -1420,13 +1207,6 @@ node-fetch@^2.6.7:
dependencies:
whatwg-url "^5.0.0"
-npm-run-path@^5.1.0:
- version "5.3.0"
- resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.3.0.tgz#e23353d0ebb9317f174e93417e4a4d82d0249e9f"
- integrity sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==
- dependencies:
- path-key "^4.0.0"
-
nwsapi@^2.2.10:
version "2.2.10"
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.10.tgz#0b77a68e21a0b483db70b11fad055906e867cda8"
@@ -1460,26 +1240,10 @@ object.assign@^4.1.4:
has-symbols "^1.0.3"
object-keys "^1.1.1"
-once@^1.3.0:
- version "1.4.0"
- resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1"
- integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==
- dependencies:
- wrappy "1"
-
-onetime@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4"
- integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==
- dependencies:
- mimic-fn "^4.0.0"
-
-p-limit@^5.0.0:
- version "5.0.0"
- resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-5.0.0.tgz#6946d5b7140b649b7a33a027d89b4c625b3a5985"
- integrity sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==
- dependencies:
- yocto-queue "^1.0.0"
+obug@^2.1.1:
+ version "2.2.1"
+ resolved "https://registry.yarnpkg.com/obug/-/obug-2.2.1.tgz#9c453efeeda822050eb9774242e969c784d64d78"
+ integrity sha512-XrsrhT5sybtKI6wakr2SPOlGZWWYbUXZ7a0jT8/QOeAPau+1X/bSegNe5YR75oJmEZQbKningirmGOEJCIk61Q==
parse5@^7.1.2:
version "7.1.2"
@@ -1488,58 +1252,39 @@ parse5@^7.1.2:
dependencies:
entities "^4.4.0"
-path-is-absolute@^1.0.0:
- version "1.0.1"
- resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f"
- integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==
-
-path-key@^3.1.0:
- version "3.1.1"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375"
- integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==
-
-path-key@^4.0.0:
- version "4.0.0"
- resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18"
- integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==
-
-pathe@^1.1.1, pathe@^1.1.2:
- version "1.1.2"
- resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.2.tgz#6c4cb47a945692e48a1ddd6e4094d170516437ec"
- integrity sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==
-
-pathval@^1.1.1:
- version "1.1.1"
- resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d"
- integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==
+pathe@^2.0.3:
+ version "2.0.3"
+ resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716"
+ integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==
picocolors@^1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.1.tgz#a8ad579b571952f0e5d25892de5445bcfe25aaa1"
integrity sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==
-pkg-types@^1.0.3, pkg-types@^1.1.0:
+picocolors@^1.1.1:
version "1.1.1"
- resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.1.1.tgz#07b626880749beb607b0c817af63aac1845a73f2"
- integrity sha512-ko14TjmDuQJ14zsotODv7dBlwxKhUKQEhuhmbqo1uCi9BB0Z2alo/wAXg6q1dTR5TyuqYyWhjtfe/Tsh+X28jQ==
- dependencies:
- confbox "^0.1.7"
- mlly "^1.7.0"
- pathe "^1.1.2"
+ resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
+ integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
+
+picomatch@^4.0.3, picomatch@^4.0.4, picomatch@^4.0.7:
+ version "4.0.7"
+ resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.7.tgz#6313360034ccb36b3dc61ecbdff78121f90fe21f"
+ integrity sha512-qcJu88Q2IWqJsDD529JKMdwGm/dvInW4HvQnRwiH9JtihJvzGOscDtHE3x1pBKeUOTysQ8kVmLnJ2kJu7yhcGA==
possible-typed-array-names@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz#89bb63c6fada2c3e90adc4a647beeeb39cc7bf8f"
integrity sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==
-postcss@^8.4.38:
- version "8.4.38"
- resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.38.tgz#b387d533baf2054288e337066d81c6bee9db9e0e"
- integrity sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==
+postcss@^8.5.29:
+ version "8.5.31"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.31.tgz#d44731fa02f8ae8371629ec7220e2ae0dbdf23ec"
+ integrity sha512-YUbWYCgErwnMAVkjUnYa+KlMBzGpHwiIt/DE7f0G33AuX2LH9UcTk6KgWxd3zRU+pN3u/C+Xl3EnMLM4Hea7Sg==
dependencies:
- nanoid "^3.3.7"
- picocolors "^1.0.0"
- source-map-js "^1.2.0"
+ nanoid "^3.3.20"
+ picocolors "^1.1.1"
+ source-map-js "^1.2.2"
prettier@3.2.5:
version "3.2.5"
@@ -1555,15 +1300,6 @@ pretty-format@^27.0.2:
ansi-styles "^5.0.0"
react-is "^17.0.1"
-pretty-format@^29.7.0:
- version "29.7.0"
- resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812"
- integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==
- dependencies:
- "@jest/schemas" "^29.6.3"
- ansi-styles "^5.0.0"
- react-is "^18.0.0"
-
psl@^1.1.33:
version "1.9.0"
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
@@ -1592,11 +1328,6 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
-react-is@^18.0.0:
- version "18.3.1"
- resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.3.1.tgz#e83557dc12eae63a99e003a46388b1dcbb44db7e"
- integrity sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==
-
react@^18.2.0:
version "18.3.1"
resolved "https://registry.yarnpkg.com/react/-/react-18.3.1.tgz#49ab892009c53933625bd16b2533fc754cab2891"
@@ -1637,30 +1368,29 @@ rfdc@^1.3.0:
resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.1.tgz#2b6d4df52dffe8bb346992a10ea9451f24373a8f"
integrity sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==
-rollup@^4.13.0:
- version "4.18.0"
- resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.18.0.tgz#497f60f0c5308e4602cf41136339fbf87d5f5dda"
- integrity sha512-QmJz14PX3rzbJCN1SG4Xe/bAAX2a6NpCP8ab2vfu2GiUr8AQcr2nCV/oEO3yneFarB67zk8ShlIyWb2LGTb3Sg==
+rolldown@~1.2.12:
+ version "1.2.14"
+ resolved "https://registry.yarnpkg.com/rolldown/-/rolldown-1.2.14.tgz#4005c51ae81e1d07b2e0d22f56d1f040f85aac96"
+ integrity sha512-eTBTTqMR6uHKLgcUqpJP8ntzDI6V4LYA8negAMBEI7gkgVvOdrx6VsvS2Ym+83KhOPdLCHWJu0w7UQFJZhHKNw==
dependencies:
- "@types/estree" "1.0.5"
+ "@oxc-project/types" "=0.154.0"
+ "@rolldown/pluginutils" "^1.0.0"
optionalDependencies:
- "@rollup/rollup-android-arm-eabi" "4.18.0"
- "@rollup/rollup-android-arm64" "4.18.0"
- "@rollup/rollup-darwin-arm64" "4.18.0"
- "@rollup/rollup-darwin-x64" "4.18.0"
- "@rollup/rollup-linux-arm-gnueabihf" "4.18.0"
- "@rollup/rollup-linux-arm-musleabihf" "4.18.0"
- "@rollup/rollup-linux-arm64-gnu" "4.18.0"
- "@rollup/rollup-linux-arm64-musl" "4.18.0"
- "@rollup/rollup-linux-powerpc64le-gnu" "4.18.0"
- "@rollup/rollup-linux-riscv64-gnu" "4.18.0"
- "@rollup/rollup-linux-s390x-gnu" "4.18.0"
- "@rollup/rollup-linux-x64-gnu" "4.18.0"
- "@rollup/rollup-linux-x64-musl" "4.18.0"
- "@rollup/rollup-win32-arm64-msvc" "4.18.0"
- "@rollup/rollup-win32-ia32-msvc" "4.18.0"
- "@rollup/rollup-win32-x64-msvc" "4.18.0"
- fsevents "~2.3.2"
+ "@rolldown/binding-android-arm-eabi" "1.2.14"
+ "@rolldown/binding-android-arm64" "1.2.14"
+ "@rolldown/binding-darwin-arm64" "1.2.14"
+ "@rolldown/binding-darwin-x64" "1.2.14"
+ "@rolldown/binding-freebsd-x64" "1.2.14"
+ "@rolldown/binding-linux-arm-gnueabihf" "1.2.14"
+ "@rolldown/binding-linux-arm64-gnu" "1.2.14"
+ "@rolldown/binding-linux-arm64-musl" "1.2.14"
+ "@rolldown/binding-linux-ppc64-gnu" "1.2.14"
+ "@rolldown/binding-linux-s390x-gnu" "1.2.14"
+ "@rolldown/binding-linux-x64-gnu" "1.2.14"
+ "@rolldown/binding-linux-x64-musl" "1.2.14"
+ "@rolldown/binding-openharmony-arm64" "1.2.14"
+ "@rolldown/binding-win32-arm64-msvc" "1.2.14"
+ "@rolldown/binding-win32-x64-msvc" "1.2.14"
rrweb-cssom@^0.6.0:
version "0.6.0"
@@ -1718,18 +1448,6 @@ set-function-name@^2.0.1:
functions-have-names "^1.2.3"
has-property-descriptors "^1.0.2"
-shebang-command@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea"
- integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==
- dependencies:
- shebang-regex "^3.0.0"
-
-shebang-regex@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172"
- integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==
-
side-channel@^1.0.4:
version "1.0.6"
resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2"
@@ -1745,25 +1463,20 @@ siginfo@^2.0.0:
resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30"
integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==
-signal-exit@^4.1.0:
- version "4.1.0"
- resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04"
- integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==
-
-source-map-js@^1.2.0:
- version "1.2.0"
- resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.0.tgz#16b809c162517b5b8c3e7dcd315a2a5c2612b2af"
- integrity sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==
+source-map-js@^1.2.1, source-map-js@^1.2.2:
+ version "1.2.2"
+ resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.2.tgz#79fb88d97535a21cb27162cb05d211b67acea4ab"
+ integrity sha512-KGj/8Y43x35aZVDtt+J4mK1hoLGHULMYfSkODJNQjNDC3oW1PqPoxMwo0pLUsWM/UEGzON/NxeHywEfNXNP3Vw==
stackback@0.0.2:
version "0.0.2"
resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b"
integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==
-std-env@^3.5.0:
- version "3.7.0"
- resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2"
- integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==
+std-env@^4.0.0-rc.1:
+ version "4.3.0"
+ resolved "https://registry.yarnpkg.com/std-env/-/std-env-4.3.0.tgz#4e7231b61fd83219aa7f76f71fa8818b07e41321"
+ integrity sha512-OtU/EgQ1kIm5KwqQpBC6ZEMXrZRui11w8zgfTWp8cdO9B8OaPsbA8bTHO2P+HNo1VlUTGMVBwPhydu6poeXiag==
stop-iteration-iterator@^1.0.0:
version "1.0.0"
@@ -1772,11 +1485,6 @@ stop-iteration-iterator@^1.0.0:
dependencies:
internal-slot "^1.0.4"
-strip-final-newline@^3.0.0:
- version "3.0.0"
- resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd"
- integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==
-
strip-indent@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/strip-indent/-/strip-indent-3.0.0.tgz#c32e1cee940b6b3432c771bc2c54bcce73cd3001"
@@ -1784,13 +1492,6 @@ strip-indent@^3.0.0:
dependencies:
min-indent "^1.0.0"
-strip-literal@^2.0.0:
- version "2.1.0"
- resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-2.1.0.tgz#6d82ade5e2e74f5c7e8739b6c84692bd65f0bd2a"
- integrity sha512-Op+UycaUt/8FbN/Z2TWPBLge3jWrP3xj10f3fnYxf052bKuS3EKs1ZQcVGjnEMdsNVAM+plXRdmjrZ/KgG3Skw==
- dependencies:
- js-tokens "^9.0.0"
-
supports-color@^5.3.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f"
@@ -1810,34 +1511,28 @@ symbol-tree@^3.2.4:
resolved "https://registry.yarnpkg.com/symbol-tree/-/symbol-tree-3.2.4.tgz#430637d248ba77e078883951fb9aa0eed7c63fa2"
integrity sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==
-test-exclude@^6.0.0:
- version "6.0.0"
- resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e"
- integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==
- dependencies:
- "@istanbuljs/schema" "^0.1.2"
- glob "^7.1.4"
- minimatch "^3.0.4"
-
-tinybench@^2.5.1:
- version "2.8.0"
- resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.8.0.tgz#30e19ae3a27508ee18273ffed9ac7018949acd7b"
- integrity sha512-1/eK7zUnIklz4JUUlL+658n58XO2hHLQfSk1Zf2LKieUjxidN16eKFEoDEfjHc3ohofSSqK3X5yO6VGb6iW8Lw==
+tinybench@^2.9.0:
+ version "2.9.0"
+ resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.9.0.tgz#103c9f8ba6d7237a47ab6dd1dcff77251863426b"
+ integrity sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==
-tinypool@^0.8.3:
- version "0.8.4"
- resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.8.4.tgz#e217fe1270d941b39e98c625dcecebb1408c9aa8"
- integrity sha512-i11VH5gS6IFeLY3gMBQ00/MmLncVP7JLXOw1vlgkytLmJK7QnEr7NXf0LBdxfmNPAeyetukOk0bOYrJrFGjYJQ==
+tinyexec@^1.0.2:
+ version "1.3.1"
+ resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.3.1.tgz#16a2e3c6e23fafce72640e678e651db36145b9c6"
+ integrity sha512-GCvB3aoys96IuDFBMcTB46JOR6mdMtAToqwiW8JlWhsoh1mhHi/xn9ss/Dg7N555GiJyEt2qzoG/NHCwM6h1EA==
-tinyspy@^2.2.0:
- version "2.2.1"
- resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.1.tgz#117b2342f1f38a0dbdcc73a50a454883adf861d1"
- integrity sha512-KYad6Vy5VDWV4GH3fjpseMQ/XU2BhIYP7Vzd0LG44qRWm/Yt2WCOTicFdvmgo6gWaqooMQCawTtILVQJupKu7A==
+tinyglobby@^0.2.15, tinyglobby@^0.2.17:
+ version "0.2.17"
+ resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.17.tgz#562a9a6c9eb2b3b123d39719f9af5bb44fcd7631"
+ integrity sha512-wXR/dYpcqKmfWpEdZjiKJOwCNFndD0DMnrW/cYjVGttEkBfVgcLFHoNrlj47mjOVic9yyNu65alsgF4NQyTa2g==
+ dependencies:
+ fdir "^6.5.0"
+ picomatch "^4.0.4"
-to-fast-properties@^2.0.0:
- version "2.0.0"
- resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e"
- integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==
+tinyrainbow@^3.1.0:
+ version "3.2.0"
+ resolved "https://registry.yarnpkg.com/tinyrainbow/-/tinyrainbow-3.2.0.tgz#f62df4fda24415b353c08b9c38934b4b13877655"
+ integrity sha512-LgO3D9yZJjApUiuUfl9iFAwrtaX4+lok3wJIqttGoKCHlWUqHqbQpnxCf82L8FjgKsh4iGo78hqJwgL8F6To2A==
tough-cookie@^4.1.4:
version "4.1.4"
@@ -1880,21 +1575,11 @@ ts-node@^10.9.1:
v8-compile-cache-lib "^3.0.1"
yn "3.1.1"
-type-detect@^4.0.0, type-detect@^4.0.8:
- version "4.0.8"
- resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
- integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==
-
typescript@^4.8.3:
version "4.9.5"
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.5.tgz#095979f9bcc0d09da324d58d03ce8f8374cbe65a"
integrity sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==
-ufo@^1.5.3:
- version "1.5.3"
- resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.5.3.tgz#3325bd3c977b6c6cd3160bf4ff52989adc9d3344"
- integrity sha512-Y7HYmWaFwPUmkoQCUIAYpKqkOf+SbVj/2fJJZ4RJMCfZp0rTGwRbzQD+HghfnhKOjL9E01okqz+ncJskGYfBNw==
-
universalify@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/universalify/-/universalify-0.2.0.tgz#6451760566fa857534745ab1dde952d1b1761be0"
@@ -1913,53 +1598,44 @@ v8-compile-cache-lib@^3.0.1:
resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
-vite-node@1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.6.0.tgz#2c7e61129bfecc759478fa592754fd9704aaba7f"
- integrity sha512-de6HJgzC+TFzOu0NTC4RAIsyf/DY/ibWDYQUcuEA84EMHhcefTUGkjFHKKEJhQN4A+6I0u++kr3l36ZF2d7XRw==
- dependencies:
- cac "^6.7.14"
- debug "^4.3.4"
- pathe "^1.1.1"
- picocolors "^1.0.0"
- vite "^5.0.0"
-
-vite@^5.0.0:
- version "5.2.12"
- resolved "https://registry.yarnpkg.com/vite/-/vite-5.2.12.tgz#3536c93c58ba18edea4915a2ac573e6537409d97"
- integrity sha512-/gC8GxzxMK5ntBwb48pR32GGhENnjtY30G4A0jemunsBkiEZFw60s8InGpN8gkhHEkjnRK1aSAxeQgwvFhUHAA==
+"vite@^6.0.0 || ^7.0.0 || ^8.0.0":
+ version "8.3.4"
+ resolved "https://registry.yarnpkg.com/vite/-/vite-8.3.4.tgz#ba08678ba41ba53f41c251b1772946c27b1c874e"
+ integrity sha512-IftLE8phJhdNRIGNEV4JCCvfNScoZQVfcXaN8TQropWGJtOHcu+iAB9pHcuGvmEb/kddw0LBe/jS8ztdC6xdiQ==
dependencies:
- esbuild "^0.20.1"
- postcss "^8.4.38"
- rollup "^4.13.0"
+ lightningcss "^1.33.0"
+ picomatch "^4.0.7"
+ postcss "^8.5.29"
+ rolldown "~1.2.12"
+ tinyglobby "^0.2.17"
optionalDependencies:
fsevents "~2.3.3"
-vitest@^1.6.0:
- version "1.6.0"
- resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.6.0.tgz#9d5ad4752a3c451be919e412c597126cffb9892f"
- integrity sha512-H5r/dN06swuFnzNFhq/dnz37bPXnq8xB2xB5JOVk8K09rUtoeNN+LHWkoQ0A/i3hvbUKKcCei9KpbxqHMLhLLA==
- dependencies:
- "@vitest/expect" "1.6.0"
- "@vitest/runner" "1.6.0"
- "@vitest/snapshot" "1.6.0"
- "@vitest/spy" "1.6.0"
- "@vitest/utils" "1.6.0"
- acorn-walk "^8.3.2"
- chai "^4.3.10"
- debug "^4.3.4"
- execa "^8.0.1"
- local-pkg "^0.5.0"
- magic-string "^0.30.5"
- pathe "^1.1.1"
- picocolors "^1.0.0"
- std-env "^3.5.0"
- strip-literal "^2.0.0"
- tinybench "^2.5.1"
- tinypool "^0.8.3"
- vite "^5.0.0"
- vite-node "1.6.0"
- why-is-node-running "^2.2.2"
+vitest@^4.0.18:
+ version "4.1.12"
+ resolved "https://registry.yarnpkg.com/vitest/-/vitest-4.1.12.tgz#b372587e9c000f165f1757793178ea6b5631f82e"
+ integrity sha512-5eWdz2yb3ajxWF3C8C4TjkXl7FGm3n2E/VlazALrQHzK7nYMSGFnCZto0bbPNl77AwkOZVLk0YnBAejUu0NiWA==
+ dependencies:
+ "@vitest/expect" "4.1.12"
+ "@vitest/mocker" "4.1.12"
+ "@vitest/pretty-format" "4.1.12"
+ "@vitest/runner" "4.1.12"
+ "@vitest/snapshot" "4.1.12"
+ "@vitest/spy" "4.1.12"
+ "@vitest/utils" "4.1.12"
+ es-module-lexer "^2.0.0"
+ expect-type "^1.3.0"
+ magic-string "^0.30.21"
+ obug "^2.1.1"
+ pathe "^2.0.3"
+ picomatch "^4.0.3"
+ std-env "^4.0.0-rc.1"
+ tinybench "^2.9.0"
+ tinyexec "^1.0.2"
+ tinyglobby "^0.2.15"
+ tinyrainbow "^3.1.0"
+ vite "^6.0.0 || ^7.0.0 || ^8.0.0"
+ why-is-node-running "^2.3.0"
w3c-xmlserializer@^5.0.0:
version "5.0.0"
@@ -2038,26 +1714,14 @@ which-typed-array@^1.1.13:
gopd "^1.0.1"
has-tostringtag "^1.0.2"
-which@^2.0.1:
- version "2.0.2"
- resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1"
- integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==
- dependencies:
- isexe "^2.0.0"
-
-why-is-node-running@^2.2.2:
- version "2.2.2"
- resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.2.2.tgz#4185b2b4699117819e7154594271e7e344c9973e"
- integrity sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==
+why-is-node-running@^2.3.0:
+ version "2.3.0"
+ resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.3.0.tgz#a3f69a97107f494b3cdc3bdddd883a7d65cebf04"
+ integrity sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==
dependencies:
siginfo "^2.0.0"
stackback "0.0.2"
-wrappy@1:
- version "1.0.2"
- resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f"
- integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==
-
ws@^8.17.0:
version "8.17.0"
resolved "https://registry.yarnpkg.com/ws/-/ws-8.17.0.tgz#d145d18eca2ed25aaf791a183903f7be5e295fea"
@@ -2077,8 +1741,3 @@ yn@3.1.1:
version "3.1.1"
resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
-
-yocto-queue@^1.0.0:
- version "1.0.0"
- resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251"
- integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==