@solvapay/react-supabase 1.0.8-preview.1 → 1.0.8-preview.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -40
- package/dist/index.cjs +27 -12
- package/dist/index.d.cts +73 -9
- package/dist/index.d.ts +73 -9
- package/dist/index.js +27 -12
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -14,69 +14,49 @@ yarn add @solvapay/react-supabase @supabase/supabase-js
|
|
|
14
14
|
|
|
15
15
|
## Usage
|
|
16
16
|
|
|
17
|
-
|
|
17
|
+
Pass your existing Supabase client to `createSupabaseAuthAdapter`:
|
|
18
18
|
|
|
19
19
|
```tsx
|
|
20
|
+
import { createClient } from '@supabase/supabase-js'
|
|
20
21
|
import { SolvaPayProvider } from '@solvapay/react'
|
|
21
22
|
import { createSupabaseAuthAdapter } from '@solvapay/react-supabase'
|
|
22
23
|
|
|
23
|
-
const
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
24
|
+
const supabase = createClient(
|
|
25
|
+
process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
26
|
+
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
27
|
+
)
|
|
28
|
+
|
|
29
|
+
const adapter = createSupabaseAuthAdapter({ client: supabase })
|
|
27
30
|
|
|
28
31
|
export default function RootLayout({ children }) {
|
|
29
32
|
return <SolvaPayProvider config={{ auth: { adapter } }}>{children}</SolvaPayProvider>
|
|
30
33
|
}
|
|
31
34
|
```
|
|
32
35
|
|
|
36
|
+
Reusing the host app's client avoids spawning a second `GoTrue` instance and is the only reliable form with `@supabase/ssr`, custom `auth.storageKey`, or `persistSession: false`.
|
|
37
|
+
|
|
33
38
|
## API
|
|
34
39
|
|
|
35
40
|
### `createSupabaseAuthAdapter(config)`
|
|
36
41
|
|
|
37
|
-
Creates a Supabase auth adapter instance.
|
|
42
|
+
Creates a Supabase auth adapter instance. Accepts one of two config shapes:
|
|
38
43
|
|
|
39
|
-
|
|
44
|
+
**`{ client }`** (recommended)
|
|
40
45
|
|
|
41
|
-
- `config.
|
|
42
|
-
- `config.supabaseAnonKey` (string, required) - Your Supabase anonymous/public key
|
|
46
|
+
- `config.client` (`SupabaseClient`, required) - Your existing Supabase client.
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
## How It Works
|
|
48
|
+
**`{ supabaseUrl, supabaseAnonKey }`** (deprecated)
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
- `config.supabaseUrl` (string) - Your Supabase project URL.
|
|
51
|
+
- `config.supabaseAnonKey` (string) - Your Supabase anonymous/public key.
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
2. Gets the current session using `supabase.auth.getSession()`
|
|
52
|
-
3. Extracts the access token and user ID from the session
|
|
53
|
-
4. Returns `null` if no session is available (unauthenticated)
|
|
53
|
+
The URL/key form dynamically imports `@supabase/supabase-js` and creates a second client. It emits a one-time `console.warn` recommending migration to the `{ client }` form.
|
|
54
54
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
## Example: Full Setup
|
|
58
|
-
|
|
59
|
-
```tsx
|
|
60
|
-
'use client'
|
|
55
|
+
**Returns:** `AuthAdapter` instance.
|
|
61
56
|
|
|
62
|
-
|
|
63
|
-
import { createSupabaseAuthAdapter } from '@solvapay/react-supabase'
|
|
57
|
+
## How It Works
|
|
64
58
|
|
|
65
|
-
|
|
66
|
-
const adapter = createSupabaseAuthAdapter({
|
|
67
|
-
supabaseUrl: process.env.NEXT_PUBLIC_SUPABASE_URL!,
|
|
68
|
-
supabaseAnonKey: process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
|
|
69
|
-
})
|
|
70
|
-
|
|
71
|
-
return (
|
|
72
|
-
<html>
|
|
73
|
-
<body>
|
|
74
|
-
<SolvaPayProvider config={{ auth: { adapter } }}>{children}</SolvaPayProvider>
|
|
75
|
-
</body>
|
|
76
|
-
</html>
|
|
77
|
-
)
|
|
78
|
-
}
|
|
79
|
-
```
|
|
59
|
+
The adapter calls `supabase.auth.getSession()` and returns the access token + user ID. Returns `null` when there is no active session. Never throws.
|
|
80
60
|
|
|
81
61
|
## Custom Adapters
|
|
82
62
|
|
package/dist/index.cjs
CHANGED
|
@@ -35,23 +35,35 @@ __export(index_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(index_exports);
|
|
36
36
|
|
|
37
37
|
// src/supabase-adapter.ts
|
|
38
|
+
var urlKeyDeprecationWarned = false;
|
|
39
|
+
function isClientConfig(config) {
|
|
40
|
+
return "client" in config && config.client !== void 0 && config.client !== null;
|
|
41
|
+
}
|
|
38
42
|
function createSupabaseAuthAdapter(config) {
|
|
39
|
-
if (
|
|
40
|
-
|
|
43
|
+
if (isClientConfig(config)) {
|
|
44
|
+
return adapterFromClient(() => Promise.resolve(config.client));
|
|
45
|
+
}
|
|
46
|
+
const { supabaseUrl, supabaseAnonKey } = config;
|
|
47
|
+
if (!supabaseUrl || !supabaseAnonKey) {
|
|
48
|
+
throw new Error(
|
|
49
|
+
"createSupabaseAuthAdapter: pass { client } with your existing Supabase client, or { supabaseUrl, supabaseAnonKey } to have the adapter create one."
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
if (!urlKeyDeprecationWarned) {
|
|
53
|
+
urlKeyDeprecationWarned = true;
|
|
54
|
+
console.warn(
|
|
55
|
+
"[SupabaseAuthAdapter] The { supabaseUrl, supabaseAnonKey } form is deprecated and creates a second GoTrueClient that can miss sessions with @supabase/ssr or custom auth.storageKey. Pass { client: yourExistingSupabaseClient } instead."
|
|
56
|
+
);
|
|
41
57
|
}
|
|
42
58
|
let supabaseClient = null;
|
|
43
59
|
let clientPromise = null;
|
|
44
|
-
const
|
|
45
|
-
if (supabaseClient)
|
|
46
|
-
|
|
47
|
-
}
|
|
48
|
-
if (clientPromise) {
|
|
49
|
-
return clientPromise;
|
|
50
|
-
}
|
|
60
|
+
const getClient = () => {
|
|
61
|
+
if (supabaseClient) return Promise.resolve(supabaseClient);
|
|
62
|
+
if (clientPromise) return clientPromise;
|
|
51
63
|
clientPromise = (async () => {
|
|
52
64
|
try {
|
|
53
65
|
const { createClient } = await import("@supabase/supabase-js");
|
|
54
|
-
const client = createClient(
|
|
66
|
+
const client = createClient(supabaseUrl, supabaseAnonKey);
|
|
55
67
|
supabaseClient = client;
|
|
56
68
|
return client;
|
|
57
69
|
} catch {
|
|
@@ -63,11 +75,14 @@ function createSupabaseAuthAdapter(config) {
|
|
|
63
75
|
})();
|
|
64
76
|
return clientPromise;
|
|
65
77
|
};
|
|
78
|
+
return adapterFromClient(getClient);
|
|
79
|
+
}
|
|
80
|
+
function adapterFromClient(getClient) {
|
|
66
81
|
return {
|
|
67
82
|
async getToken() {
|
|
68
83
|
if (typeof window === "undefined") return null;
|
|
69
84
|
try {
|
|
70
|
-
const supabase = await
|
|
85
|
+
const supabase = await getClient();
|
|
71
86
|
const {
|
|
72
87
|
data: { session }
|
|
73
88
|
} = await supabase.auth.getSession();
|
|
@@ -80,7 +95,7 @@ function createSupabaseAuthAdapter(config) {
|
|
|
80
95
|
async getUserId() {
|
|
81
96
|
if (typeof window === "undefined") return null;
|
|
82
97
|
try {
|
|
83
|
-
const supabase = await
|
|
98
|
+
const supabase = await getClient();
|
|
84
99
|
const {
|
|
85
100
|
data: { session }
|
|
86
101
|
} = await supabase.auth.getSession();
|
package/dist/index.d.cts
CHANGED
|
@@ -7,16 +7,80 @@ import { AuthAdapter } from '@solvapay/react';
|
|
|
7
7
|
* This adapter integrates with Supabase Auth to get tokens and user IDs.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Structural shape of a Supabase client as used by the adapter.
|
|
12
|
+
*
|
|
13
|
+
* Matches `SupabaseClient` from `@supabase/supabase-js` without importing
|
|
14
|
+
* the type, so consumers pass the real client without a cast and this
|
|
15
|
+
* package stays dependency-light.
|
|
16
|
+
*/
|
|
17
|
+
type SupabaseClientLike = {
|
|
18
|
+
auth: {
|
|
19
|
+
getSession: () => Promise<{
|
|
20
|
+
data: {
|
|
21
|
+
session: {
|
|
22
|
+
access_token?: string;
|
|
23
|
+
user?: {
|
|
24
|
+
id?: string;
|
|
25
|
+
};
|
|
26
|
+
} | null;
|
|
27
|
+
};
|
|
28
|
+
}>;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Configuration for `createSupabaseAuthAdapter`.
|
|
33
|
+
*
|
|
34
|
+
* Prefer the `{ client }` form: pass your app's existing Supabase client so
|
|
35
|
+
* only one `GoTrue` instance is ever in the page. The URL/key form is kept
|
|
36
|
+
* for backwards compatibility but creates a second client that can miss
|
|
37
|
+
* sessions when the host app uses custom storage keys, `@supabase/ssr`, or
|
|
38
|
+
* iframe-isolated storage.
|
|
39
|
+
*/
|
|
40
|
+
type SupabaseAuthAdapterConfig = {
|
|
41
|
+
/** The host app's existing Supabase client. Recommended. */
|
|
42
|
+
client: SupabaseClientLike;
|
|
43
|
+
} | {
|
|
44
|
+
/** @deprecated Prefer `{ client }` — pass your existing Supabase client instead. */
|
|
14
45
|
supabaseUrl: string;
|
|
15
|
-
/**
|
|
16
|
-
* Supabase anonymous/public key
|
|
17
|
-
*/
|
|
46
|
+
/** @deprecated Prefer `{ client }` — pass your existing Supabase client instead. */
|
|
18
47
|
supabaseAnonKey: string;
|
|
19
|
-
}
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Create a Supabase authentication adapter for SolvaPayProvider.
|
|
51
|
+
*
|
|
52
|
+
* Two configuration forms are supported:
|
|
53
|
+
*
|
|
54
|
+
* 1. **`{ client }` (recommended)** — reuse the host app's existing Supabase
|
|
55
|
+
* client. No dynamic import, no second `GoTrue` instance, works with
|
|
56
|
+
* `@supabase/ssr` and custom storage configurations.
|
|
57
|
+
* 2. **`{ supabaseUrl, supabaseAnonKey }` (deprecated)** — the adapter
|
|
58
|
+
* dynamically imports `@supabase/supabase-js` and creates its own client.
|
|
59
|
+
* Emits a one-time `console.warn` recommending migration to `{ client }`.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* // Recommended: reuse the host app's client
|
|
64
|
+
* import { createClient } from '@supabase/supabase-js'
|
|
65
|
+
* import { createSupabaseAuthAdapter } from '@solvapay/react-supabase'
|
|
66
|
+
* import { SolvaPayProvider } from '@solvapay/react'
|
|
67
|
+
*
|
|
68
|
+
* const supabase = createClient(url, anonKey)
|
|
69
|
+
* const adapter = createSupabaseAuthAdapter({ client: supabase })
|
|
70
|
+
*
|
|
71
|
+
* export function App() {
|
|
72
|
+
* return (
|
|
73
|
+
* <SolvaPayProvider config={{ auth: { adapter } }}>
|
|
74
|
+
* <YourApp />
|
|
75
|
+
* </SolvaPayProvider>
|
|
76
|
+
* )
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @see SolvaPayProvider (from `@solvapay/react`) for using the adapter
|
|
81
|
+
* @see {@link AuthAdapter} for the adapter interface
|
|
82
|
+
* @since 1.0.0
|
|
83
|
+
*/
|
|
20
84
|
declare function createSupabaseAuthAdapter(config: SupabaseAuthAdapterConfig): AuthAdapter;
|
|
21
85
|
|
|
22
|
-
export { type SupabaseAuthAdapterConfig, createSupabaseAuthAdapter };
|
|
86
|
+
export { type SupabaseAuthAdapterConfig, type SupabaseClientLike, createSupabaseAuthAdapter };
|
package/dist/index.d.ts
CHANGED
|
@@ -7,16 +7,80 @@ import { AuthAdapter } from '@solvapay/react';
|
|
|
7
7
|
* This adapter integrates with Supabase Auth to get tokens and user IDs.
|
|
8
8
|
*/
|
|
9
9
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Structural shape of a Supabase client as used by the adapter.
|
|
12
|
+
*
|
|
13
|
+
* Matches `SupabaseClient` from `@supabase/supabase-js` without importing
|
|
14
|
+
* the type, so consumers pass the real client without a cast and this
|
|
15
|
+
* package stays dependency-light.
|
|
16
|
+
*/
|
|
17
|
+
type SupabaseClientLike = {
|
|
18
|
+
auth: {
|
|
19
|
+
getSession: () => Promise<{
|
|
20
|
+
data: {
|
|
21
|
+
session: {
|
|
22
|
+
access_token?: string;
|
|
23
|
+
user?: {
|
|
24
|
+
id?: string;
|
|
25
|
+
};
|
|
26
|
+
} | null;
|
|
27
|
+
};
|
|
28
|
+
}>;
|
|
29
|
+
};
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* Configuration for `createSupabaseAuthAdapter`.
|
|
33
|
+
*
|
|
34
|
+
* Prefer the `{ client }` form: pass your app's existing Supabase client so
|
|
35
|
+
* only one `GoTrue` instance is ever in the page. The URL/key form is kept
|
|
36
|
+
* for backwards compatibility but creates a second client that can miss
|
|
37
|
+
* sessions when the host app uses custom storage keys, `@supabase/ssr`, or
|
|
38
|
+
* iframe-isolated storage.
|
|
39
|
+
*/
|
|
40
|
+
type SupabaseAuthAdapterConfig = {
|
|
41
|
+
/** The host app's existing Supabase client. Recommended. */
|
|
42
|
+
client: SupabaseClientLike;
|
|
43
|
+
} | {
|
|
44
|
+
/** @deprecated Prefer `{ client }` — pass your existing Supabase client instead. */
|
|
14
45
|
supabaseUrl: string;
|
|
15
|
-
/**
|
|
16
|
-
* Supabase anonymous/public key
|
|
17
|
-
*/
|
|
46
|
+
/** @deprecated Prefer `{ client }` — pass your existing Supabase client instead. */
|
|
18
47
|
supabaseAnonKey: string;
|
|
19
|
-
}
|
|
48
|
+
};
|
|
49
|
+
/**
|
|
50
|
+
* Create a Supabase authentication adapter for SolvaPayProvider.
|
|
51
|
+
*
|
|
52
|
+
* Two configuration forms are supported:
|
|
53
|
+
*
|
|
54
|
+
* 1. **`{ client }` (recommended)** — reuse the host app's existing Supabase
|
|
55
|
+
* client. No dynamic import, no second `GoTrue` instance, works with
|
|
56
|
+
* `@supabase/ssr` and custom storage configurations.
|
|
57
|
+
* 2. **`{ supabaseUrl, supabaseAnonKey }` (deprecated)** — the adapter
|
|
58
|
+
* dynamically imports `@supabase/supabase-js` and creates its own client.
|
|
59
|
+
* Emits a one-time `console.warn` recommending migration to `{ client }`.
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```tsx
|
|
63
|
+
* // Recommended: reuse the host app's client
|
|
64
|
+
* import { createClient } from '@supabase/supabase-js'
|
|
65
|
+
* import { createSupabaseAuthAdapter } from '@solvapay/react-supabase'
|
|
66
|
+
* import { SolvaPayProvider } from '@solvapay/react'
|
|
67
|
+
*
|
|
68
|
+
* const supabase = createClient(url, anonKey)
|
|
69
|
+
* const adapter = createSupabaseAuthAdapter({ client: supabase })
|
|
70
|
+
*
|
|
71
|
+
* export function App() {
|
|
72
|
+
* return (
|
|
73
|
+
* <SolvaPayProvider config={{ auth: { adapter } }}>
|
|
74
|
+
* <YourApp />
|
|
75
|
+
* </SolvaPayProvider>
|
|
76
|
+
* )
|
|
77
|
+
* }
|
|
78
|
+
* ```
|
|
79
|
+
*
|
|
80
|
+
* @see SolvaPayProvider (from `@solvapay/react`) for using the adapter
|
|
81
|
+
* @see {@link AuthAdapter} for the adapter interface
|
|
82
|
+
* @since 1.0.0
|
|
83
|
+
*/
|
|
20
84
|
declare function createSupabaseAuthAdapter(config: SupabaseAuthAdapterConfig): AuthAdapter;
|
|
21
85
|
|
|
22
|
-
export { type SupabaseAuthAdapterConfig, createSupabaseAuthAdapter };
|
|
86
|
+
export { type SupabaseAuthAdapterConfig, type SupabaseClientLike, createSupabaseAuthAdapter };
|
package/dist/index.js
CHANGED
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
// src/supabase-adapter.ts
|
|
2
|
+
var urlKeyDeprecationWarned = false;
|
|
3
|
+
function isClientConfig(config) {
|
|
4
|
+
return "client" in config && config.client !== void 0 && config.client !== null;
|
|
5
|
+
}
|
|
2
6
|
function createSupabaseAuthAdapter(config) {
|
|
3
|
-
if (
|
|
4
|
-
|
|
7
|
+
if (isClientConfig(config)) {
|
|
8
|
+
return adapterFromClient(() => Promise.resolve(config.client));
|
|
9
|
+
}
|
|
10
|
+
const { supabaseUrl, supabaseAnonKey } = config;
|
|
11
|
+
if (!supabaseUrl || !supabaseAnonKey) {
|
|
12
|
+
throw new Error(
|
|
13
|
+
"createSupabaseAuthAdapter: pass { client } with your existing Supabase client, or { supabaseUrl, supabaseAnonKey } to have the adapter create one."
|
|
14
|
+
);
|
|
15
|
+
}
|
|
16
|
+
if (!urlKeyDeprecationWarned) {
|
|
17
|
+
urlKeyDeprecationWarned = true;
|
|
18
|
+
console.warn(
|
|
19
|
+
"[SupabaseAuthAdapter] The { supabaseUrl, supabaseAnonKey } form is deprecated and creates a second GoTrueClient that can miss sessions with @supabase/ssr or custom auth.storageKey. Pass { client: yourExistingSupabaseClient } instead."
|
|
20
|
+
);
|
|
5
21
|
}
|
|
6
22
|
let supabaseClient = null;
|
|
7
23
|
let clientPromise = null;
|
|
8
|
-
const
|
|
9
|
-
if (supabaseClient)
|
|
10
|
-
|
|
11
|
-
}
|
|
12
|
-
if (clientPromise) {
|
|
13
|
-
return clientPromise;
|
|
14
|
-
}
|
|
24
|
+
const getClient = () => {
|
|
25
|
+
if (supabaseClient) return Promise.resolve(supabaseClient);
|
|
26
|
+
if (clientPromise) return clientPromise;
|
|
15
27
|
clientPromise = (async () => {
|
|
16
28
|
try {
|
|
17
29
|
const { createClient } = await import("@supabase/supabase-js");
|
|
18
|
-
const client = createClient(
|
|
30
|
+
const client = createClient(supabaseUrl, supabaseAnonKey);
|
|
19
31
|
supabaseClient = client;
|
|
20
32
|
return client;
|
|
21
33
|
} catch {
|
|
@@ -27,11 +39,14 @@ function createSupabaseAuthAdapter(config) {
|
|
|
27
39
|
})();
|
|
28
40
|
return clientPromise;
|
|
29
41
|
};
|
|
42
|
+
return adapterFromClient(getClient);
|
|
43
|
+
}
|
|
44
|
+
function adapterFromClient(getClient) {
|
|
30
45
|
return {
|
|
31
46
|
async getToken() {
|
|
32
47
|
if (typeof window === "undefined") return null;
|
|
33
48
|
try {
|
|
34
|
-
const supabase = await
|
|
49
|
+
const supabase = await getClient();
|
|
35
50
|
const {
|
|
36
51
|
data: { session }
|
|
37
52
|
} = await supabase.auth.getSession();
|
|
@@ -44,7 +59,7 @@ function createSupabaseAuthAdapter(config) {
|
|
|
44
59
|
async getUserId() {
|
|
45
60
|
if (typeof window === "undefined") return null;
|
|
46
61
|
try {
|
|
47
|
-
const supabase = await
|
|
62
|
+
const supabase = await getClient();
|
|
48
63
|
const {
|
|
49
64
|
data: { session }
|
|
50
65
|
} = await supabase.auth.getSession();
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@solvapay/react-supabase",
|
|
3
|
-
"version": "1.0.8-preview.
|
|
3
|
+
"version": "1.0.8-preview.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.js",
|
|
@@ -18,20 +18,20 @@
|
|
|
18
18
|
"directory": "packages/react-supabase"
|
|
19
19
|
},
|
|
20
20
|
"peerDependencies": {
|
|
21
|
-
"@
|
|
22
|
-
"@
|
|
21
|
+
"@supabase/supabase-js": "^2.0.0",
|
|
22
|
+
"@solvapay/react": "^1.0.8-preview.11"
|
|
23
23
|
},
|
|
24
24
|
"devDependencies": {
|
|
25
25
|
"@types/react": "^19.2.14",
|
|
26
26
|
"tsup": "^8.5.1",
|
|
27
27
|
"typescript": "^5.9.3",
|
|
28
28
|
"vitest": "^4.1.2",
|
|
29
|
-
"@solvapay/react": "1.0.8-preview.
|
|
29
|
+
"@solvapay/react": "1.0.8-preview.11"
|
|
30
30
|
},
|
|
31
31
|
"scripts": {
|
|
32
32
|
"build": "tsup src/index.ts --format esm,cjs --dts --tsconfig tsconfig.build.json",
|
|
33
|
-
"test": "vitest run
|
|
34
|
-
"test:unit": "vitest run
|
|
33
|
+
"test": "vitest run",
|
|
34
|
+
"test:unit": "vitest run",
|
|
35
35
|
"test:watch": "vitest",
|
|
36
36
|
"lint": "eslint src --config ../../eslint.config.react.mjs",
|
|
37
37
|
"lint:fix": "eslint src --config ../../eslint.config.react.mjs --fix"
|