@mastra/auth-supabase 0.0.0-fix-generate-title-20250616171351

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.
@@ -0,0 +1 @@
1
+ export { MastraAuthSupabase } from './_tsup-dts-rollup.cjs';
@@ -0,0 +1 @@
1
+ export { MastraAuthSupabase } from './_tsup-dts-rollup.js';
package/dist/index.js ADDED
@@ -0,0 +1,380 @@
1
+ import { SpanKind, trace, context, propagation, SpanStatusCode } from './chunk-JLXWUSDO.js';
2
+ import { createClient } from '@supabase/supabase-js';
3
+
4
+ // ../../packages/core/dist/chunk-BE2B3X5T.js
5
+ function hasActiveTelemetry(tracerName = "default-tracer") {
6
+ try {
7
+ return !!trace.getTracer(tracerName);
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ function getBaggageValues(ctx) {
13
+ const currentBaggage = propagation.getBaggage(ctx);
14
+ const requestId = currentBaggage?.getEntry("http.request_id")?.value;
15
+ const componentName = currentBaggage?.getEntry("componentName")?.value;
16
+ const runId = currentBaggage?.getEntry("runId")?.value;
17
+ return {
18
+ requestId,
19
+ componentName,
20
+ runId
21
+ };
22
+ }
23
+ function withSpan(options) {
24
+ return function(_target, propertyKey, descriptor) {
25
+ if (!descriptor || typeof descriptor === "number") return;
26
+ const originalMethod = descriptor.value;
27
+ const methodName = String(propertyKey);
28
+ descriptor.value = function(...args) {
29
+ if (options?.skipIfNoTelemetry && !hasActiveTelemetry(options?.tracerName)) {
30
+ return originalMethod.apply(this, args);
31
+ }
32
+ const tracer = trace.getTracer(options?.tracerName ?? "default-tracer");
33
+ let spanName;
34
+ let spanKind;
35
+ if (typeof options === "string") {
36
+ spanName = options;
37
+ } else if (options) {
38
+ spanName = options.spanName || methodName;
39
+ spanKind = options.spanKind;
40
+ } else {
41
+ spanName = methodName;
42
+ }
43
+ const span = tracer.startSpan(spanName, { kind: spanKind });
44
+ let ctx = trace.setSpan(context.active(), span);
45
+ args.forEach((arg, index) => {
46
+ try {
47
+ span.setAttribute(`${spanName}.argument.${index}`, JSON.stringify(arg));
48
+ } catch {
49
+ span.setAttribute(`${spanName}.argument.${index}`, "[Not Serializable]");
50
+ }
51
+ });
52
+ const { requestId, componentName, runId } = getBaggageValues(ctx);
53
+ if (requestId) {
54
+ span.setAttribute("http.request_id", requestId);
55
+ }
56
+ if (componentName) {
57
+ span.setAttribute("componentName", componentName);
58
+ span.setAttribute("runId", runId);
59
+ } else if (this && this.name) {
60
+ span.setAttribute("componentName", this.name);
61
+ span.setAttribute("runId", this.runId);
62
+ ctx = propagation.setBaggage(
63
+ ctx,
64
+ propagation.createBaggage({
65
+ // @ts-ignore
66
+ componentName: { value: this.name },
67
+ // @ts-ignore
68
+ runId: { value: this.runId },
69
+ // @ts-ignore
70
+ "http.request_id": { value: requestId }
71
+ })
72
+ );
73
+ }
74
+ let result;
75
+ try {
76
+ result = context.with(ctx, () => originalMethod.apply(this, args));
77
+ if (result instanceof Promise) {
78
+ return result.then((resolvedValue) => {
79
+ try {
80
+ span.setAttribute(`${spanName}.result`, JSON.stringify(resolvedValue));
81
+ } catch {
82
+ span.setAttribute(`${spanName}.result`, "[Not Serializable]");
83
+ }
84
+ return resolvedValue;
85
+ }).finally(() => span.end());
86
+ }
87
+ try {
88
+ span.setAttribute(`${spanName}.result`, JSON.stringify(result));
89
+ } catch {
90
+ span.setAttribute(`${spanName}.result`, "[Not Serializable]");
91
+ }
92
+ return result;
93
+ } catch (error) {
94
+ span.setStatus({
95
+ code: SpanStatusCode.ERROR,
96
+ message: error instanceof Error ? error.message : "Unknown error"
97
+ });
98
+ if (error instanceof Error) {
99
+ span.recordException(error);
100
+ }
101
+ throw error;
102
+ } finally {
103
+ if (!(result instanceof Promise)) {
104
+ span.end();
105
+ }
106
+ }
107
+ };
108
+ return descriptor;
109
+ };
110
+ }
111
+ function InstrumentClass(options) {
112
+ return function(target) {
113
+ const methods = Object.getOwnPropertyNames(target.prototype);
114
+ methods.forEach((method) => {
115
+ if (options?.excludeMethods?.includes(method) || method === "constructor") return;
116
+ if (options?.methodFilter && !options.methodFilter(method)) return;
117
+ const descriptor = Object.getOwnPropertyDescriptor(target.prototype, method);
118
+ if (descriptor && typeof descriptor.value === "function") {
119
+ Object.defineProperty(
120
+ target.prototype,
121
+ method,
122
+ withSpan({
123
+ spanName: options?.prefix ? `${options.prefix}.${method}` : method,
124
+ skipIfNoTelemetry: true,
125
+ spanKind: options?.spanKind || SpanKind.INTERNAL,
126
+ tracerName: options?.tracerName
127
+ })(target, method, descriptor)
128
+ );
129
+ }
130
+ });
131
+ return target;
132
+ };
133
+ }
134
+
135
+ // ../../packages/core/dist/chunk-5YDTZN2X.js
136
+ var RegisteredLogger = {
137
+ LLM: "LLM"};
138
+ var LogLevel = {
139
+ DEBUG: "debug",
140
+ INFO: "info",
141
+ WARN: "warn",
142
+ ERROR: "error"};
143
+ var MastraLogger = class {
144
+ name;
145
+ level;
146
+ transports;
147
+ constructor(options = {}) {
148
+ this.name = options.name || "Mastra";
149
+ this.level = options.level || LogLevel.ERROR;
150
+ this.transports = new Map(Object.entries(options.transports || {}));
151
+ }
152
+ getTransports() {
153
+ return this.transports;
154
+ }
155
+ trackException(_error) {
156
+ }
157
+ async getLogs(transportId, params) {
158
+ if (!transportId || !this.transports.has(transportId)) {
159
+ return { logs: [], total: 0, page: params?.page ?? 1, perPage: params?.perPage ?? 100, hasMore: false };
160
+ }
161
+ return this.transports.get(transportId).getLogs(params) ?? {
162
+ logs: [],
163
+ total: 0,
164
+ page: params?.page ?? 1,
165
+ perPage: params?.perPage ?? 100,
166
+ hasMore: false
167
+ };
168
+ }
169
+ async getLogsByRunId({
170
+ transportId,
171
+ runId,
172
+ fromDate,
173
+ toDate,
174
+ logLevel,
175
+ filters,
176
+ page,
177
+ perPage
178
+ }) {
179
+ if (!transportId || !this.transports.has(transportId) || !runId) {
180
+ return { logs: [], total: 0, page: page ?? 1, perPage: perPage ?? 100, hasMore: false };
181
+ }
182
+ return this.transports.get(transportId).getLogsByRunId({ runId, fromDate, toDate, logLevel, filters, page, perPage }) ?? {
183
+ logs: [],
184
+ total: 0,
185
+ page: page ?? 1,
186
+ perPage: perPage ?? 100,
187
+ hasMore: false
188
+ };
189
+ }
190
+ };
191
+ var ConsoleLogger = class extends MastraLogger {
192
+ constructor(options = {}) {
193
+ super(options);
194
+ }
195
+ debug(message, ...args) {
196
+ if (this.level === LogLevel.DEBUG) {
197
+ console.debug(message, ...args);
198
+ }
199
+ }
200
+ info(message, ...args) {
201
+ if (this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) {
202
+ console.info(message, ...args);
203
+ }
204
+ }
205
+ warn(message, ...args) {
206
+ if (this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) {
207
+ console.warn(message, ...args);
208
+ }
209
+ }
210
+ error(message, ...args) {
211
+ if (this.level === LogLevel.ERROR || this.level === LogLevel.WARN || this.level === LogLevel.INFO || this.level === LogLevel.DEBUG) {
212
+ console.error(message, ...args);
213
+ }
214
+ }
215
+ async getLogs(_transportId, _params) {
216
+ return { logs: [], total: 0, page: _params?.page ?? 1, perPage: _params?.perPage ?? 100, hasMore: false };
217
+ }
218
+ async getLogsByRunId(_args) {
219
+ return { logs: [], total: 0, page: _args.page ?? 1, perPage: _args.perPage ?? 100, hasMore: false };
220
+ }
221
+ };
222
+
223
+ // ../../packages/core/dist/chunk-5IEKR756.js
224
+ var MastraBase = class {
225
+ component = RegisteredLogger.LLM;
226
+ logger;
227
+ name;
228
+ telemetry;
229
+ constructor({ component, name }) {
230
+ this.component = component || RegisteredLogger.LLM;
231
+ this.name = name;
232
+ this.logger = new ConsoleLogger({ name: `${this.component} - ${this.name}` });
233
+ }
234
+ /**
235
+ * Set the logger for the agent
236
+ * @param logger
237
+ */
238
+ __setLogger(logger) {
239
+ this.logger = logger;
240
+ if (this.component !== RegisteredLogger.LLM) {
241
+ this.logger.debug(`Logger updated [component=${this.component}] [name=${this.name}]`);
242
+ }
243
+ }
244
+ /**
245
+ * Set the telemetry for the
246
+ * @param telemetry
247
+ */
248
+ __setTelemetry(telemetry) {
249
+ this.telemetry = telemetry;
250
+ if (this.component !== RegisteredLogger.LLM) {
251
+ this.logger.debug(`Telemetry updated [component=${this.component}] [name=${this.telemetry.name}]`);
252
+ }
253
+ }
254
+ /**
255
+ * Get the telemetry on the vector
256
+ * @returns telemetry
257
+ */
258
+ __getTelemetry() {
259
+ return this.telemetry;
260
+ }
261
+ /*
262
+ get experimental_telemetry config
263
+ */
264
+ get experimental_telemetry() {
265
+ return this.telemetry ? {
266
+ // tracer: this.telemetry.tracer,
267
+ tracer: this.telemetry.getBaggageTracer(),
268
+ isEnabled: !!this.telemetry.tracer
269
+ } : void 0;
270
+ }
271
+ };
272
+
273
+ // ../../packages/core/dist/chunk-C6A6W6XS.js
274
+ var __create = Object.create;
275
+ var __defProp = Object.defineProperty;
276
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
277
+ var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : Symbol.for("Symbol." + name);
278
+ var __typeError = (msg) => {
279
+ throw TypeError(msg);
280
+ };
281
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, {
282
+ enumerable: true,
283
+ configurable: true,
284
+ writable: true,
285
+ value
286
+ }) : obj[key] = value;
287
+ var __name = (target, value) => __defProp(target, "name", {
288
+ value,
289
+ configurable: true
290
+ });
291
+ var __decoratorStart = (base) => [, , , __create(base?.[__knownSymbol("metadata")] ?? null)];
292
+ var __decoratorStrings = ["class", "method", "getter", "setter", "accessor", "field", "value", "get", "set"];
293
+ var __expectFn = (fn) => fn !== void 0 && typeof fn !== "function" ? __typeError("Function expected") : fn;
294
+ var __decoratorContext = (kind, name, done, metadata, fns) => ({
295
+ kind: __decoratorStrings[kind],
296
+ name,
297
+ metadata,
298
+ addInitializer: (fn) => done._ ? __typeError("Already initialized") : fns.push(__expectFn(fn || null))
299
+ });
300
+ var __decoratorMetadata = (array, target) => __defNormalProp(target, __knownSymbol("metadata"), array[3]);
301
+ var __runInitializers = (array, flags, self, value) => {
302
+ for (var i = 0, fns = array[flags >> 1], n = fns && fns.length; i < n; i++) fns[i].call(self) ;
303
+ return value;
304
+ };
305
+ var __decorateElement = (array, flags, name, decorators, target, extra) => {
306
+ var it, done, ctx, k = flags & 7, p = false;
307
+ var j = 0;
308
+ var extraInitializers = array[j] || (array[j] = []);
309
+ var desc = k && ((target = target.prototype), k < 5 && (k > 3 || !p) && __getOwnPropDesc(target , name));
310
+ __name(target, name);
311
+ for (var i = decorators.length - 1; i >= 0; i--) {
312
+ ctx = __decoratorContext(k, name, done = {}, array[3], extraInitializers);
313
+ it = (0, decorators[i])(target, ctx), done._ = 1;
314
+ __expectFn(it) && (target = it);
315
+ }
316
+ return __decoratorMetadata(array, target), desc && __defProp(target, name, desc), p ? k ^ 4 ? extra : desc : target;
317
+ };
318
+
319
+ // ../../packages/core/dist/server/index.js
320
+ var _MastraAuthProvider_decorators;
321
+ var _init;
322
+ var _a;
323
+ _MastraAuthProvider_decorators = [InstrumentClass({
324
+ prefix: "auth",
325
+ excludeMethods: ["__setTools", "__setLogger", "__setTelemetry", "#log"]
326
+ })];
327
+ var MastraAuthProvider = class extends (_a = MastraBase) {
328
+ constructor(options) {
329
+ super({
330
+ component: "AUTH",
331
+ name: options?.name
332
+ });
333
+ if (options?.authorizeUser) {
334
+ this.authorizeUser = options.authorizeUser.bind(this);
335
+ }
336
+ }
337
+ registerOptions(opts) {
338
+ if (opts?.authorizeUser) {
339
+ this.authorizeUser = opts.authorizeUser.bind(this);
340
+ }
341
+ }
342
+ };
343
+ MastraAuthProvider = /* @__PURE__ */ ((_) => {
344
+ _init = __decoratorStart(_a);
345
+ MastraAuthProvider = __decorateElement(_init, 0, "MastraAuthProvider", _MastraAuthProvider_decorators, MastraAuthProvider);
346
+ __runInitializers(_init, 1, MastraAuthProvider);
347
+ return MastraAuthProvider;
348
+ })();
349
+ var MastraAuthSupabase = class extends MastraAuthProvider {
350
+ supabase;
351
+ constructor(options) {
352
+ super({ name: options?.name ?? "supabase" });
353
+ const supabaseUrl = options?.url ?? process.env.SUPABASE_URL;
354
+ const supabaseAnonKey = options?.anonKey ?? process.env.SUPABASE_ANON_KEY;
355
+ if (!supabaseUrl || !supabaseAnonKey) {
356
+ throw new Error(
357
+ "Supabase URL and anon key are required, please provide them in the options or set the environment variables SUPABASE_URL and SUPABASE_ANON_KEY"
358
+ );
359
+ }
360
+ this.supabase = createClient(supabaseUrl, supabaseAnonKey);
361
+ this.registerOptions(options);
362
+ }
363
+ async authenticateToken(token) {
364
+ const { data, error } = await this.supabase.auth.getUser(token);
365
+ if (error) {
366
+ return null;
367
+ }
368
+ return data.user;
369
+ }
370
+ async authorizeUser(user) {
371
+ const { data, error } = await this.supabase.from("users").select("isAdmin").eq("id", user?.id).single();
372
+ if (error) {
373
+ return false;
374
+ }
375
+ const isAdmin = data?.isAdmin;
376
+ return isAdmin;
377
+ }
378
+ };
379
+
380
+ export { MastraAuthSupabase };
@@ -0,0 +1,6 @@
1
+ import { createConfig } from '@internal/lint/eslint';
2
+
3
+ const config = await createConfig();
4
+
5
+ /** @type {import("eslint").Linter.Config[]} */
6
+ export default [...config];
package/package.json ADDED
@@ -0,0 +1,40 @@
1
+ {
2
+ "name": "@mastra/auth-supabase",
3
+ "version": "0.0.0-fix-generate-title-20250616171351",
4
+ "description": "Mastra Supabase Auth integration",
5
+ "type": "module",
6
+ "main": "dist/index.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "import": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "require": {
15
+ "types": "./dist/index.d.cts",
16
+ "default": "./dist/index.cjs"
17
+ }
18
+ },
19
+ "./package.json": "./package.json"
20
+ },
21
+ "license": "Elastic-2.0",
22
+ "dependencies": {
23
+ "@supabase/supabase-js": "^2.50.0"
24
+ },
25
+ "devDependencies": {
26
+ "@types/node": "^20.19.0",
27
+ "eslint": "^9.28.0",
28
+ "tsup": "^8.5.0",
29
+ "typescript": "^5.8.3",
30
+ "vitest": "^2.1.9",
31
+ "@internal/lint": "0.0.0-fix-generate-title-20250616171351",
32
+ "@mastra/core": "0.0.0-fix-generate-title-20250616171351"
33
+ },
34
+ "scripts": {
35
+ "build": "tsup src/index.ts --format esm,cjs --experimental-dts --clean --treeshake",
36
+ "build:watch": "pnpm build --watch",
37
+ "test": "vitest run",
38
+ "lint": "eslint ."
39
+ }
40
+ }
@@ -0,0 +1,152 @@
1
+ import { createClient } from '@supabase/supabase-js';
2
+ import type { User } from '@supabase/supabase-js';
3
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
4
+ import { MastraAuthSupabase } from './index';
5
+
6
+ // Mock Supabase client
7
+ vi.mock('@supabase/supabase-js', () => ({
8
+ createClient: vi.fn(),
9
+ }));
10
+
11
+ describe('MastraAuthSupabase', () => {
12
+ const mockSupabaseUrl = 'https://test.supabase.co';
13
+ const mockSupabaseAnonKey = 'test-anon-key';
14
+ const mockUser: User = {
15
+ id: 'test-user-id',
16
+ email: 'test@example.com',
17
+ created_at: '',
18
+ aud: '',
19
+ role: '',
20
+ app_metadata: {},
21
+ user_metadata: {},
22
+ };
23
+
24
+ let authProvider: MastraAuthSupabase;
25
+ let mockSupabaseClient: any;
26
+
27
+ beforeEach(() => {
28
+ // Reset environment variables
29
+ vi.resetModules();
30
+ process.env.SUPABASE_URL = mockSupabaseUrl;
31
+ process.env.SUPABASE_ANON_KEY = mockSupabaseAnonKey;
32
+
33
+ // Setup mock Supabase client
34
+ mockSupabaseClient = {
35
+ auth: {
36
+ getUser: vi.fn(),
37
+ },
38
+ from: vi.fn().mockReturnThis(),
39
+ select: vi.fn().mockReturnThis(),
40
+ eq: vi.fn().mockReturnThis(),
41
+ single: vi.fn(),
42
+ };
43
+
44
+ (createClient as any).mockReturnValue(mockSupabaseClient);
45
+ authProvider = new MastraAuthSupabase();
46
+ });
47
+
48
+ describe('constructor', () => {
49
+ it('should create instance with environment variables', () => {
50
+ expect(createClient).toHaveBeenCalledWith(mockSupabaseUrl, mockSupabaseAnonKey);
51
+ });
52
+
53
+ it('should create instance with provided options', () => {
54
+ const customUrl = 'https://custom.supabase.co';
55
+ const customKey = 'custom-key';
56
+ new MastraAuthSupabase({ url: customUrl, anonKey: customKey });
57
+ expect(createClient).toHaveBeenCalledWith(customUrl, customKey);
58
+ });
59
+
60
+ it('should throw error when required credentials are missing', () => {
61
+ delete process.env.SUPABASE_URL;
62
+ delete process.env.SUPABASE_ANON_KEY;
63
+
64
+ expect(() => new MastraAuthSupabase()).toThrow('Supabase URL and anon key are required');
65
+ });
66
+ });
67
+
68
+ describe('authenticateToken', () => {
69
+ it('should return user when token is valid', async () => {
70
+ const mockToken = 'valid-token';
71
+ mockSupabaseClient.auth.getUser.mockResolvedValue({
72
+ data: { user: mockUser },
73
+ error: null,
74
+ });
75
+
76
+ const result = await authProvider.authenticateToken(mockToken);
77
+ expect(result).toEqual(mockUser);
78
+ expect(mockSupabaseClient.auth.getUser).toHaveBeenCalledWith(mockToken);
79
+ });
80
+
81
+ it('should return null when token is invalid', async () => {
82
+ const mockToken = 'invalid-token';
83
+ mockSupabaseClient.auth.getUser.mockResolvedValue({
84
+ data: { user: null },
85
+ error: new Error('Invalid token'),
86
+ });
87
+
88
+ const result = await authProvider.authenticateToken(mockToken);
89
+ expect(result).toBeNull();
90
+ });
91
+ });
92
+
93
+ describe('authorizeUser', () => {
94
+ it('should return true for admin users', async () => {
95
+ mockSupabaseClient.single.mockResolvedValue({
96
+ data: { isAdmin: true },
97
+ error: null,
98
+ });
99
+
100
+ const result = await authProvider.authorizeUser(mockUser);
101
+ expect(result).toBe(true);
102
+ expect(mockSupabaseClient.from).toHaveBeenCalledWith('users');
103
+ expect(mockSupabaseClient.select).toHaveBeenCalledWith('isAdmin');
104
+ expect(mockSupabaseClient.eq).toHaveBeenCalledWith('id', mockUser.id);
105
+ });
106
+
107
+ it('should return false for non-admin users', async () => {
108
+ mockSupabaseClient.single.mockResolvedValue({
109
+ data: { isAdmin: false },
110
+ error: null,
111
+ });
112
+
113
+ const result = await authProvider.authorizeUser(mockUser);
114
+ expect(result).toBe(false);
115
+ });
116
+
117
+ it('should return false when user data cannot be retrieved', async () => {
118
+ mockSupabaseClient.single.mockResolvedValue({
119
+ data: null,
120
+ error: new Error('Database error'),
121
+ });
122
+
123
+ const result = await authProvider.authorizeUser(mockUser);
124
+ expect(result).toBe(false);
125
+ });
126
+ });
127
+
128
+ it('can be overridden with custom authorization logic', async () => {
129
+ // class CustomSupabase extends MastraAuthSupabase {
130
+
131
+ // }
132
+
133
+ const supabase = new MastraAuthSupabase({
134
+ async authorizeUser(user: any): Promise<boolean> {
135
+ // Custom authorization logic that checks for specific permissions
136
+ return user?.permissions?.includes('admin') ?? false;
137
+ },
138
+ });
139
+
140
+ // Test with admin user
141
+ const adminUser = { sub: 'user123', permissions: ['admin'] } as unknown as User;
142
+ expect(await supabase.authorizeUser(adminUser)).toBe(true);
143
+
144
+ // Test with non-admin user
145
+ const regularUser = { sub: 'user456', permissions: ['read'] } as unknown as User;
146
+ expect(await supabase.authorizeUser(regularUser)).toBe(false);
147
+
148
+ // Test with user without permissions
149
+ const noPermissionsUser = { sub: 'user789' } as unknown as User;
150
+ expect(await supabase.authorizeUser(noPermissionsUser)).toBe(false);
151
+ });
152
+ });
package/src/index.ts ADDED
@@ -0,0 +1,55 @@
1
+ import type { MastraAuthProviderOptions } from '@mastra/core/server';
2
+ import { MastraAuthProvider } from '@mastra/core/server';
3
+
4
+ import { createClient } from '@supabase/supabase-js';
5
+ import type { SupabaseClient, User } from '@supabase/supabase-js';
6
+
7
+ interface MastraAuthSupabaseOptions extends MastraAuthProviderOptions<User> {
8
+ url?: string;
9
+ anonKey?: string;
10
+ }
11
+
12
+ export class MastraAuthSupabase extends MastraAuthProvider<User> {
13
+ protected supabase: SupabaseClient;
14
+
15
+ constructor(options?: MastraAuthSupabaseOptions) {
16
+ super({ name: options?.name ?? 'supabase' });
17
+
18
+ const supabaseUrl = options?.url ?? process.env.SUPABASE_URL;
19
+ const supabaseAnonKey = options?.anonKey ?? process.env.SUPABASE_ANON_KEY;
20
+
21
+ if (!supabaseUrl || !supabaseAnonKey) {
22
+ throw new Error(
23
+ 'Supabase URL and anon key are required, please provide them in the options or set the environment variables SUPABASE_URL and SUPABASE_ANON_KEY',
24
+ );
25
+ }
26
+
27
+ this.supabase = createClient(supabaseUrl, supabaseAnonKey);
28
+
29
+ this.registerOptions(options);
30
+ }
31
+
32
+ async authenticateToken(token: string): Promise<User | null> {
33
+ const { data, error } = await this.supabase.auth.getUser(token);
34
+
35
+ if (error) {
36
+ return null;
37
+ }
38
+
39
+ return data.user;
40
+ }
41
+
42
+ async authorizeUser(user: User) {
43
+ // Get user data from Supabase
44
+ const { data, error } = await this.supabase.from('users').select('isAdmin').eq('id', user?.id).single();
45
+
46
+ if (error) {
47
+ return false;
48
+ }
49
+
50
+ const isAdmin = data?.isAdmin;
51
+
52
+ // Check permissions based on role
53
+ return isAdmin;
54
+ }
55
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,5 @@
1
+ {
2
+ "extends": "../../tsconfig.node.json",
3
+ "include": ["src/**/*"],
4
+ "exclude": ["node_modules", "**/*.test.ts"]
5
+ }
@@ -0,0 +1,8 @@
1
+ import { defineConfig } from 'vitest/config';
2
+
3
+ export default defineConfig({
4
+ test: {
5
+ globals: true,
6
+ include: ['src/**/*.test.ts'],
7
+ },
8
+ });