@quatrain/auth-supabase 1.1.18 → 1.1.20
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/package.json +3 -3
- package/lib/SupabaseAuthAdapter.d.ts +0 -23
- package/lib/SupabaseAuthAdapter.js +0 -177
- package/lib/SupabaseAuthAdapter.test.d.ts +0 -1
- package/lib/SupabaseAuthAdapter.test.js +0 -383
- package/lib/index.d.ts +0 -2
- package/lib/index.js +0 -5
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@quatrain/auth-supabase",
|
|
3
|
-
"version": "1.1.
|
|
3
|
+
"version": "1.1.20",
|
|
4
4
|
"license": "AGPL-3.0-only",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"types": "lib/index.d.ts",
|
|
@@ -13,8 +13,8 @@
|
|
|
13
13
|
],
|
|
14
14
|
"author": "Quatrain Développement SAS <developers@quatrain.com>",
|
|
15
15
|
"dependencies": {
|
|
16
|
-
"@quatrain/auth": "^1.1.
|
|
17
|
-
"@quatrain/backend": "^1.1.
|
|
16
|
+
"@quatrain/auth": "^1.1.21",
|
|
17
|
+
"@quatrain/backend": "^1.1.27",
|
|
18
18
|
"@supabase/supabase-js": "^2.87.3",
|
|
19
19
|
"node-fetch-native": "^1.6.4"
|
|
20
20
|
},
|
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
import { User } from '@quatrain/backend';
|
|
2
|
-
import { AbstractAuthAdapter, AuthParameters } from '@quatrain/auth';
|
|
3
|
-
export declare class SupabaseAuthAdapter extends AbstractAuthAdapter {
|
|
4
|
-
protected _client: any;
|
|
5
|
-
constructor(params?: AuthParameters);
|
|
6
|
-
/**
|
|
7
|
-
* Register new user in authentication
|
|
8
|
-
* @param user
|
|
9
|
-
* @returns user unique id
|
|
10
|
-
*/
|
|
11
|
-
register(user: User, clearPassword?: string): Promise<any>;
|
|
12
|
-
getAuthToken(bearer: string): Promise<any>;
|
|
13
|
-
refreshToken(refreshToken: string): Promise<any>;
|
|
14
|
-
revokeAuthToken(token: string): Promise<false | undefined>;
|
|
15
|
-
signup(login: string, password: string): Promise<false | {
|
|
16
|
-
user: any;
|
|
17
|
-
session: any;
|
|
18
|
-
}>;
|
|
19
|
-
signout(): Promise<any>;
|
|
20
|
-
update(user: User, updatable: any): Promise<any>;
|
|
21
|
-
delete(user: User): Promise<any>;
|
|
22
|
-
setCustomUserClaims(id: string, claims: any): Promise<any>;
|
|
23
|
-
}
|
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
exports.SupabaseAuthAdapter = void 0;
|
|
36
|
-
const auth_1 = require("@quatrain/auth");
|
|
37
|
-
const supabase_js_1 = require("@supabase/supabase-js");
|
|
38
|
-
const nativeFetch = __importStar(require("node-fetch-native"));
|
|
39
|
-
// Create a single supabase client for interacting with your database
|
|
40
|
-
class SupabaseAuthAdapter extends auth_1.AbstractAuthAdapter {
|
|
41
|
-
constructor(params = {}) {
|
|
42
|
-
super(params);
|
|
43
|
-
this._client = (0, supabase_js_1.createClient)(params.config.supabaseUrl, params.config.supabaseKey, {
|
|
44
|
-
auth: {
|
|
45
|
-
autoRefreshToken: false,
|
|
46
|
-
persistSession: false,
|
|
47
|
-
},
|
|
48
|
-
});
|
|
49
|
-
auth_1.Auth.info(`Created Supabase client for ${params.config.supabaseUrl}`);
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Register new user in authentication
|
|
53
|
-
* @param user
|
|
54
|
-
* @returns user unique id
|
|
55
|
-
*/
|
|
56
|
-
register(user, clearPassword) {
|
|
57
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
58
|
-
try {
|
|
59
|
-
const { name: displayName, email, phone: phoneNumber, password, } = user._;
|
|
60
|
-
auth_1.Auth.info(`[SAA] Adding user '${displayName}'`);
|
|
61
|
-
const { data, error } = yield this._client.auth.admin.createUser({
|
|
62
|
-
email,
|
|
63
|
-
password: clearPassword || password,
|
|
64
|
-
email_confirm: true, // TODO move to params
|
|
65
|
-
});
|
|
66
|
-
if (error) {
|
|
67
|
-
auth_1.Auth.error(error.message);
|
|
68
|
-
if (error.code === 'email_exists') {
|
|
69
|
-
throw new auth_1.AuthenticationError(auth_1.Auth.ERROR_EMAIL_EXISTS);
|
|
70
|
-
}
|
|
71
|
-
throw new Error(error);
|
|
72
|
-
}
|
|
73
|
-
return data.user;
|
|
74
|
-
}
|
|
75
|
-
catch (err) {
|
|
76
|
-
auth_1.Auth.error(err);
|
|
77
|
-
throw new auth_1.AuthenticationError(err.message);
|
|
78
|
-
}
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
getAuthToken(bearer) {
|
|
82
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
83
|
-
const token = yield this._client.auth.getUser(bearer);
|
|
84
|
-
if (token.data && token.data.user) {
|
|
85
|
-
return token.data.user;
|
|
86
|
-
}
|
|
87
|
-
throw new Error('Unable to retrieve auth token from Supabase');
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
refreshToken(refreshToken) {
|
|
91
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
-
const url = `${this._params.config.supabaseUrl}/auth/v1/token?grant_type=refresh_token`;
|
|
93
|
-
const response = yield nativeFetch.fetch(url, {
|
|
94
|
-
method: 'POST',
|
|
95
|
-
headers: {
|
|
96
|
-
apikey: this._params.config.supabaseKey,
|
|
97
|
-
},
|
|
98
|
-
body: JSON.stringify({
|
|
99
|
-
refresh_token: refreshToken,
|
|
100
|
-
}),
|
|
101
|
-
});
|
|
102
|
-
const data = response.json();
|
|
103
|
-
return data;
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
revokeAuthToken(token) {
|
|
107
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
108
|
-
// Careful, this only delete tokens on client side, not on server side
|
|
109
|
-
const { error } = yield this.signout();
|
|
110
|
-
if (error !== null) {
|
|
111
|
-
auth_1.Auth.error(error);
|
|
112
|
-
return false;
|
|
113
|
-
}
|
|
114
|
-
});
|
|
115
|
-
}
|
|
116
|
-
signup(login, password) {
|
|
117
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
118
|
-
const { data, error } = yield this._client.auth.signInWithPassword({
|
|
119
|
-
email: login,
|
|
120
|
-
password,
|
|
121
|
-
});
|
|
122
|
-
if (error !== null) {
|
|
123
|
-
auth_1.Auth.error(error);
|
|
124
|
-
return false;
|
|
125
|
-
}
|
|
126
|
-
return { user: data.user, session: data.session };
|
|
127
|
-
});
|
|
128
|
-
}
|
|
129
|
-
signout() {
|
|
130
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
131
|
-
const { error } = yield this._client.auth.signOut();
|
|
132
|
-
if (error !== null) {
|
|
133
|
-
auth_1.Auth.error(error);
|
|
134
|
-
return false;
|
|
135
|
-
}
|
|
136
|
-
return true;
|
|
137
|
-
});
|
|
138
|
-
}
|
|
139
|
-
update(user, updatable) {
|
|
140
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
141
|
-
auth_1.Auth.debug('auth data to update', JSON.stringify(updatable));
|
|
142
|
-
try {
|
|
143
|
-
if (Object.keys(updatable).length > 0) {
|
|
144
|
-
auth_1.Auth.info(`Updating ${updatable.displayName} Auth record`);
|
|
145
|
-
const { error } = yield this._client.auth.admin.updateUserById(user.uid, updatable);
|
|
146
|
-
if (error !== null) {
|
|
147
|
-
auth_1.Auth.error(error);
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
catch (e) {
|
|
152
|
-
auth_1.Auth.error(e);
|
|
153
|
-
return false;
|
|
154
|
-
}
|
|
155
|
-
});
|
|
156
|
-
}
|
|
157
|
-
delete(user) {
|
|
158
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
159
|
-
// return await getAuth().deleteUser(user.uid)
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
setCustomUserClaims(id, claims) {
|
|
163
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
164
|
-
auth_1.Auth.debug(`Updating user ${id} with claims ${JSON.stringify(claims)}`);
|
|
165
|
-
const { data, error } = yield this._client.auth.admin.updateUserById(id, {
|
|
166
|
-
user_metadata: claims,
|
|
167
|
-
});
|
|
168
|
-
if (error) {
|
|
169
|
-
throw new auth_1.AuthenticationError(error);
|
|
170
|
-
}
|
|
171
|
-
else {
|
|
172
|
-
return data;
|
|
173
|
-
}
|
|
174
|
-
});
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
exports.SupabaseAuthAdapter = SupabaseAuthAdapter;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,383 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
-
if (mod && mod.__esModule) return mod;
|
|
20
|
-
var result = {};
|
|
21
|
-
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
-
__setModuleDefault(result, mod);
|
|
23
|
-
return result;
|
|
24
|
-
};
|
|
25
|
-
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
-
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
-
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
-
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
-
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
-
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
-
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
-
});
|
|
33
|
-
};
|
|
34
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
-
const SupabaseAuthAdapter_1 = require("./SupabaseAuthAdapter");
|
|
36
|
-
const auth_1 = require("@quatrain/auth");
|
|
37
|
-
const supabase_js_1 = require("@supabase/supabase-js");
|
|
38
|
-
const nativeFetch = __importStar(require("node-fetch-native"));
|
|
39
|
-
// Mock the dependencies
|
|
40
|
-
jest.mock('@supabase/supabase-js');
|
|
41
|
-
jest.mock('node-fetch-native');
|
|
42
|
-
describe('SupabaseAuthAdapter', () => {
|
|
43
|
-
let adapter;
|
|
44
|
-
let mockSupabaseClient;
|
|
45
|
-
let mockAuthAdmin;
|
|
46
|
-
let mockAuth;
|
|
47
|
-
beforeEach(() => {
|
|
48
|
-
// Clear all mocks before each test
|
|
49
|
-
jest.clearAllMocks();
|
|
50
|
-
// Create mock Supabase client structure
|
|
51
|
-
mockAuthAdmin = {
|
|
52
|
-
createUser: jest.fn(),
|
|
53
|
-
updateUserById: jest.fn(),
|
|
54
|
-
};
|
|
55
|
-
mockAuth = {
|
|
56
|
-
admin: mockAuthAdmin,
|
|
57
|
-
getUser: jest.fn(),
|
|
58
|
-
signInWithPassword: jest.fn(),
|
|
59
|
-
signOut: jest.fn(),
|
|
60
|
-
};
|
|
61
|
-
mockSupabaseClient = {
|
|
62
|
-
auth: mockAuth,
|
|
63
|
-
};
|
|
64
|
-
supabase_js_1.createClient.mockReturnValue(mockSupabaseClient);
|
|
65
|
-
// Create adapter instance
|
|
66
|
-
adapter = new SupabaseAuthAdapter_1.SupabaseAuthAdapter({
|
|
67
|
-
config: {
|
|
68
|
-
supabaseUrl: 'https://test.supabase.co',
|
|
69
|
-
supabaseKey: 'test-key-123',
|
|
70
|
-
},
|
|
71
|
-
});
|
|
72
|
-
});
|
|
73
|
-
afterEach(() => {
|
|
74
|
-
jest.restoreAllMocks();
|
|
75
|
-
});
|
|
76
|
-
describe('Constructor', () => {
|
|
77
|
-
it('should create Supabase client with correct configuration', () => {
|
|
78
|
-
expect(supabase_js_1.createClient).toHaveBeenCalledWith('https://test.supabase.co', 'test-key-123', {
|
|
79
|
-
auth: {
|
|
80
|
-
autoRefreshToken: false,
|
|
81
|
-
persistSession: false,
|
|
82
|
-
},
|
|
83
|
-
});
|
|
84
|
-
});
|
|
85
|
-
it('should set autoRefreshToken to false', () => {
|
|
86
|
-
const callArgs = supabase_js_1.createClient.mock.calls[0];
|
|
87
|
-
expect(callArgs[2].auth.autoRefreshToken).toBe(false);
|
|
88
|
-
});
|
|
89
|
-
it('should set persistSession to false', () => {
|
|
90
|
-
const callArgs = supabase_js_1.createClient.mock.calls[0];
|
|
91
|
-
expect(callArgs[2].auth.persistSession).toBe(false);
|
|
92
|
-
});
|
|
93
|
-
});
|
|
94
|
-
describe('register()', () => {
|
|
95
|
-
const mockUser = {
|
|
96
|
-
_: {
|
|
97
|
-
name: 'John Doe',
|
|
98
|
-
email: 'john@example.com',
|
|
99
|
-
phone: '+1234567890',
|
|
100
|
-
password: 'hashed-password',
|
|
101
|
-
},
|
|
102
|
-
};
|
|
103
|
-
it('should successfully register a new user', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
104
|
-
const mockSupabaseUser = {
|
|
105
|
-
id: 'user-123',
|
|
106
|
-
email: 'john@example.com',
|
|
107
|
-
};
|
|
108
|
-
mockAuthAdmin.createUser.mockResolvedValue({
|
|
109
|
-
data: { user: mockSupabaseUser },
|
|
110
|
-
error: null,
|
|
111
|
-
});
|
|
112
|
-
const result = yield adapter.register(mockUser, 'clearPassword123');
|
|
113
|
-
expect(mockAuthAdmin.createUser).toHaveBeenCalledWith({
|
|
114
|
-
email: 'john@example.com',
|
|
115
|
-
password: 'clearPassword123',
|
|
116
|
-
email_confirm: true,
|
|
117
|
-
});
|
|
118
|
-
expect(result).toEqual(mockSupabaseUser);
|
|
119
|
-
}));
|
|
120
|
-
it('should use hashed password when clearPassword is not provided', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
121
|
-
const mockSupabaseUser = {
|
|
122
|
-
id: 'user-123',
|
|
123
|
-
email: 'john@example.com',
|
|
124
|
-
};
|
|
125
|
-
mockAuthAdmin.createUser.mockResolvedValue({
|
|
126
|
-
data: { user: mockSupabaseUser },
|
|
127
|
-
error: null,
|
|
128
|
-
});
|
|
129
|
-
yield adapter.register(mockUser);
|
|
130
|
-
expect(mockAuthAdmin.createUser).toHaveBeenCalledWith({
|
|
131
|
-
email: 'john@example.com',
|
|
132
|
-
password: 'hashed-password',
|
|
133
|
-
email_confirm: true,
|
|
134
|
-
});
|
|
135
|
-
}));
|
|
136
|
-
it('should throw AuthenticationError when email already exists', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
137
|
-
mockAuthAdmin.createUser.mockResolvedValue({
|
|
138
|
-
data: null,
|
|
139
|
-
error: {
|
|
140
|
-
code: 'email_exists',
|
|
141
|
-
message: 'User already registered',
|
|
142
|
-
},
|
|
143
|
-
});
|
|
144
|
-
yield expect(adapter.register(mockUser, 'password')).rejects.toThrow(auth_1.AuthenticationError);
|
|
145
|
-
yield expect(adapter.register(mockUser, 'password')).rejects.toThrow('User email already exists');
|
|
146
|
-
}));
|
|
147
|
-
it('should throw AuthenticationError on generic error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
148
|
-
mockAuthAdmin.createUser.mockResolvedValue({
|
|
149
|
-
data: null,
|
|
150
|
-
error: {
|
|
151
|
-
code: 'server_error',
|
|
152
|
-
message: 'Internal server error',
|
|
153
|
-
},
|
|
154
|
-
});
|
|
155
|
-
yield expect(adapter.register(mockUser, 'password')).rejects.toThrow(auth_1.AuthenticationError);
|
|
156
|
-
}));
|
|
157
|
-
it('should handle exceptions and wrap them in AuthenticationError', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
158
|
-
mockAuthAdmin.createUser.mockRejectedValue(new Error('Network error'));
|
|
159
|
-
yield expect(adapter.register(mockUser, 'password')).rejects.toThrow(auth_1.AuthenticationError);
|
|
160
|
-
yield expect(adapter.register(mockUser, 'password')).rejects.toThrow('Network error');
|
|
161
|
-
}));
|
|
162
|
-
});
|
|
163
|
-
describe('getAuthToken()', () => {
|
|
164
|
-
it('should successfully retrieve auth token', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
165
|
-
const mockUserData = {
|
|
166
|
-
id: 'user-123',
|
|
167
|
-
email: 'test@example.com',
|
|
168
|
-
};
|
|
169
|
-
mockAuth.getUser.mockResolvedValue({
|
|
170
|
-
data: { user: mockUserData },
|
|
171
|
-
error: null,
|
|
172
|
-
});
|
|
173
|
-
const result = yield adapter.getAuthToken('bearer-token-123');
|
|
174
|
-
expect(mockAuth.getUser).toHaveBeenCalledWith('bearer-token-123');
|
|
175
|
-
expect(result).toEqual(mockUserData);
|
|
176
|
-
}));
|
|
177
|
-
it('should throw error when user data is missing', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
178
|
-
mockAuth.getUser.mockResolvedValue({
|
|
179
|
-
data: null,
|
|
180
|
-
error: null,
|
|
181
|
-
});
|
|
182
|
-
yield expect(adapter.getAuthToken('invalid-token')).rejects.toThrow('Unable to retrieve auth token from Supabase');
|
|
183
|
-
}));
|
|
184
|
-
it('should throw error when user is undefined', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
185
|
-
mockAuth.getUser.mockResolvedValue({
|
|
186
|
-
data: { user: null },
|
|
187
|
-
error: null,
|
|
188
|
-
});
|
|
189
|
-
yield expect(adapter.getAuthToken('invalid-token')).rejects.toThrow('Unable to retrieve auth token from Supabase');
|
|
190
|
-
}));
|
|
191
|
-
});
|
|
192
|
-
describe('refreshToken()', () => {
|
|
193
|
-
it('should successfully refresh token', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
194
|
-
const mockResponse = {
|
|
195
|
-
access_token: 'new-token',
|
|
196
|
-
refresh_token: 'new-refresh-token',
|
|
197
|
-
};
|
|
198
|
-
const mockFetchResponse = {
|
|
199
|
-
json: jest.fn().mockResolvedValue(mockResponse),
|
|
200
|
-
};
|
|
201
|
-
nativeFetch.fetch.mockResolvedValue(mockFetchResponse);
|
|
202
|
-
const result = yield adapter.refreshToken('old-refresh-token');
|
|
203
|
-
expect(nativeFetch.fetch).toHaveBeenCalledWith('https://test.supabase.co/auth/v1/token?grant_type=refresh_token', {
|
|
204
|
-
method: 'POST',
|
|
205
|
-
headers: {
|
|
206
|
-
apikey: 'test-key-123',
|
|
207
|
-
},
|
|
208
|
-
body: JSON.stringify({
|
|
209
|
-
refresh_token: 'old-refresh-token',
|
|
210
|
-
}),
|
|
211
|
-
});
|
|
212
|
-
// Note: The actual implementation doesn't await json(), so result is the promise
|
|
213
|
-
// But since we mocked it to return the value, we get the direct value
|
|
214
|
-
const resultValue = yield result;
|
|
215
|
-
expect(resultValue).toEqual(mockResponse);
|
|
216
|
-
}));
|
|
217
|
-
it('should construct correct URL with config values', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
218
|
-
const mockFetchResponse = {
|
|
219
|
-
json: jest.fn().mockResolvedValue({}),
|
|
220
|
-
};
|
|
221
|
-
nativeFetch.fetch.mockResolvedValue(mockFetchResponse);
|
|
222
|
-
yield adapter.refreshToken('refresh-token');
|
|
223
|
-
const callArgs = nativeFetch.fetch.mock.calls[0];
|
|
224
|
-
expect(callArgs[0]).toBe('https://test.supabase.co/auth/v1/token?grant_type=refresh_token');
|
|
225
|
-
}));
|
|
226
|
-
});
|
|
227
|
-
describe('revokeAuthToken()', () => {
|
|
228
|
-
it('should successfully revoke token via signout', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
229
|
-
mockAuth.signOut.mockResolvedValue({
|
|
230
|
-
error: null,
|
|
231
|
-
});
|
|
232
|
-
const result = yield adapter.revokeAuthToken('token-123');
|
|
233
|
-
expect(mockAuth.signOut).toHaveBeenCalled();
|
|
234
|
-
// Note: The implementation has a bug - it destructures { error } from signout()
|
|
235
|
-
// which returns true/false, not an object. So error is undefined, and
|
|
236
|
-
// undefined !== null is true, so it returns false even on success.
|
|
237
|
-
expect(result).toBe(false);
|
|
238
|
-
}));
|
|
239
|
-
it('should return false when signout fails', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
240
|
-
mockAuth.signOut.mockResolvedValue({
|
|
241
|
-
error: { message: 'Signout failed' },
|
|
242
|
-
});
|
|
243
|
-
const result = yield adapter.revokeAuthToken('token-123');
|
|
244
|
-
expect(result).toBe(false);
|
|
245
|
-
}));
|
|
246
|
-
});
|
|
247
|
-
describe('signup()', () => {
|
|
248
|
-
it('should successfully sign in with email and password', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
249
|
-
const mockUserData = {
|
|
250
|
-
id: 'user-123',
|
|
251
|
-
email: 'test@example.com',
|
|
252
|
-
};
|
|
253
|
-
const mockSessionData = {
|
|
254
|
-
access_token: 'token-123',
|
|
255
|
-
refresh_token: 'refresh-123',
|
|
256
|
-
};
|
|
257
|
-
mockAuth.signInWithPassword.mockResolvedValue({
|
|
258
|
-
data: {
|
|
259
|
-
user: mockUserData,
|
|
260
|
-
session: mockSessionData,
|
|
261
|
-
},
|
|
262
|
-
error: null,
|
|
263
|
-
});
|
|
264
|
-
const result = yield adapter.signup('test@example.com', 'password123');
|
|
265
|
-
expect(mockAuth.signInWithPassword).toHaveBeenCalledWith({
|
|
266
|
-
email: 'test@example.com',
|
|
267
|
-
password: 'password123',
|
|
268
|
-
});
|
|
269
|
-
expect(result).toEqual({
|
|
270
|
-
user: mockUserData,
|
|
271
|
-
session: mockSessionData,
|
|
272
|
-
});
|
|
273
|
-
}));
|
|
274
|
-
it('should return false on error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
275
|
-
mockAuth.signInWithPassword.mockResolvedValue({
|
|
276
|
-
data: null,
|
|
277
|
-
error: { message: 'Invalid credentials' },
|
|
278
|
-
});
|
|
279
|
-
const result = yield adapter.signup('test@example.com', 'wrongpass');
|
|
280
|
-
expect(result).toBe(false);
|
|
281
|
-
}));
|
|
282
|
-
});
|
|
283
|
-
describe('signout()', () => {
|
|
284
|
-
it('should successfully sign out', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
285
|
-
mockAuth.signOut.mockResolvedValue({
|
|
286
|
-
error: null,
|
|
287
|
-
});
|
|
288
|
-
const result = yield adapter.signout();
|
|
289
|
-
expect(mockAuth.signOut).toHaveBeenCalled();
|
|
290
|
-
expect(result).toBe(true);
|
|
291
|
-
}));
|
|
292
|
-
it('should return false on error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
293
|
-
mockAuth.signOut.mockResolvedValue({
|
|
294
|
-
error: { message: 'Signout failed' },
|
|
295
|
-
});
|
|
296
|
-
const result = yield adapter.signout();
|
|
297
|
-
expect(result).toBe(false);
|
|
298
|
-
}));
|
|
299
|
-
});
|
|
300
|
-
describe('update()', () => {
|
|
301
|
-
const mockUser = {
|
|
302
|
-
uid: 'user-123',
|
|
303
|
-
_: {
|
|
304
|
-
email: 'test@example.com',
|
|
305
|
-
},
|
|
306
|
-
};
|
|
307
|
-
it('should successfully update user', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
308
|
-
const updatable = {
|
|
309
|
-
email: 'newemail@example.com',
|
|
310
|
-
displayName: 'New Name',
|
|
311
|
-
};
|
|
312
|
-
mockAuthAdmin.updateUserById.mockResolvedValue({
|
|
313
|
-
data: { user: Object.assign(Object.assign({}, mockUser), updatable) },
|
|
314
|
-
error: null,
|
|
315
|
-
});
|
|
316
|
-
yield adapter.update(mockUser, updatable);
|
|
317
|
-
expect(mockAuthAdmin.updateUserById).toHaveBeenCalledWith('user-123', updatable);
|
|
318
|
-
}));
|
|
319
|
-
it('should skip update when updatable is empty', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
320
|
-
yield adapter.update(mockUser, {});
|
|
321
|
-
expect(mockAuthAdmin.updateUserById).not.toHaveBeenCalled();
|
|
322
|
-
}));
|
|
323
|
-
it('should handle error during update', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
324
|
-
const updatable = { displayName: 'New Name' };
|
|
325
|
-
mockAuthAdmin.updateUserById.mockResolvedValue({
|
|
326
|
-
data: null,
|
|
327
|
-
error: { message: 'Update failed' },
|
|
328
|
-
});
|
|
329
|
-
yield adapter.update(mockUser, updatable);
|
|
330
|
-
// The method doesn't throw, just logs the error
|
|
331
|
-
expect(mockAuthAdmin.updateUserById).toHaveBeenCalledWith('user-123', updatable);
|
|
332
|
-
}));
|
|
333
|
-
it('should return false on exception', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
334
|
-
const updatable = { displayName: 'New Name' };
|
|
335
|
-
mockAuthAdmin.updateUserById.mockRejectedValue(new Error('Network error'));
|
|
336
|
-
const result = yield adapter.update(mockUser, updatable);
|
|
337
|
-
expect(result).toBe(false);
|
|
338
|
-
}));
|
|
339
|
-
});
|
|
340
|
-
describe('delete()', () => {
|
|
341
|
-
it('should have delete method defined', () => {
|
|
342
|
-
expect(adapter.delete).toBeDefined();
|
|
343
|
-
expect(typeof adapter.delete).toBe('function');
|
|
344
|
-
});
|
|
345
|
-
it('should be callable with a user', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
346
|
-
const mockUser = {
|
|
347
|
-
uid: 'user-123',
|
|
348
|
-
};
|
|
349
|
-
// The method is currently not implemented (empty)
|
|
350
|
-
const result = yield adapter.delete(mockUser);
|
|
351
|
-
expect(result).toBeUndefined();
|
|
352
|
-
}));
|
|
353
|
-
});
|
|
354
|
-
describe('setCustomUserClaims()', () => {
|
|
355
|
-
it('should successfully set custom user claims', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
356
|
-
const claims = {
|
|
357
|
-
role: 'admin',
|
|
358
|
-
permissions: ['read', 'write'],
|
|
359
|
-
};
|
|
360
|
-
const mockUserData = {
|
|
361
|
-
id: 'user-123',
|
|
362
|
-
user_metadata: claims,
|
|
363
|
-
};
|
|
364
|
-
mockAuthAdmin.updateUserById.mockResolvedValue({
|
|
365
|
-
data: mockUserData,
|
|
366
|
-
error: null,
|
|
367
|
-
});
|
|
368
|
-
const result = yield adapter.setCustomUserClaims('user-123', claims);
|
|
369
|
-
expect(mockAuthAdmin.updateUserById).toHaveBeenCalledWith('user-123', {
|
|
370
|
-
user_metadata: claims,
|
|
371
|
-
});
|
|
372
|
-
expect(result).toEqual(mockUserData);
|
|
373
|
-
}));
|
|
374
|
-
it('should throw AuthenticationError on error', () => __awaiter(void 0, void 0, void 0, function* () {
|
|
375
|
-
const claims = { role: 'admin' };
|
|
376
|
-
mockAuthAdmin.updateUserById.mockResolvedValue({
|
|
377
|
-
data: null,
|
|
378
|
-
error: { message: 'Update failed' },
|
|
379
|
-
});
|
|
380
|
-
yield expect(adapter.setCustomUserClaims('user-123', claims)).rejects.toThrow(auth_1.AuthenticationError);
|
|
381
|
-
}));
|
|
382
|
-
});
|
|
383
|
-
});
|
package/lib/index.d.ts
DELETED
package/lib/index.js
DELETED
|
@@ -1,5 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SupabaseAuthAdapter = void 0;
|
|
4
|
-
const SupabaseAuthAdapter_1 = require("./SupabaseAuthAdapter");
|
|
5
|
-
Object.defineProperty(exports, "SupabaseAuthAdapter", { enumerable: true, get: function () { return SupabaseAuthAdapter_1.SupabaseAuthAdapter; } });
|