@redmix/auth-supabase-web 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +337 -0
- package/dist/cjs/index.d.ts +2 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +28 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/supabase.d.ts +162 -0
- package/dist/cjs/supabase.d.ts.map +1 -0
- package/dist/cjs/supabase.js +234 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +4 -0
- package/dist/supabase.d.ts +162 -0
- package/dist/supabase.d.ts.map +1 -0
- package/dist/supabase.js +213 -0
- package/package.json +73 -0
package/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
MIT License
|
2
|
+
|
3
|
+
Copyright (c) 2025 Redmix
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
@@ -0,0 +1,337 @@
|
|
1
|
+
# Supabase Authentication
|
2
|
+
|
3
|
+
To get started, run the setup command:
|
4
|
+
|
5
|
+
```bash
|
6
|
+
yarn rw setup auth supabase
|
7
|
+
```
|
8
|
+
|
9
|
+
This installs all the packages, writes all the files, and makes all the code modifications you need.
|
10
|
+
For a detailed explanation of all the api- and web-side changes that aren't exclusive to Supabase, see the top-level [Authentication](../authentication.md) doc. For now, let's focus on Supabase's side of things.
|
11
|
+
|
12
|
+
## Setup
|
13
|
+
|
14
|
+
If you don't have a Supabase account yet, now's the time to make one: navigate to https://supabase.com and click "Start your project" in the top right. Then sign up and create an organization and a project.
|
15
|
+
|
16
|
+
While Supabase creates your project, it thoughtfully shows your project's API keys.
|
17
|
+
(If the page refreshes while you're copying them over, just scroll down a bit and look for "Connecting to your new project".)
|
18
|
+
We're looking for "Project URL" and "API key" (the `anon`, `public` one).
|
19
|
+
Copy them into your project's `.env` file as `SUPABASE_URL` and `SUPABASE_KEY` respectively.
|
20
|
+
|
21
|
+
There's one more we need, the "JWT Secret", that's not here.
|
22
|
+
To get that one, click the cog icon ("Project Settings") near the bottom of the nav on the left.
|
23
|
+
Then click "API", scroll down a bit, and you should see it—"JWT Secret" under "JWT Settings".
|
24
|
+
Copy it into your project's `.env` file as `SUPABASE_JWT_SECRET`.
|
25
|
+
All together now:
|
26
|
+
|
27
|
+
```bash title=".env"
|
28
|
+
SUPABASE_URL="..."
|
29
|
+
SUPABASE_KEY="..."
|
30
|
+
SUPABASE_JWT_SECRET="..."
|
31
|
+
```
|
32
|
+
|
33
|
+
Lastly, in `redwood.toml`, include `SUPABASE_URL` and `SUPABASE_KEY` in the list of env vars that should be available to the web side:
|
34
|
+
|
35
|
+
```toml title="redwood.toml"
|
36
|
+
[web]
|
37
|
+
# ...
|
38
|
+
includeEnvironmentVariables = ["SUPABASE_URL", "SUPABASE_KEY"]
|
39
|
+
```
|
40
|
+
|
41
|
+
## Authentication UI
|
42
|
+
|
43
|
+
Supabase doesn't redirect to a hosted sign-up page or open a sign-up modal.
|
44
|
+
In a real app, you'd build a form here, but we're going to hardcode an email and password.
|
45
|
+
|
46
|
+
### Basic Example
|
47
|
+
|
48
|
+
After you sign up, head to your inbox: there should be a confirmation email from Supabase waiting for you.
|
49
|
+
|
50
|
+
Click the link, then head back to your app.
|
51
|
+
Once you refresh the page, you should see `{"isAuthenticated":true}` on the page.
|
52
|
+
|
53
|
+
Let's make sure: if this is a brand new project, generate a home page.
|
54
|
+
|
55
|
+
There we'll try to sign up by destructuring `signUp` from the `useAuth` hook (import that from `'src/auth'`). We'll also destructure and display `isAuthenticated` to see if it worked:
|
56
|
+
|
57
|
+
```tsx title="web/src/pages/HomePage.tsx"
|
58
|
+
import { useAuth } from 'src/auth'
|
59
|
+
|
60
|
+
const HomePage = () => {
|
61
|
+
const { isAuthenticated, signUp } = useAuth()
|
62
|
+
|
63
|
+
return (
|
64
|
+
<>
|
65
|
+
{/* MetaTags, h1, paragraphs, etc. */}
|
66
|
+
|
67
|
+
<p>{JSON.stringify({ isAuthenticated })}</p>
|
68
|
+
<button
|
69
|
+
onClick={() =>
|
70
|
+
signUp({
|
71
|
+
email: 'your.email@email.com',
|
72
|
+
password: 'super secret password',
|
73
|
+
})
|
74
|
+
}
|
75
|
+
>
|
76
|
+
sign up
|
77
|
+
</button>
|
78
|
+
</>
|
79
|
+
)
|
80
|
+
}
|
81
|
+
```
|
82
|
+
|
83
|
+
## Authentication Reference
|
84
|
+
|
85
|
+
You will notice that [Supabase Javascript SDK Auth API](https://supabase.com/docs/reference/javascript/auth-api) reference documentation presents methods to sign in with the various integrations Supabase supports: password, OAuth, IDToken, SSO, etc.
|
86
|
+
|
87
|
+
The RedwoodJS implementation of Supabase authentication supports these as well, but within the `logIn` method of the `useAuth` hook.
|
88
|
+
|
89
|
+
That means that you will see that Supabase documents sign in with email password as:
|
90
|
+
|
91
|
+
```ts
|
92
|
+
const { data, error } = await supabase.auth.signInWithPassword({
|
93
|
+
email: 'example@email.com',
|
94
|
+
password: 'example-password',
|
95
|
+
})
|
96
|
+
```
|
97
|
+
|
98
|
+
In RedwoodJS, you will always use `logIn` and pass the necessary credential options and also an `authenticationMethod` to declare how you want to authenticate.
|
99
|
+
|
100
|
+
```ts
|
101
|
+
const { logIn } = useAuth()
|
102
|
+
|
103
|
+
await logIn({
|
104
|
+
authenticationMethod: 'password',
|
105
|
+
email: 'example@email.com',
|
106
|
+
password: 'example-password',
|
107
|
+
})
|
108
|
+
```
|
109
|
+
|
110
|
+
### Sign Up with email and password
|
111
|
+
|
112
|
+
Creates a new user.
|
113
|
+
|
114
|
+
```ts
|
115
|
+
const { signUp } = useAuth()
|
116
|
+
|
117
|
+
await signUp({
|
118
|
+
email: 'example@email.com',
|
119
|
+
password: 'example-password',
|
120
|
+
})
|
121
|
+
```
|
122
|
+
|
123
|
+
### Sign Up with email and password and additional user metadata
|
124
|
+
|
125
|
+
Creates a new user with additional user metadata.
|
126
|
+
|
127
|
+
```ts
|
128
|
+
const { signUp } = useAuth()
|
129
|
+
|
130
|
+
await signUp({
|
131
|
+
email: 'example@email.com',
|
132
|
+
password: 'example-password',
|
133
|
+
options: {
|
134
|
+
data: {
|
135
|
+
first_name: 'John',
|
136
|
+
age: 27,
|
137
|
+
},
|
138
|
+
},
|
139
|
+
})
|
140
|
+
```
|
141
|
+
|
142
|
+
### Sign Up with email and password and a redirect URL
|
143
|
+
|
144
|
+
Creates a new user with a redirect URL.
|
145
|
+
|
146
|
+
```ts
|
147
|
+
const { signUp } = useAuth()
|
148
|
+
|
149
|
+
await signUp({
|
150
|
+
email: 'example@email.com',
|
151
|
+
password: 'example-password',
|
152
|
+
options: {
|
153
|
+
emailRedirectTo: 'https://example.com/welcome',
|
154
|
+
},
|
155
|
+
})
|
156
|
+
```
|
157
|
+
|
158
|
+
### Sign in a user with email and password
|
159
|
+
|
160
|
+
Log in an existing user with an email and password or phone and password.
|
161
|
+
|
162
|
+
- Requires either an email and password or a phone number and password.
|
163
|
+
|
164
|
+
```ts
|
165
|
+
const { logIn } = useAuth()
|
166
|
+
|
167
|
+
await logIn({
|
168
|
+
authenticationMethod: 'password',
|
169
|
+
email: 'example@email.com',
|
170
|
+
password: 'example-password',
|
171
|
+
})
|
172
|
+
```
|
173
|
+
|
174
|
+
### Sign in a user through Passwordless/OTP
|
175
|
+
|
176
|
+
Log in a user using magiclink or a one-time password (OTP).
|
177
|
+
|
178
|
+
- Requires either an email or phone number.
|
179
|
+
|
180
|
+
- This method is used for passwordless sign-ins where a OTP is sent to the user's email or phone number.
|
181
|
+
|
182
|
+
```ts
|
183
|
+
const { logIn } = useAuth()
|
184
|
+
|
185
|
+
await logIn({
|
186
|
+
authenticationMethod: 'otp',
|
187
|
+
email: 'example@email.com',
|
188
|
+
options: {
|
189
|
+
emailRedirectTo: 'https://example.com/welcome',
|
190
|
+
},
|
191
|
+
})
|
192
|
+
```
|
193
|
+
|
194
|
+
### Sign in a user through OAuth
|
195
|
+
|
196
|
+
Log in an existing user via a third-party provider.
|
197
|
+
|
198
|
+
- This method is used for signing in using a third-party provider.
|
199
|
+
|
200
|
+
- Supabase supports many different [third-party providers](https://supabase.com/docs/guides/auth#providers).
|
201
|
+
|
202
|
+
```ts
|
203
|
+
const { logIn } = useAuth()
|
204
|
+
|
205
|
+
await logIn({
|
206
|
+
authMethod: 'oauth',
|
207
|
+
provider: 'github',
|
208
|
+
})
|
209
|
+
```
|
210
|
+
|
211
|
+
### Sign in a user with IDToken
|
212
|
+
|
213
|
+
Log in a user using IDToken.
|
214
|
+
|
215
|
+
```ts
|
216
|
+
const { logIn } = useAuth()
|
217
|
+
|
218
|
+
await logIn({
|
219
|
+
authenticationMethod: 'id_token',
|
220
|
+
provider: 'apple',
|
221
|
+
token: 'cortland-apple-id-token',
|
222
|
+
})
|
223
|
+
```
|
224
|
+
|
225
|
+
### Sign in a user with SSO
|
226
|
+
|
227
|
+
Log in a user using IDToken.
|
228
|
+
|
229
|
+
```ts
|
230
|
+
const { logIn } = useAuth()
|
231
|
+
|
232
|
+
await logIn({
|
233
|
+
authenticationMethod: 'sso',
|
234
|
+
providerId: 'sso-provider-identity-uuid',
|
235
|
+
domain: 'example.com',
|
236
|
+
})
|
237
|
+
```
|
238
|
+
|
239
|
+
### Get Current User
|
240
|
+
|
241
|
+
Gets the content of the current user set by API side authentication.
|
242
|
+
|
243
|
+
```ts
|
244
|
+
const { currentUser } = useAuth()
|
245
|
+
|
246
|
+
<p>{JSON.stringify({ currentUser })}</p>
|
247
|
+
```
|
248
|
+
|
249
|
+
### Get Current User Metadata
|
250
|
+
|
251
|
+
Gets content of the current Supabase user session, i.e., `auth.getSession()`.
|
252
|
+
|
253
|
+
```ts
|
254
|
+
const { userMetadata } = useAuth()
|
255
|
+
|
256
|
+
<p>{JSON.stringify({ userMetadata })}</p>
|
257
|
+
```
|
258
|
+
|
259
|
+
### Sign out a user
|
260
|
+
|
261
|
+
Inside a browser context, signOut() will remove the logged in user from the browser session and log them out - removing all items from localStorage and then trigger a "SIGNED_OUT" event.
|
262
|
+
|
263
|
+
In order to use the signOut() method, the user needs to be signed in first.
|
264
|
+
|
265
|
+
```ts
|
266
|
+
const { logOut } = useAuth()
|
267
|
+
|
268
|
+
logOut()
|
269
|
+
```
|
270
|
+
|
271
|
+
### Verify and log in through OTP
|
272
|
+
|
273
|
+
Log in a user given a User supplied OTP received via mobile.
|
274
|
+
|
275
|
+
- The verifyOtp method takes in different verification types. If a phone number is used, the type can either be sms or phone_change. If an email address is used, the type can be one of the following: signup, magiclink, recovery, invite or email_change.
|
276
|
+
|
277
|
+
- The verification type used should be determined based on the corresponding auth method called before verifyOtp to sign up / sign-in a user.
|
278
|
+
|
279
|
+
The RedwoodJS auth provider doesn't expose the `veriftyOtp` method from the Supabase SDK directly.
|
280
|
+
|
281
|
+
Instead, since you always have access the the Supabase Auth client, you can access any method it exposes.
|
282
|
+
|
283
|
+
So, in order to use the `verifyOtp` method, you would:
|
284
|
+
|
285
|
+
```ts
|
286
|
+
const { client } = useAuth()
|
287
|
+
|
288
|
+
useEffect(() => {
|
289
|
+
const { data, error } = await client.verifyOtp({ phone, token, type: 'sms' })
|
290
|
+
}, [client])
|
291
|
+
```
|
292
|
+
|
293
|
+
### Access the Supabase Auth Client
|
294
|
+
|
295
|
+
Sometimes you may need to access the Supabase Auth client directly.
|
296
|
+
|
297
|
+
```ts
|
298
|
+
const { client } = useAuth()
|
299
|
+
```
|
300
|
+
|
301
|
+
You can then use it to work with Supabase sessions, or auth events.
|
302
|
+
|
303
|
+
When using in a React component, you'll have to put any method that needs an `await` in a `useEffect()`.
|
304
|
+
|
305
|
+
### Retrieve a session
|
306
|
+
|
307
|
+
Returns the session, refreshing it if necessary. The session returned can be null if the session is not detected which can happen in the event a user is not signed-in or has logged out.
|
308
|
+
|
309
|
+
```ts
|
310
|
+
const { client } = useAuth()
|
311
|
+
|
312
|
+
useEffect(() => {
|
313
|
+
const { data, error } = await client.getSession()
|
314
|
+
}, [client])
|
315
|
+
```
|
316
|
+
|
317
|
+
### Listen to auth events
|
318
|
+
|
319
|
+
Receive a notification every time an auth event happens.
|
320
|
+
|
321
|
+
- Types of auth events: `SIGNED_IN`, `SIGNED_OUT`, `TOKEN_REFRESHED`, `USER_UPDATED`, `PASSWORD_RECOVERY`
|
322
|
+
|
323
|
+
```ts
|
324
|
+
const { client } = useAuth()
|
325
|
+
|
326
|
+
useEffect(() => {
|
327
|
+
const {
|
328
|
+
data: { subscription },
|
329
|
+
} = client.onAuthStateChange((event, session) => {
|
330
|
+
console.log(event, session)
|
331
|
+
})
|
332
|
+
|
333
|
+
return () => {
|
334
|
+
subscription.unsubscribe()
|
335
|
+
}
|
336
|
+
}, [client])
|
337
|
+
```
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA"}
|
@@ -0,0 +1,28 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __defProp = Object.defineProperty;
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
6
|
+
var __export = (target, all) => {
|
7
|
+
for (var name in all)
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
9
|
+
};
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
12
|
+
for (let key of __getOwnPropNames(from))
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
15
|
+
}
|
16
|
+
return to;
|
17
|
+
};
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
19
|
+
var index_exports = {};
|
20
|
+
__export(index_exports, {
|
21
|
+
createAuth: () => import_supabase.createAuth
|
22
|
+
});
|
23
|
+
module.exports = __toCommonJS(index_exports);
|
24
|
+
var import_supabase = require("./supabase.js");
|
25
|
+
// Annotate the CommonJS export names for ESM import in node:
|
26
|
+
0 && (module.exports = {
|
27
|
+
createAuth
|
28
|
+
});
|
@@ -0,0 +1 @@
|
|
1
|
+
{"type":"commonjs"}
|
@@ -0,0 +1,162 @@
|
|
1
|
+
import type { SupabaseClient, AuthResponse, OAuthResponse, SSOResponse, SignInWithOAuthCredentials, SignInWithIdTokenCredentials, SignInWithPasswordCredentials, SignInWithPasswordlessCredentials, SignInWithSSO } from '@supabase/supabase-js';
|
2
|
+
import type { CurrentUser } from '@redmix/auth';
|
3
|
+
export type SignInWithOAuthOptions = SignInWithOAuthCredentials & {
|
4
|
+
authMethod: 'oauth';
|
5
|
+
};
|
6
|
+
export type SignInWithIdTokenOptions = SignInWithIdTokenCredentials & {
|
7
|
+
authMethod: 'id_token';
|
8
|
+
};
|
9
|
+
export type SignInWithPasswordOptions = SignInWithPasswordCredentials & {
|
10
|
+
authMethod: 'password';
|
11
|
+
};
|
12
|
+
export type SignInWithPasswordlessOptions = SignInWithPasswordlessCredentials & {
|
13
|
+
authMethod: 'otp';
|
14
|
+
};
|
15
|
+
export type SignInWithSSOOptions = SignInWithSSO & {
|
16
|
+
authMethod: 'sso';
|
17
|
+
};
|
18
|
+
export declare function createAuth(supabaseClient: SupabaseClient, customProviderHooks?: {
|
19
|
+
useCurrentUser?: () => Promise<CurrentUser>;
|
20
|
+
useHasRole?: (currentUser: CurrentUser | null) => (rolesToCheck: string | string[]) => boolean;
|
21
|
+
}): {
|
22
|
+
AuthContext: import("react").Context<import("@redmix/auth").AuthContextInterface<import("@supabase/supabase-js").UserMetadata, SignInWithOAuthOptions | SignInWithIdTokenOptions | ({
|
23
|
+
email: string;
|
24
|
+
password: string;
|
25
|
+
options?: {
|
26
|
+
captchaToken?: string;
|
27
|
+
};
|
28
|
+
} & {
|
29
|
+
authMethod: "password";
|
30
|
+
}) | ({
|
31
|
+
phone: string;
|
32
|
+
password: string;
|
33
|
+
options?: {
|
34
|
+
captchaToken?: string;
|
35
|
+
};
|
36
|
+
} & {
|
37
|
+
authMethod: "password";
|
38
|
+
}) | ({
|
39
|
+
email: string;
|
40
|
+
options?: {
|
41
|
+
emailRedirectTo?: string;
|
42
|
+
shouldCreateUser?: boolean;
|
43
|
+
data?: object;
|
44
|
+
captchaToken?: string;
|
45
|
+
};
|
46
|
+
} & {
|
47
|
+
authMethod: "otp";
|
48
|
+
}) | ({
|
49
|
+
phone: string;
|
50
|
+
options?: {
|
51
|
+
shouldCreateUser?: boolean;
|
52
|
+
data?: object;
|
53
|
+
captchaToken?: string;
|
54
|
+
channel?: "sms" | "whatsapp";
|
55
|
+
};
|
56
|
+
} & {
|
57
|
+
authMethod: "otp";
|
58
|
+
}) | ({
|
59
|
+
providerId: string;
|
60
|
+
options?: {
|
61
|
+
redirectTo?: string;
|
62
|
+
captchaToken?: string;
|
63
|
+
};
|
64
|
+
} & {
|
65
|
+
authMethod: "sso";
|
66
|
+
}) | ({
|
67
|
+
domain: string;
|
68
|
+
options?: {
|
69
|
+
redirectTo?: string;
|
70
|
+
captchaToken?: string;
|
71
|
+
};
|
72
|
+
} & {
|
73
|
+
authMethod: "sso";
|
74
|
+
}), AuthResponse | OAuthResponse | SSOResponse, unknown, void, {
|
75
|
+
email: string;
|
76
|
+
password: string;
|
77
|
+
options?: {
|
78
|
+
emailRedirectTo?: string;
|
79
|
+
data?: object;
|
80
|
+
captchaToken?: string;
|
81
|
+
};
|
82
|
+
} | {
|
83
|
+
phone: string;
|
84
|
+
password: string;
|
85
|
+
options?: {
|
86
|
+
data?: object;
|
87
|
+
captchaToken?: string;
|
88
|
+
channel?: "sms" | "whatsapp";
|
89
|
+
};
|
90
|
+
}, AuthResponse, unknown, unknown, unknown, unknown, SupabaseClient<any, "public", any>> | undefined>;
|
91
|
+
AuthProvider: ({ children }: import("@redmix/auth").AuthProviderProps) => import("react").JSX.Element;
|
92
|
+
useAuth: () => import("@redmix/auth").AuthContextInterface<import("@supabase/supabase-js").UserMetadata, SignInWithOAuthOptions | SignInWithIdTokenOptions | ({
|
93
|
+
email: string;
|
94
|
+
password: string;
|
95
|
+
options?: {
|
96
|
+
captchaToken?: string;
|
97
|
+
};
|
98
|
+
} & {
|
99
|
+
authMethod: "password";
|
100
|
+
}) | ({
|
101
|
+
phone: string;
|
102
|
+
password: string;
|
103
|
+
options?: {
|
104
|
+
captchaToken?: string;
|
105
|
+
};
|
106
|
+
} & {
|
107
|
+
authMethod: "password";
|
108
|
+
}) | ({
|
109
|
+
email: string;
|
110
|
+
options?: {
|
111
|
+
emailRedirectTo?: string;
|
112
|
+
shouldCreateUser?: boolean;
|
113
|
+
data?: object;
|
114
|
+
captchaToken?: string;
|
115
|
+
};
|
116
|
+
} & {
|
117
|
+
authMethod: "otp";
|
118
|
+
}) | ({
|
119
|
+
phone: string;
|
120
|
+
options?: {
|
121
|
+
shouldCreateUser?: boolean;
|
122
|
+
data?: object;
|
123
|
+
captchaToken?: string;
|
124
|
+
channel?: "sms" | "whatsapp";
|
125
|
+
};
|
126
|
+
} & {
|
127
|
+
authMethod: "otp";
|
128
|
+
}) | ({
|
129
|
+
providerId: string;
|
130
|
+
options?: {
|
131
|
+
redirectTo?: string;
|
132
|
+
captchaToken?: string;
|
133
|
+
};
|
134
|
+
} & {
|
135
|
+
authMethod: "sso";
|
136
|
+
}) | ({
|
137
|
+
domain: string;
|
138
|
+
options?: {
|
139
|
+
redirectTo?: string;
|
140
|
+
captchaToken?: string;
|
141
|
+
};
|
142
|
+
} & {
|
143
|
+
authMethod: "sso";
|
144
|
+
}), AuthResponse | OAuthResponse | SSOResponse, unknown, void, {
|
145
|
+
email: string;
|
146
|
+
password: string;
|
147
|
+
options?: {
|
148
|
+
emailRedirectTo?: string;
|
149
|
+
data?: object;
|
150
|
+
captchaToken?: string;
|
151
|
+
};
|
152
|
+
} | {
|
153
|
+
phone: string;
|
154
|
+
password: string;
|
155
|
+
options?: {
|
156
|
+
data?: object;
|
157
|
+
captchaToken?: string;
|
158
|
+
channel?: "sms" | "whatsapp";
|
159
|
+
};
|
160
|
+
}, AuthResponse, unknown, unknown, unknown, unknown, SupabaseClient<any, "public", any>>;
|
161
|
+
};
|
162
|
+
//# sourceMappingURL=supabase.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../../src/supabase.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,0BAA0B,EAC1B,4BAA4B,EAC5B,6BAA6B,EAC7B,iCAAiC,EACjC,aAAa,EAId,MAAM,uBAAuB,CAAA;AAG9B,OAAO,KAAK,EAAE,WAAW,EAAuB,MAAM,cAAc,CAAA;AAMpE,MAAM,MAAM,sBAAsB,GAAG,0BAA0B,GAAG;IAChE,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,4BAA4B,GAAG;IACpE,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG,6BAA6B,GAAG;IACtE,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,6BAA6B,GACvC,iCAAiC,GAAG;IAClC,UAAU,EAAE,KAAK,CAAA;CAClB,CAAA;AAEH,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG;IACjD,UAAU,EAAE,KAAK,CAAA;CAClB,CAAA;AAmBD,wBAAgB,UAAU,CACxB,cAAc,EAAE,cAAc,EAC9B,mBAAmB,CAAC,EAAE;IACpB,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAA;IAC3C,UAAU,CAAC,EAAE,CACX,WAAW,EAAE,WAAW,GAAG,IAAI,KAC5B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,OAAO,CAAA;CAClD;;;;;wBAyO65H,CAAC;;;oBA7Qn5H,UAAU;;;;;wBA6Q6oI,CAAC;;;oBA7QxpI,UAAU;;;;2BA6Qs3I,CAAC;4BAA4H,CAAC;gBAAoS,CAAC;wBAA0H,CAAC;;;oBAxQ55J,KAAK;;;;4BAwQumK,CAAC;gBAAoS,CAAC;wBAA0H,CAAC;mBAAwF,CAAC;;;oBAxQtmL,KAAK;;;;sBAwQitT,CAAC;wBAA0H,CAAC;;;oBApQp1T,KAAK;;;;sBAoQ+iU,CAAC;wBAA0H,CAAC;;;oBApQhrU,KAAK;;;;;2BAoQu/E,CAAC;gBAAmS,CAAC;wBAA0H,CAAC;;;;;;gBAA6a,CAAC;wBAA0K,CAAC;mBAAwF,CAAC;;;wCA/PvkH,cAEjB,+BAA+B,OAAO;;;;;wBA6Ps3H,CAAC;;;oBA7Qn5H,UAAU;;;;;wBA6Q6oI,CAAC;;;oBA7QxpI,UAAU;;;;2BA6Qs3I,CAAC;4BAA4H,CAAC;gBAAoS,CAAC;wBAA0H,CAAC;;;oBAxQ55J,KAAK;;;;4BAwQumK,CAAC;gBAAoS,CAAC;wBAA0H,CAAC;mBAAwF,CAAC;;;oBAxQtmL,KAAK;;;;sBAwQitT,CAAC;wBAA0H,CAAC;;;oBApQp1T,KAAK;;;;sBAoQ+iU,CAAC;wBAA0H,CAAC;;;oBApQhrU,KAAK;;;;;2BAoQu/E,CAAC;gBAAmS,CAAC;wBAA0H,CAAC;;;;;;gBAA6a,CAAC;wBAA0K,CAAC;mBAAwF,CAAC;;;EAhO3lH"}
|
@@ -0,0 +1,234 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __defProp = Object.defineProperty;
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
6
|
+
var __export = (target, all) => {
|
7
|
+
for (var name in all)
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
9
|
+
};
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
12
|
+
for (let key of __getOwnPropNames(from))
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
15
|
+
}
|
16
|
+
return to;
|
17
|
+
};
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
19
|
+
var supabase_exports = {};
|
20
|
+
__export(supabase_exports, {
|
21
|
+
createAuth: () => createAuth
|
22
|
+
});
|
23
|
+
module.exports = __toCommonJS(supabase_exports);
|
24
|
+
var import_ssr = require("@supabase/ssr");
|
25
|
+
var import_ssr2 = require("@supabase/ssr");
|
26
|
+
var import_supabase_js = require("@supabase/supabase-js");
|
27
|
+
var import_auth = require("@redmix/auth");
|
28
|
+
function createMiddlewareAuth(supabaseClient, customProviderHooks) {
|
29
|
+
const authImplementation = createAuthImplementation({
|
30
|
+
supabaseClient,
|
31
|
+
middleware: true
|
32
|
+
});
|
33
|
+
return (0, import_auth.createAuthentication)(authImplementation, {
|
34
|
+
...customProviderHooks,
|
35
|
+
useCurrentUser: customProviderHooks?.useCurrentUser ?? (() => (0, import_auth.getCurrentUserFromMiddleware)("/middleware/supabase"))
|
36
|
+
});
|
37
|
+
}
|
38
|
+
function createAuth(supabaseClient, customProviderHooks) {
|
39
|
+
if (RWJS_ENV.RWJS_EXP_STREAMING_SSR) {
|
40
|
+
return createMiddlewareAuth(supabaseClient, customProviderHooks);
|
41
|
+
}
|
42
|
+
const authImplementation = createAuthImplementation({ supabaseClient });
|
43
|
+
return (0, import_auth.createAuthentication)(authImplementation, customProviderHooks);
|
44
|
+
}
|
45
|
+
const setAuthProviderCookie = () => {
|
46
|
+
const authProviderCookieString = (0, import_ssr2.serialize)(
|
47
|
+
"auth-provider",
|
48
|
+
"supabase",
|
49
|
+
import_ssr.DEFAULT_COOKIE_OPTIONS
|
50
|
+
);
|
51
|
+
document.cookie = authProviderCookieString;
|
52
|
+
};
|
53
|
+
const expireAuthProviderCookie = () => {
|
54
|
+
const authProviderCookieString = (0, import_ssr2.serialize)("auth-provider", "supabase", {
|
55
|
+
...import_ssr.DEFAULT_COOKIE_OPTIONS,
|
56
|
+
maxAge: -1
|
57
|
+
});
|
58
|
+
document.cookie = authProviderCookieString;
|
59
|
+
};
|
60
|
+
function createAuthImplementation({
|
61
|
+
supabaseClient,
|
62
|
+
middleware = false
|
63
|
+
}) {
|
64
|
+
return {
|
65
|
+
type: "supabase",
|
66
|
+
client: supabaseClient,
|
67
|
+
/*
|
68
|
+
* All Supabase Sign In Authentication Methods
|
69
|
+
*/
|
70
|
+
login: async (credentials) => {
|
71
|
+
let result;
|
72
|
+
switch (credentials.authMethod) {
|
73
|
+
/**
|
74
|
+
* Log in an existing user with an email and password or phone and password.
|
75
|
+
*
|
76
|
+
* Be aware that you may get back an error message that will not distinguish
|
77
|
+
* between the cases where the account does not exist or that the
|
78
|
+
* email/phone and password combination is wrong or that the account can only
|
79
|
+
* be accessed via social login.
|
80
|
+
*/
|
81
|
+
case "password":
|
82
|
+
result = await supabaseClient.auth.signInWithPassword(credentials);
|
83
|
+
break;
|
84
|
+
/**
|
85
|
+
* Log in an existing user via a third-party provider.
|
86
|
+
*/
|
87
|
+
case "oauth":
|
88
|
+
result = await supabaseClient.auth.signInWithOAuth(credentials);
|
89
|
+
break;
|
90
|
+
/**
|
91
|
+
* Log in a user using magiclink or a one-time password (OTP).
|
92
|
+
*
|
93
|
+
* If the `{{ .ConfirmationURL }}` variable is specified in the email template, a magiclink will be sent.
|
94
|
+
* If the `{{ .Token }}` variable is specified in the email template, an OTP will be sent.
|
95
|
+
* If you're using phone sign-ins, only an OTP will be sent. You won't be able to send a magiclink for phone sign-ins.
|
96
|
+
*
|
97
|
+
* Be aware that you may get back an error message that will not distinguish
|
98
|
+
* between the cases where the account does not exist or, that the account
|
99
|
+
* can only be accessed via social login.
|
100
|
+
*/
|
101
|
+
case "otp":
|
102
|
+
result = await supabaseClient.auth.signInWithOtp(credentials);
|
103
|
+
break;
|
104
|
+
/**
|
105
|
+
* Attempts a single-sign on using an enterprise Identity Provider. A
|
106
|
+
* successful SSO attempt will redirect the current page to the identity
|
107
|
+
* provider authorization page. The redirect URL is implementation and SSO
|
108
|
+
* protocol specific.
|
109
|
+
*
|
110
|
+
* You can use it by providing a SSO domain. Typically you can extract this
|
111
|
+
* domain by asking users for their email address. If this domain is
|
112
|
+
* registered on the Auth instance the redirect will use that organization's
|
113
|
+
* currently active SSO Identity Provider for the login.
|
114
|
+
*
|
115
|
+
* If you have built an organization-specific login page, you can use the
|
116
|
+
* organization's SSO Identity Provider UUID directly instead.
|
117
|
+
*
|
118
|
+
* This API is experimental and availability is conditional on correct
|
119
|
+
* settings on the Auth service.
|
120
|
+
*
|
121
|
+
* @experimental
|
122
|
+
*/
|
123
|
+
case "sso":
|
124
|
+
result = await supabaseClient.auth.signInWithSSO(credentials);
|
125
|
+
break;
|
126
|
+
/**
|
127
|
+
* Allows signing in with an ID token issued by certain supported providers.
|
128
|
+
* The ID token is verified for validity and a new session is established.
|
129
|
+
*
|
130
|
+
* @experimental
|
131
|
+
*/
|
132
|
+
case "id_token":
|
133
|
+
result = await supabaseClient.auth.signInWithIdToken(credentials);
|
134
|
+
break;
|
135
|
+
default:
|
136
|
+
return {
|
137
|
+
data: { user: null, session: null },
|
138
|
+
error: new import_supabase_js.AuthError("Unsupported authentication method")
|
139
|
+
};
|
140
|
+
}
|
141
|
+
if (middleware) {
|
142
|
+
setAuthProviderCookie();
|
143
|
+
}
|
144
|
+
return result;
|
145
|
+
},
|
146
|
+
/**
|
147
|
+
* Inside a browser context, `signOut()` will remove the logged in user from the browser session
|
148
|
+
* and log them out - removing all items from localStorage and then trigger a `"SIGNED_OUT"` event.
|
149
|
+
*
|
150
|
+
* For server-side management, you can revoke all refresh tokens for a user by passing a user's JWT through to `auth.api.signOut(JWT: string)`.
|
151
|
+
* There is no way to revoke a user's access token jwt until it expires. It is recommended to set a shorter expiry on the jwt for this reason.
|
152
|
+
*/
|
153
|
+
logout: async () => {
|
154
|
+
const { error } = await supabaseClient.auth.signOut();
|
155
|
+
if (error) {
|
156
|
+
console.error(error);
|
157
|
+
}
|
158
|
+
if (middleware) {
|
159
|
+
expireAuthProviderCookie();
|
160
|
+
}
|
161
|
+
return;
|
162
|
+
},
|
163
|
+
/**
|
164
|
+
* Creates a new user.
|
165
|
+
*
|
166
|
+
* Be aware that if a user account exists in the system you may get back an
|
167
|
+
* error message that attempts to hide this information from the user.
|
168
|
+
*
|
169
|
+
* @returns A logged-in session if the server has "autoconfirm" ON
|
170
|
+
* @returns A user if the server has "autoconfirm" OFF
|
171
|
+
*/
|
172
|
+
signup: async (credentials) => {
|
173
|
+
const result = await supabaseClient.auth.signUp(credentials);
|
174
|
+
if (result.data?.session) {
|
175
|
+
setAuthProviderCookie();
|
176
|
+
}
|
177
|
+
return result;
|
178
|
+
},
|
179
|
+
getToken: async () => {
|
180
|
+
const { data, error } = await supabaseClient.auth.getSession();
|
181
|
+
if (error) {
|
182
|
+
console.error(error);
|
183
|
+
return null;
|
184
|
+
}
|
185
|
+
return data?.session?.access_token ?? null;
|
186
|
+
},
|
187
|
+
/**
|
188
|
+
* Gets the current user metadata if there is an existing session.
|
189
|
+
*/
|
190
|
+
getUserMetadata: async () => {
|
191
|
+
const { data, error } = await supabaseClient.auth.getSession();
|
192
|
+
if (error) {
|
193
|
+
console.error(error);
|
194
|
+
return null;
|
195
|
+
}
|
196
|
+
return data?.session?.user?.user_metadata ?? null;
|
197
|
+
},
|
198
|
+
/**
|
199
|
+
* Restore Redwood authentication state when an OAuth or magiclink
|
200
|
+
* callback redirects back to site with access token
|
201
|
+
* by restoring the Supabase auth session.
|
202
|
+
*
|
203
|
+
* Initializes the Supabase client session either from the url or from storage.
|
204
|
+
* This method is automatically called when instantiating the client, but should also be called
|
205
|
+
* manually when checking for an error from an auth redirect (oauth, magiclink, password recovery, etc).
|
206
|
+
*/
|
207
|
+
restoreAuthState: async () => {
|
208
|
+
try {
|
209
|
+
const { data } = await supabaseClient.auth.refreshSession();
|
210
|
+
if (middleware) {
|
211
|
+
if (data.session) {
|
212
|
+
setAuthProviderCookie();
|
213
|
+
} else {
|
214
|
+
expireAuthProviderCookie();
|
215
|
+
}
|
216
|
+
}
|
217
|
+
window.history.replaceState(
|
218
|
+
{},
|
219
|
+
document.title,
|
220
|
+
window.location.pathname
|
221
|
+
);
|
222
|
+
} catch (error) {
|
223
|
+
console.error(error);
|
224
|
+
}
|
225
|
+
return;
|
226
|
+
},
|
227
|
+
// This is important, so we can skip fetching getCurrentUser
|
228
|
+
useMiddlewareAuth: middleware
|
229
|
+
};
|
230
|
+
}
|
231
|
+
// Annotate the CommonJS export names for ESM import in node:
|
232
|
+
0 && (module.exports = {
|
233
|
+
createAuth
|
234
|
+
});
|
package/dist/index.d.ts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAA"}
|
package/dist/index.js
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
import type { SupabaseClient, AuthResponse, OAuthResponse, SSOResponse, SignInWithOAuthCredentials, SignInWithIdTokenCredentials, SignInWithPasswordCredentials, SignInWithPasswordlessCredentials, SignInWithSSO } from '@supabase/supabase-js';
|
2
|
+
import type { CurrentUser } from '@redmix/auth';
|
3
|
+
export type SignInWithOAuthOptions = SignInWithOAuthCredentials & {
|
4
|
+
authMethod: 'oauth';
|
5
|
+
};
|
6
|
+
export type SignInWithIdTokenOptions = SignInWithIdTokenCredentials & {
|
7
|
+
authMethod: 'id_token';
|
8
|
+
};
|
9
|
+
export type SignInWithPasswordOptions = SignInWithPasswordCredentials & {
|
10
|
+
authMethod: 'password';
|
11
|
+
};
|
12
|
+
export type SignInWithPasswordlessOptions = SignInWithPasswordlessCredentials & {
|
13
|
+
authMethod: 'otp';
|
14
|
+
};
|
15
|
+
export type SignInWithSSOOptions = SignInWithSSO & {
|
16
|
+
authMethod: 'sso';
|
17
|
+
};
|
18
|
+
export declare function createAuth(supabaseClient: SupabaseClient, customProviderHooks?: {
|
19
|
+
useCurrentUser?: () => Promise<CurrentUser>;
|
20
|
+
useHasRole?: (currentUser: CurrentUser | null) => (rolesToCheck: string | string[]) => boolean;
|
21
|
+
}): {
|
22
|
+
AuthContext: import("react").Context<import("@redmix/auth").AuthContextInterface<import("@supabase/supabase-js").UserMetadata, SignInWithOAuthOptions | SignInWithIdTokenOptions | ({
|
23
|
+
email: string;
|
24
|
+
password: string;
|
25
|
+
options?: {
|
26
|
+
captchaToken?: string;
|
27
|
+
};
|
28
|
+
} & {
|
29
|
+
authMethod: "password";
|
30
|
+
}) | ({
|
31
|
+
phone: string;
|
32
|
+
password: string;
|
33
|
+
options?: {
|
34
|
+
captchaToken?: string;
|
35
|
+
};
|
36
|
+
} & {
|
37
|
+
authMethod: "password";
|
38
|
+
}) | ({
|
39
|
+
email: string;
|
40
|
+
options?: {
|
41
|
+
emailRedirectTo?: string;
|
42
|
+
shouldCreateUser?: boolean;
|
43
|
+
data?: object;
|
44
|
+
captchaToken?: string;
|
45
|
+
};
|
46
|
+
} & {
|
47
|
+
authMethod: "otp";
|
48
|
+
}) | ({
|
49
|
+
phone: string;
|
50
|
+
options?: {
|
51
|
+
shouldCreateUser?: boolean;
|
52
|
+
data?: object;
|
53
|
+
captchaToken?: string;
|
54
|
+
channel?: "sms" | "whatsapp";
|
55
|
+
};
|
56
|
+
} & {
|
57
|
+
authMethod: "otp";
|
58
|
+
}) | ({
|
59
|
+
providerId: string;
|
60
|
+
options?: {
|
61
|
+
redirectTo?: string;
|
62
|
+
captchaToken?: string;
|
63
|
+
};
|
64
|
+
} & {
|
65
|
+
authMethod: "sso";
|
66
|
+
}) | ({
|
67
|
+
domain: string;
|
68
|
+
options?: {
|
69
|
+
redirectTo?: string;
|
70
|
+
captchaToken?: string;
|
71
|
+
};
|
72
|
+
} & {
|
73
|
+
authMethod: "sso";
|
74
|
+
}), AuthResponse | OAuthResponse | SSOResponse, unknown, void, {
|
75
|
+
email: string;
|
76
|
+
password: string;
|
77
|
+
options?: {
|
78
|
+
emailRedirectTo?: string;
|
79
|
+
data?: object;
|
80
|
+
captchaToken?: string;
|
81
|
+
};
|
82
|
+
} | {
|
83
|
+
phone: string;
|
84
|
+
password: string;
|
85
|
+
options?: {
|
86
|
+
data?: object;
|
87
|
+
captchaToken?: string;
|
88
|
+
channel?: "sms" | "whatsapp";
|
89
|
+
};
|
90
|
+
}, AuthResponse, unknown, unknown, unknown, unknown, SupabaseClient<any, "public", any>> | undefined>;
|
91
|
+
AuthProvider: ({ children }: import("@redmix/auth").AuthProviderProps) => import("react").JSX.Element;
|
92
|
+
useAuth: () => import("@redmix/auth").AuthContextInterface<import("@supabase/supabase-js").UserMetadata, SignInWithOAuthOptions | SignInWithIdTokenOptions | ({
|
93
|
+
email: string;
|
94
|
+
password: string;
|
95
|
+
options?: {
|
96
|
+
captchaToken?: string;
|
97
|
+
};
|
98
|
+
} & {
|
99
|
+
authMethod: "password";
|
100
|
+
}) | ({
|
101
|
+
phone: string;
|
102
|
+
password: string;
|
103
|
+
options?: {
|
104
|
+
captchaToken?: string;
|
105
|
+
};
|
106
|
+
} & {
|
107
|
+
authMethod: "password";
|
108
|
+
}) | ({
|
109
|
+
email: string;
|
110
|
+
options?: {
|
111
|
+
emailRedirectTo?: string;
|
112
|
+
shouldCreateUser?: boolean;
|
113
|
+
data?: object;
|
114
|
+
captchaToken?: string;
|
115
|
+
};
|
116
|
+
} & {
|
117
|
+
authMethod: "otp";
|
118
|
+
}) | ({
|
119
|
+
phone: string;
|
120
|
+
options?: {
|
121
|
+
shouldCreateUser?: boolean;
|
122
|
+
data?: object;
|
123
|
+
captchaToken?: string;
|
124
|
+
channel?: "sms" | "whatsapp";
|
125
|
+
};
|
126
|
+
} & {
|
127
|
+
authMethod: "otp";
|
128
|
+
}) | ({
|
129
|
+
providerId: string;
|
130
|
+
options?: {
|
131
|
+
redirectTo?: string;
|
132
|
+
captchaToken?: string;
|
133
|
+
};
|
134
|
+
} & {
|
135
|
+
authMethod: "sso";
|
136
|
+
}) | ({
|
137
|
+
domain: string;
|
138
|
+
options?: {
|
139
|
+
redirectTo?: string;
|
140
|
+
captchaToken?: string;
|
141
|
+
};
|
142
|
+
} & {
|
143
|
+
authMethod: "sso";
|
144
|
+
}), AuthResponse | OAuthResponse | SSOResponse, unknown, void, {
|
145
|
+
email: string;
|
146
|
+
password: string;
|
147
|
+
options?: {
|
148
|
+
emailRedirectTo?: string;
|
149
|
+
data?: object;
|
150
|
+
captchaToken?: string;
|
151
|
+
};
|
152
|
+
} | {
|
153
|
+
phone: string;
|
154
|
+
password: string;
|
155
|
+
options?: {
|
156
|
+
data?: object;
|
157
|
+
captchaToken?: string;
|
158
|
+
channel?: "sms" | "whatsapp";
|
159
|
+
};
|
160
|
+
}, AuthResponse, unknown, unknown, unknown, unknown, SupabaseClient<any, "public", any>>;
|
161
|
+
};
|
162
|
+
//# sourceMappingURL=supabase.d.ts.map
|
@@ -0,0 +1 @@
|
|
1
|
+
{"version":3,"file":"supabase.d.ts","sourceRoot":"","sources":["../src/supabase.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,cAAc,EACd,YAAY,EACZ,aAAa,EACb,WAAW,EACX,0BAA0B,EAC1B,4BAA4B,EAC5B,6BAA6B,EAC7B,iCAAiC,EACjC,aAAa,EAId,MAAM,uBAAuB,CAAA;AAG9B,OAAO,KAAK,EAAE,WAAW,EAAuB,MAAM,cAAc,CAAA;AAMpE,MAAM,MAAM,sBAAsB,GAAG,0BAA0B,GAAG;IAChE,UAAU,EAAE,OAAO,CAAA;CACpB,CAAA;AAED,MAAM,MAAM,wBAAwB,GAAG,4BAA4B,GAAG;IACpE,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,yBAAyB,GAAG,6BAA6B,GAAG;IACtE,UAAU,EAAE,UAAU,CAAA;CACvB,CAAA;AAED,MAAM,MAAM,6BAA6B,GACvC,iCAAiC,GAAG;IAClC,UAAU,EAAE,KAAK,CAAA;CAClB,CAAA;AAEH,MAAM,MAAM,oBAAoB,GAAG,aAAa,GAAG;IACjD,UAAU,EAAE,KAAK,CAAA;CAClB,CAAA;AAmBD,wBAAgB,UAAU,CACxB,cAAc,EAAE,cAAc,EAC9B,mBAAmB,CAAC,EAAE;IACpB,cAAc,CAAC,EAAE,MAAM,OAAO,CAAC,WAAW,CAAC,CAAA;IAC3C,UAAU,CAAC,EAAE,CACX,WAAW,EAAE,WAAW,GAAG,IAAI,KAC5B,CAAC,YAAY,EAAE,MAAM,GAAG,MAAM,EAAE,KAAK,OAAO,CAAA;CAClD;;;;;wBAyO65H,CAAC;;;oBA7Qn5H,UAAU;;;;;wBA6Q6oI,CAAC;;;oBA7QxpI,UAAU;;;;2BA6Qs3I,CAAC;4BAA4H,CAAC;gBAAoS,CAAC;wBAA0H,CAAC;;;oBAxQ55J,KAAK;;;;4BAwQumK,CAAC;gBAAoS,CAAC;wBAA0H,CAAC;mBAAwF,CAAC;;;oBAxQtmL,KAAK;;;;sBAwQitT,CAAC;wBAA0H,CAAC;;;oBApQp1T,KAAK;;;;sBAoQ+iU,CAAC;wBAA0H,CAAC;;;oBApQhrU,KAAK;;;;;2BAoQu/E,CAAC;gBAAmS,CAAC;wBAA0H,CAAC;;;;;;gBAA6a,CAAC;wBAA0K,CAAC;mBAAwF,CAAC;;;wCA/PvkH,cAEjB,+BAA+B,OAAO;;;;;wBA6Ps3H,CAAC;;;oBA7Qn5H,UAAU;;;;;wBA6Q6oI,CAAC;;;oBA7QxpI,UAAU;;;;2BA6Qs3I,CAAC;4BAA4H,CAAC;gBAAoS,CAAC;wBAA0H,CAAC;;;oBAxQ55J,KAAK;;;;4BAwQumK,CAAC;gBAAoS,CAAC;wBAA0H,CAAC;mBAAwF,CAAC;;;oBAxQtmL,KAAK;;;;sBAwQitT,CAAC;wBAA0H,CAAC;;;oBApQp1T,KAAK;;;;sBAoQ+iU,CAAC;wBAA0H,CAAC;;;oBApQhrU,KAAK;;;;;2BAoQu/E,CAAC;gBAAmS,CAAC;wBAA0H,CAAC;;;;;;gBAA6a,CAAC;wBAA0K,CAAC;mBAAwF,CAAC;;;EAhO3lH"}
|
package/dist/supabase.js
ADDED
@@ -0,0 +1,213 @@
|
|
1
|
+
import { DEFAULT_COOKIE_OPTIONS as DEFAULT_SUPABASE_COOKIE_OPTIONS } from "@supabase/ssr";
|
2
|
+
import { serialize } from "@supabase/ssr";
|
3
|
+
import { AuthError } from "@supabase/supabase-js";
|
4
|
+
import {
|
5
|
+
createAuthentication,
|
6
|
+
getCurrentUserFromMiddleware
|
7
|
+
} from "@redmix/auth";
|
8
|
+
function createMiddlewareAuth(supabaseClient, customProviderHooks) {
|
9
|
+
const authImplementation = createAuthImplementation({
|
10
|
+
supabaseClient,
|
11
|
+
middleware: true
|
12
|
+
});
|
13
|
+
return createAuthentication(authImplementation, {
|
14
|
+
...customProviderHooks,
|
15
|
+
useCurrentUser: customProviderHooks?.useCurrentUser ?? (() => getCurrentUserFromMiddleware("/middleware/supabase"))
|
16
|
+
});
|
17
|
+
}
|
18
|
+
function createAuth(supabaseClient, customProviderHooks) {
|
19
|
+
if (RWJS_ENV.RWJS_EXP_STREAMING_SSR) {
|
20
|
+
return createMiddlewareAuth(supabaseClient, customProviderHooks);
|
21
|
+
}
|
22
|
+
const authImplementation = createAuthImplementation({ supabaseClient });
|
23
|
+
return createAuthentication(authImplementation, customProviderHooks);
|
24
|
+
}
|
25
|
+
const setAuthProviderCookie = () => {
|
26
|
+
const authProviderCookieString = serialize(
|
27
|
+
"auth-provider",
|
28
|
+
"supabase",
|
29
|
+
DEFAULT_SUPABASE_COOKIE_OPTIONS
|
30
|
+
);
|
31
|
+
document.cookie = authProviderCookieString;
|
32
|
+
};
|
33
|
+
const expireAuthProviderCookie = () => {
|
34
|
+
const authProviderCookieString = serialize("auth-provider", "supabase", {
|
35
|
+
...DEFAULT_SUPABASE_COOKIE_OPTIONS,
|
36
|
+
maxAge: -1
|
37
|
+
});
|
38
|
+
document.cookie = authProviderCookieString;
|
39
|
+
};
|
40
|
+
function createAuthImplementation({
|
41
|
+
supabaseClient,
|
42
|
+
middleware = false
|
43
|
+
}) {
|
44
|
+
return {
|
45
|
+
type: "supabase",
|
46
|
+
client: supabaseClient,
|
47
|
+
/*
|
48
|
+
* All Supabase Sign In Authentication Methods
|
49
|
+
*/
|
50
|
+
login: async (credentials) => {
|
51
|
+
let result;
|
52
|
+
switch (credentials.authMethod) {
|
53
|
+
/**
|
54
|
+
* Log in an existing user with an email and password or phone and password.
|
55
|
+
*
|
56
|
+
* Be aware that you may get back an error message that will not distinguish
|
57
|
+
* between the cases where the account does not exist or that the
|
58
|
+
* email/phone and password combination is wrong or that the account can only
|
59
|
+
* be accessed via social login.
|
60
|
+
*/
|
61
|
+
case "password":
|
62
|
+
result = await supabaseClient.auth.signInWithPassword(credentials);
|
63
|
+
break;
|
64
|
+
/**
|
65
|
+
* Log in an existing user via a third-party provider.
|
66
|
+
*/
|
67
|
+
case "oauth":
|
68
|
+
result = await supabaseClient.auth.signInWithOAuth(credentials);
|
69
|
+
break;
|
70
|
+
/**
|
71
|
+
* Log in a user using magiclink or a one-time password (OTP).
|
72
|
+
*
|
73
|
+
* If the `{{ .ConfirmationURL }}` variable is specified in the email template, a magiclink will be sent.
|
74
|
+
* If the `{{ .Token }}` variable is specified in the email template, an OTP will be sent.
|
75
|
+
* If you're using phone sign-ins, only an OTP will be sent. You won't be able to send a magiclink for phone sign-ins.
|
76
|
+
*
|
77
|
+
* Be aware that you may get back an error message that will not distinguish
|
78
|
+
* between the cases where the account does not exist or, that the account
|
79
|
+
* can only be accessed via social login.
|
80
|
+
*/
|
81
|
+
case "otp":
|
82
|
+
result = await supabaseClient.auth.signInWithOtp(credentials);
|
83
|
+
break;
|
84
|
+
/**
|
85
|
+
* Attempts a single-sign on using an enterprise Identity Provider. A
|
86
|
+
* successful SSO attempt will redirect the current page to the identity
|
87
|
+
* provider authorization page. The redirect URL is implementation and SSO
|
88
|
+
* protocol specific.
|
89
|
+
*
|
90
|
+
* You can use it by providing a SSO domain. Typically you can extract this
|
91
|
+
* domain by asking users for their email address. If this domain is
|
92
|
+
* registered on the Auth instance the redirect will use that organization's
|
93
|
+
* currently active SSO Identity Provider for the login.
|
94
|
+
*
|
95
|
+
* If you have built an organization-specific login page, you can use the
|
96
|
+
* organization's SSO Identity Provider UUID directly instead.
|
97
|
+
*
|
98
|
+
* This API is experimental and availability is conditional on correct
|
99
|
+
* settings on the Auth service.
|
100
|
+
*
|
101
|
+
* @experimental
|
102
|
+
*/
|
103
|
+
case "sso":
|
104
|
+
result = await supabaseClient.auth.signInWithSSO(credentials);
|
105
|
+
break;
|
106
|
+
/**
|
107
|
+
* Allows signing in with an ID token issued by certain supported providers.
|
108
|
+
* The ID token is verified for validity and a new session is established.
|
109
|
+
*
|
110
|
+
* @experimental
|
111
|
+
*/
|
112
|
+
case "id_token":
|
113
|
+
result = await supabaseClient.auth.signInWithIdToken(credentials);
|
114
|
+
break;
|
115
|
+
default:
|
116
|
+
return {
|
117
|
+
data: { user: null, session: null },
|
118
|
+
error: new AuthError("Unsupported authentication method")
|
119
|
+
};
|
120
|
+
}
|
121
|
+
if (middleware) {
|
122
|
+
setAuthProviderCookie();
|
123
|
+
}
|
124
|
+
return result;
|
125
|
+
},
|
126
|
+
/**
|
127
|
+
* Inside a browser context, `signOut()` will remove the logged in user from the browser session
|
128
|
+
* and log them out - removing all items from localStorage and then trigger a `"SIGNED_OUT"` event.
|
129
|
+
*
|
130
|
+
* For server-side management, you can revoke all refresh tokens for a user by passing a user's JWT through to `auth.api.signOut(JWT: string)`.
|
131
|
+
* There is no way to revoke a user's access token jwt until it expires. It is recommended to set a shorter expiry on the jwt for this reason.
|
132
|
+
*/
|
133
|
+
logout: async () => {
|
134
|
+
const { error } = await supabaseClient.auth.signOut();
|
135
|
+
if (error) {
|
136
|
+
console.error(error);
|
137
|
+
}
|
138
|
+
if (middleware) {
|
139
|
+
expireAuthProviderCookie();
|
140
|
+
}
|
141
|
+
return;
|
142
|
+
},
|
143
|
+
/**
|
144
|
+
* Creates a new user.
|
145
|
+
*
|
146
|
+
* Be aware that if a user account exists in the system you may get back an
|
147
|
+
* error message that attempts to hide this information from the user.
|
148
|
+
*
|
149
|
+
* @returns A logged-in session if the server has "autoconfirm" ON
|
150
|
+
* @returns A user if the server has "autoconfirm" OFF
|
151
|
+
*/
|
152
|
+
signup: async (credentials) => {
|
153
|
+
const result = await supabaseClient.auth.signUp(credentials);
|
154
|
+
if (result.data?.session) {
|
155
|
+
setAuthProviderCookie();
|
156
|
+
}
|
157
|
+
return result;
|
158
|
+
},
|
159
|
+
getToken: async () => {
|
160
|
+
const { data, error } = await supabaseClient.auth.getSession();
|
161
|
+
if (error) {
|
162
|
+
console.error(error);
|
163
|
+
return null;
|
164
|
+
}
|
165
|
+
return data?.session?.access_token ?? null;
|
166
|
+
},
|
167
|
+
/**
|
168
|
+
* Gets the current user metadata if there is an existing session.
|
169
|
+
*/
|
170
|
+
getUserMetadata: async () => {
|
171
|
+
const { data, error } = await supabaseClient.auth.getSession();
|
172
|
+
if (error) {
|
173
|
+
console.error(error);
|
174
|
+
return null;
|
175
|
+
}
|
176
|
+
return data?.session?.user?.user_metadata ?? null;
|
177
|
+
},
|
178
|
+
/**
|
179
|
+
* Restore Redwood authentication state when an OAuth or magiclink
|
180
|
+
* callback redirects back to site with access token
|
181
|
+
* by restoring the Supabase auth session.
|
182
|
+
*
|
183
|
+
* Initializes the Supabase client session either from the url or from storage.
|
184
|
+
* This method is automatically called when instantiating the client, but should also be called
|
185
|
+
* manually when checking for an error from an auth redirect (oauth, magiclink, password recovery, etc).
|
186
|
+
*/
|
187
|
+
restoreAuthState: async () => {
|
188
|
+
try {
|
189
|
+
const { data } = await supabaseClient.auth.refreshSession();
|
190
|
+
if (middleware) {
|
191
|
+
if (data.session) {
|
192
|
+
setAuthProviderCookie();
|
193
|
+
} else {
|
194
|
+
expireAuthProviderCookie();
|
195
|
+
}
|
196
|
+
}
|
197
|
+
window.history.replaceState(
|
198
|
+
{},
|
199
|
+
document.title,
|
200
|
+
window.location.pathname
|
201
|
+
);
|
202
|
+
} catch (error) {
|
203
|
+
console.error(error);
|
204
|
+
}
|
205
|
+
return;
|
206
|
+
},
|
207
|
+
// This is important, so we can skip fetching getCurrentUser
|
208
|
+
useMiddlewareAuth: middleware
|
209
|
+
};
|
210
|
+
}
|
211
|
+
export {
|
212
|
+
createAuth
|
213
|
+
};
|
package/package.json
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
{
|
2
|
+
"name": "@redmix/auth-supabase-web",
|
3
|
+
"version": "0.0.1",
|
4
|
+
"repository": {
|
5
|
+
"type": "git",
|
6
|
+
"url": "git+https://github.com/redmix-run/redmix.git",
|
7
|
+
"directory": "packages/auth-providers/supabase/web"
|
8
|
+
},
|
9
|
+
"license": "MIT",
|
10
|
+
"type": "module",
|
11
|
+
"exports": {
|
12
|
+
".": {
|
13
|
+
"import": {
|
14
|
+
"types": "./dist/index.d.ts",
|
15
|
+
"default": "./dist/index.js"
|
16
|
+
},
|
17
|
+
"default": {
|
18
|
+
"types": "./dist/cjs/index.d.ts",
|
19
|
+
"default": "./dist/cjs/index.js"
|
20
|
+
}
|
21
|
+
},
|
22
|
+
"./dist/supabase": {
|
23
|
+
"import": {
|
24
|
+
"types": "./dist/supabase.d.ts",
|
25
|
+
"default": "./dist/supabase.js"
|
26
|
+
},
|
27
|
+
"default": {
|
28
|
+
"types": "./dist/cjs/supabase.d.ts",
|
29
|
+
"default": "./dist/cjs/supabase.js"
|
30
|
+
}
|
31
|
+
}
|
32
|
+
},
|
33
|
+
"main": "./dist/cjs/index.js",
|
34
|
+
"module": "./dist/index.js",
|
35
|
+
"types": "./dist/index.d.ts",
|
36
|
+
"files": [
|
37
|
+
"dist"
|
38
|
+
],
|
39
|
+
"scripts": {
|
40
|
+
"build": "tsx ./build.ts",
|
41
|
+
"build:pack": "yarn pack -o redmix-auth-supabase-web.tgz",
|
42
|
+
"build:types": "tsc --build --verbose ./tsconfig.build.json",
|
43
|
+
"build:types-cjs": "tsc --build --verbose ./tsconfig.cjs.json",
|
44
|
+
"build:watch": "nodemon --watch src --ext \"js,jsx,ts,tsx,template\" --ignore dist --exec \"yarn build\"",
|
45
|
+
"check:attw": "yarn rw-fwtools-attw",
|
46
|
+
"check:package": "concurrently npm:check:attw yarn:publint",
|
47
|
+
"prepublishOnly": "NODE_ENV=production yarn build",
|
48
|
+
"test": "vitest run",
|
49
|
+
"test:watch": "vitest watch"
|
50
|
+
},
|
51
|
+
"dependencies": {
|
52
|
+
"@redmix/auth": "0.0.1"
|
53
|
+
},
|
54
|
+
"devDependencies": {
|
55
|
+
"@redmix/framework-tools": "0.0.1",
|
56
|
+
"@supabase/ssr": "0.5.1",
|
57
|
+
"@supabase/supabase-js": "2.45.4",
|
58
|
+
"@types/react": "^18.2.55",
|
59
|
+
"concurrently": "8.2.2",
|
60
|
+
"publint": "0.3.11",
|
61
|
+
"react": "19.0.0-rc-f2df5694-20240916",
|
62
|
+
"tsx": "4.19.3",
|
63
|
+
"typescript": "5.6.2",
|
64
|
+
"vitest": "2.1.9"
|
65
|
+
},
|
66
|
+
"peerDependencies": {
|
67
|
+
"@supabase/supabase-js": "2.45.4"
|
68
|
+
},
|
69
|
+
"publishConfig": {
|
70
|
+
"access": "public"
|
71
|
+
},
|
72
|
+
"gitHead": "688027c97502c500ebbede9cdc7cc51545a8dcf3"
|
73
|
+
}
|