@aurabase/aurabase-js 0.5.2 → 0.5.4
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/dist/{AuraClient-DL7mqfNu.d.cts → AuraClient-5jDiXjrO.d.cts} +27 -3
- package/dist/{AuraClient-DL7mqfNu.d.ts → AuraClient-5jDiXjrO.d.ts} +27 -3
- package/dist/index.cjs +26 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +26 -1
- package/dist/nextjs.cjs +389 -0
- package/dist/nextjs.d.cts +126 -0
- package/dist/nextjs.d.ts +126 -0
- package/dist/nextjs.js +383 -0
- package/dist/react.cjs +150 -0
- package/dist/react.d.cts +82 -0
- package/dist/react.d.ts +82 -0
- package/dist/react.js +143 -0
- package/dist/ssr.cjs +26 -1
- package/dist/ssr.d.cts +1 -1
- package/dist/ssr.d.ts +1 -1
- package/dist/ssr.js +26 -1
- package/package.json +29 -9
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AiService } from '@aurabase/ai';
|
|
2
2
|
import { AuthService, AuthAdminService } from '@aurabase/auth';
|
|
3
3
|
import { AuraClientLike, BaseAuthStore, AuraObservabilityEvent, AuraClientOptions, ChannelConfig } from '@aurabase/core';
|
|
4
|
-
import { DatabaseService } from '@aurabase/db';
|
|
4
|
+
import { GenericSchema, DatabaseService, AuraQueryBuilder, AuraClientOptionsT } from '@aurabase/db';
|
|
5
5
|
import { FunctionsService } from '@aurabase/functions';
|
|
6
6
|
import { NotificationsService } from '@aurabase/notifications';
|
|
7
7
|
import { RealtimeService, AuraChannel } from '@aurabase/realtime';
|
|
@@ -23,7 +23,9 @@ import { StorageService } from '@aurabase/storage';
|
|
|
23
23
|
* const { data } = await aura.db.from('posts').eq('published', true)
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
declare class AuraClient<Database = any
|
|
26
|
+
declare class AuraClient<Database = any, Schema extends GenericSchema = Database extends {
|
|
27
|
+
public: infer S;
|
|
28
|
+
} ? S extends GenericSchema ? S : any : any> implements AuraClientLike {
|
|
27
29
|
/** URL du projet (`https://<slug>.aurabase.cloud`), sans barre finale. */
|
|
28
30
|
readonly baseUrl: string;
|
|
29
31
|
readonly apiKey: string | null;
|
|
@@ -64,12 +66,34 @@ declare class AuraClient<Database = any> implements AuraClientLike {
|
|
|
64
66
|
dispose(): void;
|
|
65
67
|
get auth(): AuthService;
|
|
66
68
|
get authAdmin(): AuthAdminService;
|
|
67
|
-
get db(): DatabaseService<Database>;
|
|
69
|
+
get db(): DatabaseService<Database, Schema>;
|
|
68
70
|
get storage(): StorageService;
|
|
69
71
|
get realtime(): RealtimeService;
|
|
70
72
|
get functions(): FunctionsService;
|
|
71
73
|
get ai(): AiService;
|
|
72
74
|
get notifications(): NotificationsService;
|
|
75
|
+
/**
|
|
76
|
+
* Shortcut: query a database table or view (Supabase-compatible API).
|
|
77
|
+
* Equivalent to `aura.db.from(table)`.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* const { data, error } = await aura.from('posts').select('*').limit(10)
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
from<TableName extends string & keyof Schema['Tables'], Table extends Schema['Tables'][TableName]>(table: TableName): AuraQueryBuilder<Schema, Table, TableName, AuraClientOptionsT>;
|
|
85
|
+
from<ViewName extends string & keyof Schema['Views'], View extends Schema['Views'][ViewName]>(view: ViewName): AuraQueryBuilder<Schema, View, ViewName, AuraClientOptionsT>;
|
|
86
|
+
from(table: string): AuraQueryBuilder<any, any, any, AuraClientOptionsT>;
|
|
87
|
+
/**
|
|
88
|
+
* Shortcut: call a stored procedure / PostgreSQL function via RPC (Supabase-compatible API).
|
|
89
|
+
* Equivalent to `aura.db.rpc(fn, args, options)`.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* const { data, error } = await aura.rpc('echo_test', { message: 'hello' })
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
rpc<FnName extends string = string, Args extends Record<string, unknown> = Record<string, unknown>>(fn: FnName, args?: Args, options?: Parameters<DatabaseService<Database, Schema>['rpc']>[2]): ReturnType<DatabaseService<Database, Schema>['rpc']>;
|
|
73
97
|
/**
|
|
74
98
|
* Shortcut: create a realtime channel with Supabase-compatible API.
|
|
75
99
|
* Equivalent to `aura.realtime.channel(name)`.
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AiService } from '@aurabase/ai';
|
|
2
2
|
import { AuthService, AuthAdminService } from '@aurabase/auth';
|
|
3
3
|
import { AuraClientLike, BaseAuthStore, AuraObservabilityEvent, AuraClientOptions, ChannelConfig } from '@aurabase/core';
|
|
4
|
-
import { DatabaseService } from '@aurabase/db';
|
|
4
|
+
import { GenericSchema, DatabaseService, AuraQueryBuilder, AuraClientOptionsT } from '@aurabase/db';
|
|
5
5
|
import { FunctionsService } from '@aurabase/functions';
|
|
6
6
|
import { NotificationsService } from '@aurabase/notifications';
|
|
7
7
|
import { RealtimeService, AuraChannel } from '@aurabase/realtime';
|
|
@@ -23,7 +23,9 @@ import { StorageService } from '@aurabase/storage';
|
|
|
23
23
|
* const { data } = await aura.db.from('posts').eq('published', true)
|
|
24
24
|
* ```
|
|
25
25
|
*/
|
|
26
|
-
declare class AuraClient<Database = any
|
|
26
|
+
declare class AuraClient<Database = any, Schema extends GenericSchema = Database extends {
|
|
27
|
+
public: infer S;
|
|
28
|
+
} ? S extends GenericSchema ? S : any : any> implements AuraClientLike {
|
|
27
29
|
/** URL du projet (`https://<slug>.aurabase.cloud`), sans barre finale. */
|
|
28
30
|
readonly baseUrl: string;
|
|
29
31
|
readonly apiKey: string | null;
|
|
@@ -64,12 +66,34 @@ declare class AuraClient<Database = any> implements AuraClientLike {
|
|
|
64
66
|
dispose(): void;
|
|
65
67
|
get auth(): AuthService;
|
|
66
68
|
get authAdmin(): AuthAdminService;
|
|
67
|
-
get db(): DatabaseService<Database>;
|
|
69
|
+
get db(): DatabaseService<Database, Schema>;
|
|
68
70
|
get storage(): StorageService;
|
|
69
71
|
get realtime(): RealtimeService;
|
|
70
72
|
get functions(): FunctionsService;
|
|
71
73
|
get ai(): AiService;
|
|
72
74
|
get notifications(): NotificationsService;
|
|
75
|
+
/**
|
|
76
|
+
* Shortcut: query a database table or view (Supabase-compatible API).
|
|
77
|
+
* Equivalent to `aura.db.from(table)`.
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* const { data, error } = await aura.from('posts').select('*').limit(10)
|
|
82
|
+
* ```
|
|
83
|
+
*/
|
|
84
|
+
from<TableName extends string & keyof Schema['Tables'], Table extends Schema['Tables'][TableName]>(table: TableName): AuraQueryBuilder<Schema, Table, TableName, AuraClientOptionsT>;
|
|
85
|
+
from<ViewName extends string & keyof Schema['Views'], View extends Schema['Views'][ViewName]>(view: ViewName): AuraQueryBuilder<Schema, View, ViewName, AuraClientOptionsT>;
|
|
86
|
+
from(table: string): AuraQueryBuilder<any, any, any, AuraClientOptionsT>;
|
|
87
|
+
/**
|
|
88
|
+
* Shortcut: call a stored procedure / PostgreSQL function via RPC (Supabase-compatible API).
|
|
89
|
+
* Equivalent to `aura.db.rpc(fn, args, options)`.
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* ```ts
|
|
93
|
+
* const { data, error } = await aura.rpc('echo_test', { message: 'hello' })
|
|
94
|
+
* ```
|
|
95
|
+
*/
|
|
96
|
+
rpc<FnName extends string = string, Args extends Record<string, unknown> = Record<string, unknown>>(fn: FnName, args?: Args, options?: Parameters<DatabaseService<Database, Schema>['rpc']>[2]): ReturnType<DatabaseService<Database, Schema>['rpc']>;
|
|
73
97
|
/**
|
|
74
98
|
* Shortcut: create a realtime channel with Supabase-compatible API.
|
|
75
99
|
* Equivalent to `aura.realtime.channel(name)`.
|
package/dist/index.cjs
CHANGED
|
@@ -63,6 +63,11 @@ var AuraClient = class {
|
|
|
63
63
|
"[aurabase] No API key provided. Most operations require an API key (apikey header). Only public auth routes (register, login, refresh) will work without one."
|
|
64
64
|
);
|
|
65
65
|
}
|
|
66
|
+
if (typeof console !== "undefined" && /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?\/?$/.test(this.baseUrl)) {
|
|
67
|
+
console.warn(
|
|
68
|
+
"[aurabase] Attention : en local, l'URL du projet doit inclure le sous-domaine (ex: http://<slug>.localhost:8080) pour permettre la r\xE9solution automatique du projet par la passerelle."
|
|
69
|
+
);
|
|
70
|
+
}
|
|
66
71
|
if (this.apiKey?.startsWith(SERVICE_ROLE_KEY_PREFIX) && isBrowserContext()) {
|
|
67
72
|
const refuse = resolvedOptions?.refuseServiceRoleInBrowser ?? true;
|
|
68
73
|
const message = "[aurabase] S\xC9CURIT\xC9 : une cl\xE9 service_role (aura_sk_\u2026) est fournie \xE0 createClient() dans un contexte navigateur. Cette cl\xE9 \xE0 privil\xE8ges \xE9lev\xE9s NE DOIT JAMAIS \xEAtre expos\xE9e c\xF4t\xE9 client (elle fuiterait dans le bundle). Utilisez une cl\xE9 anon (aura_anon_\u2026) c\xF4t\xE9 client, et createAdminClient() c\xF4t\xE9 serveur pour les op\xE9rations d'administration.";
|
|
@@ -76,7 +81,12 @@ var AuraClient = class {
|
|
|
76
81
|
this.authStore = resolvedOptions.auth.storage;
|
|
77
82
|
} else if (resolvedOptions?.auth?.persistSession === false) {
|
|
78
83
|
this.authStore = new core.BaseAuthStore();
|
|
79
|
-
} else if (typeof localStorage !== "undefined") {
|
|
84
|
+
} else if (isBrowserContext() && typeof window.localStorage !== "undefined" || typeof globalThis !== "undefined" && (() => {
|
|
85
|
+
const g = globalThis;
|
|
86
|
+
const proc = g?.process;
|
|
87
|
+
const isTest = !!(proc?.env?.VITEST || proc?.env?.NODE_ENV === "test" || proc?.env?.JEST_WORKER_ID);
|
|
88
|
+
return isTest && !!g?.localStorage && typeof g.localStorage.getItem === "function";
|
|
89
|
+
})()) {
|
|
80
90
|
this.authStore = new core.LocalAuthStore(`aura-${core.clientScope(this.baseUrl)}-auth`);
|
|
81
91
|
} else {
|
|
82
92
|
this.authStore = new core.BaseAuthStore();
|
|
@@ -153,6 +163,21 @@ var AuraClient = class {
|
|
|
153
163
|
if (!this._notifications) this._notifications = new notifications.NotificationsService(this);
|
|
154
164
|
return this._notifications;
|
|
155
165
|
}
|
|
166
|
+
from(table) {
|
|
167
|
+
return this.db.from(table);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Shortcut: call a stored procedure / PostgreSQL function via RPC (Supabase-compatible API).
|
|
171
|
+
* Equivalent to `aura.db.rpc(fn, args, options)`.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```ts
|
|
175
|
+
* const { data, error } = await aura.rpc('echo_test', { message: 'hello' })
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
rpc(fn, args, options) {
|
|
179
|
+
return this.db.rpc(fn, args, options);
|
|
180
|
+
}
|
|
156
181
|
/**
|
|
157
182
|
* Shortcut: create a realtime channel with Supabase-compatible API.
|
|
158
183
|
* Equivalent to `aura.realtime.channel(name)`.
|
package/dist/index.d.cts
CHANGED
|
@@ -6,8 +6,8 @@ export { DatabaseService, QueryBuilder } from '@aurabase/db';
|
|
|
6
6
|
export { FunctionsService } from '@aurabase/functions';
|
|
7
7
|
export { NotificationsAdminService, NotificationsService } from '@aurabase/notifications';
|
|
8
8
|
export { AuraChannel, RealtimeService } from '@aurabase/realtime';
|
|
9
|
-
export { StorageService } from '@aurabase/storage';
|
|
10
|
-
import { A as AuraClient } from './AuraClient-
|
|
9
|
+
export { StorageBucketClient, StorageService } from '@aurabase/storage';
|
|
10
|
+
import { A as AuraClient } from './AuraClient-5jDiXjrO.cjs';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Create a new Aurabase client instance.
|
package/dist/index.d.ts
CHANGED
|
@@ -6,8 +6,8 @@ export { DatabaseService, QueryBuilder } from '@aurabase/db';
|
|
|
6
6
|
export { FunctionsService } from '@aurabase/functions';
|
|
7
7
|
export { NotificationsAdminService, NotificationsService } from '@aurabase/notifications';
|
|
8
8
|
export { AuraChannel, RealtimeService } from '@aurabase/realtime';
|
|
9
|
-
export { StorageService } from '@aurabase/storage';
|
|
10
|
-
import { A as AuraClient } from './AuraClient-
|
|
9
|
+
export { StorageBucketClient, StorageService } from '@aurabase/storage';
|
|
10
|
+
import { A as AuraClient } from './AuraClient-5jDiXjrO.js';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Create a new Aurabase client instance.
|
package/dist/index.js
CHANGED
|
@@ -69,6 +69,11 @@ var AuraClient = class {
|
|
|
69
69
|
"[aurabase] No API key provided. Most operations require an API key (apikey header). Only public auth routes (register, login, refresh) will work without one."
|
|
70
70
|
);
|
|
71
71
|
}
|
|
72
|
+
if (typeof console !== "undefined" && /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?\/?$/.test(this.baseUrl)) {
|
|
73
|
+
console.warn(
|
|
74
|
+
"[aurabase] Attention : en local, l'URL du projet doit inclure le sous-domaine (ex: http://<slug>.localhost:8080) pour permettre la r\xE9solution automatique du projet par la passerelle."
|
|
75
|
+
);
|
|
76
|
+
}
|
|
72
77
|
if (this.apiKey?.startsWith(SERVICE_ROLE_KEY_PREFIX) && isBrowserContext()) {
|
|
73
78
|
const refuse = resolvedOptions?.refuseServiceRoleInBrowser ?? true;
|
|
74
79
|
const message = "[aurabase] S\xC9CURIT\xC9 : une cl\xE9 service_role (aura_sk_\u2026) est fournie \xE0 createClient() dans un contexte navigateur. Cette cl\xE9 \xE0 privil\xE8ges \xE9lev\xE9s NE DOIT JAMAIS \xEAtre expos\xE9e c\xF4t\xE9 client (elle fuiterait dans le bundle). Utilisez une cl\xE9 anon (aura_anon_\u2026) c\xF4t\xE9 client, et createAdminClient() c\xF4t\xE9 serveur pour les op\xE9rations d'administration.";
|
|
@@ -82,7 +87,12 @@ var AuraClient = class {
|
|
|
82
87
|
this.authStore = resolvedOptions.auth.storage;
|
|
83
88
|
} else if (resolvedOptions?.auth?.persistSession === false) {
|
|
84
89
|
this.authStore = new BaseAuthStore();
|
|
85
|
-
} else if (typeof localStorage !== "undefined") {
|
|
90
|
+
} else if (isBrowserContext() && typeof window.localStorage !== "undefined" || typeof globalThis !== "undefined" && (() => {
|
|
91
|
+
const g = globalThis;
|
|
92
|
+
const proc = g?.process;
|
|
93
|
+
const isTest = !!(proc?.env?.VITEST || proc?.env?.NODE_ENV === "test" || proc?.env?.JEST_WORKER_ID);
|
|
94
|
+
return isTest && !!g?.localStorage && typeof g.localStorage.getItem === "function";
|
|
95
|
+
})()) {
|
|
86
96
|
this.authStore = new LocalAuthStore(`aura-${clientScope(this.baseUrl)}-auth`);
|
|
87
97
|
} else {
|
|
88
98
|
this.authStore = new BaseAuthStore();
|
|
@@ -159,6 +169,21 @@ var AuraClient = class {
|
|
|
159
169
|
if (!this._notifications) this._notifications = new NotificationsService(this);
|
|
160
170
|
return this._notifications;
|
|
161
171
|
}
|
|
172
|
+
from(table) {
|
|
173
|
+
return this.db.from(table);
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* Shortcut: call a stored procedure / PostgreSQL function via RPC (Supabase-compatible API).
|
|
177
|
+
* Equivalent to `aura.db.rpc(fn, args, options)`.
|
|
178
|
+
*
|
|
179
|
+
* @example
|
|
180
|
+
* ```ts
|
|
181
|
+
* const { data, error } = await aura.rpc('echo_test', { message: 'hello' })
|
|
182
|
+
* ```
|
|
183
|
+
*/
|
|
184
|
+
rpc(fn, args, options) {
|
|
185
|
+
return this.db.rpc(fn, args, options);
|
|
186
|
+
}
|
|
162
187
|
/**
|
|
163
188
|
* Shortcut: create a realtime channel with Supabase-compatible API.
|
|
164
189
|
* Equivalent to `aura.realtime.channel(name)`.
|
package/dist/nextjs.cjs
ADDED
|
@@ -0,0 +1,389 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var core = require('@aurabase/core');
|
|
4
|
+
var ai = require('@aurabase/ai');
|
|
5
|
+
var auth$1 = require('@aurabase/auth');
|
|
6
|
+
var db = require('@aurabase/db');
|
|
7
|
+
var functions = require('@aurabase/functions');
|
|
8
|
+
var notifications = require('@aurabase/notifications');
|
|
9
|
+
var realtime = require('@aurabase/realtime');
|
|
10
|
+
var storage = require('@aurabase/storage');
|
|
11
|
+
|
|
12
|
+
// src/ssr.ts
|
|
13
|
+
function isBrowserContext() {
|
|
14
|
+
if (typeof window !== "undefined") return true;
|
|
15
|
+
const g = globalThis;
|
|
16
|
+
if (typeof g.DedicatedWorkerGlobalScope !== "undefined") return true;
|
|
17
|
+
if (typeof g.SharedWorkerGlobalScope !== "undefined") return true;
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
var SERVICE_ROLE_KEY_PREFIX = "aura_sk_";
|
|
21
|
+
var AuraClient = class {
|
|
22
|
+
/** URL du projet (`https://<slug>.aurabase.cloud`), sans barre finale. */
|
|
23
|
+
baseUrl;
|
|
24
|
+
apiKey;
|
|
25
|
+
fetchFn;
|
|
26
|
+
authStore;
|
|
27
|
+
retryConfig;
|
|
28
|
+
/** Timeout par défaut (ms) des requêtes JSON sans signal. `undefined` → défaut core (30s). */
|
|
29
|
+
requestTimeoutMs;
|
|
30
|
+
/** Hook d'observabilité (LOT 3) — voir `AuraClientOptions.onEvent`. */
|
|
31
|
+
onEvent;
|
|
32
|
+
/** Journalise chaque `AuraObservabilityEvent` via `console.debug` — voir `AuraClientOptions.debug`. */
|
|
33
|
+
debug;
|
|
34
|
+
// Lazy-initialised service instances
|
|
35
|
+
_auth = null;
|
|
36
|
+
_db = null;
|
|
37
|
+
_storage = null;
|
|
38
|
+
_realtime = null;
|
|
39
|
+
_functions = null;
|
|
40
|
+
_ai = null;
|
|
41
|
+
_notifications = null;
|
|
42
|
+
_authAdmin = null;
|
|
43
|
+
_disposed = false;
|
|
44
|
+
_persistSession;
|
|
45
|
+
_autoRefresh;
|
|
46
|
+
_detectSessionInUrl;
|
|
47
|
+
/**
|
|
48
|
+
* @param baseUrl URL du projet (`https://<slug>.aurabase.cloud`).
|
|
49
|
+
* @param apiKey Clé API du projet (`aura_anon_…`, `aura_auth_…`, `aura_sk_…`).
|
|
50
|
+
*/
|
|
51
|
+
constructor(baseUrl, apiKey, options) {
|
|
52
|
+
this.baseUrl = baseUrl.replace(/\/+$/, "");
|
|
53
|
+
const resolvedOptions = options;
|
|
54
|
+
this.apiKey = apiKey || null;
|
|
55
|
+
this.fetchFn = resolvedOptions?.fetch ?? globalThis.fetch.bind(globalThis);
|
|
56
|
+
const r = resolvedOptions?.retry;
|
|
57
|
+
this.retryConfig = r === false ? { enabled: false, maxRetries: 0 } : r === void 0 || r === true ? { enabled: true, maxRetries: core.DEFAULT_MAX_RETRIES } : { enabled: r.enabled ?? true, maxRetries: r.maxRetries ?? core.DEFAULT_MAX_RETRIES };
|
|
58
|
+
this.requestTimeoutMs = resolvedOptions?.requestTimeoutMs;
|
|
59
|
+
this.onEvent = resolvedOptions?.onEvent;
|
|
60
|
+
this.debug = resolvedOptions?.debug;
|
|
61
|
+
if (!this.apiKey && typeof console !== "undefined") {
|
|
62
|
+
console.warn(
|
|
63
|
+
"[aurabase] No API key provided. Most operations require an API key (apikey header). Only public auth routes (register, login, refresh) will work without one."
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
if (typeof console !== "undefined" && /^https?:\/\/(localhost|127\.0\.0\.1)(:\d+)?\/?$/.test(this.baseUrl)) {
|
|
67
|
+
console.warn(
|
|
68
|
+
"[aurabase] Attention : en local, l'URL du projet doit inclure le sous-domaine (ex: http://<slug>.localhost:8080) pour permettre la r\xE9solution automatique du projet par la passerelle."
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
if (this.apiKey?.startsWith(SERVICE_ROLE_KEY_PREFIX) && isBrowserContext()) {
|
|
72
|
+
const refuse = resolvedOptions?.refuseServiceRoleInBrowser ?? true;
|
|
73
|
+
const message = "[aurabase] S\xC9CURIT\xC9 : une cl\xE9 service_role (aura_sk_\u2026) est fournie \xE0 createClient() dans un contexte navigateur. Cette cl\xE9 \xE0 privil\xE8ges \xE9lev\xE9s NE DOIT JAMAIS \xEAtre expos\xE9e c\xF4t\xE9 client (elle fuiterait dans le bundle). Utilisez une cl\xE9 anon (aura_anon_\u2026) c\xF4t\xE9 client, et createAdminClient() c\xF4t\xE9 serveur pour les op\xE9rations d'administration.";
|
|
74
|
+
if (refuse) {
|
|
75
|
+
throw new Error(message);
|
|
76
|
+
} else if (typeof console !== "undefined") {
|
|
77
|
+
console.warn(message);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
if (resolvedOptions?.auth?.storage) {
|
|
81
|
+
this.authStore = resolvedOptions.auth.storage;
|
|
82
|
+
} else if (resolvedOptions?.auth?.persistSession === false) {
|
|
83
|
+
this.authStore = new core.BaseAuthStore();
|
|
84
|
+
} else if (isBrowserContext() && typeof window.localStorage !== "undefined" || typeof globalThis !== "undefined" && (() => {
|
|
85
|
+
const g = globalThis;
|
|
86
|
+
const proc = g?.process;
|
|
87
|
+
const isTest = !!(proc?.env?.VITEST || proc?.env?.NODE_ENV === "test" || proc?.env?.JEST_WORKER_ID);
|
|
88
|
+
return isTest && !!g?.localStorage && typeof g.localStorage.getItem === "function";
|
|
89
|
+
})()) {
|
|
90
|
+
this.authStore = new core.LocalAuthStore(`aura-${core.clientScope(this.baseUrl)}-auth`);
|
|
91
|
+
} else {
|
|
92
|
+
this.authStore = new core.BaseAuthStore();
|
|
93
|
+
}
|
|
94
|
+
this.authStore.setObservabilityHook(this.onEvent, this.debug);
|
|
95
|
+
this._persistSession = resolvedOptions?.auth?.persistSession !== false;
|
|
96
|
+
this._autoRefresh = resolvedOptions?.auth?.autoRefresh ?? true;
|
|
97
|
+
this._detectSessionInUrl = resolvedOptions?.auth?.detectSessionInUrl;
|
|
98
|
+
if (this._autoRefresh && this._persistSession && typeof window !== "undefined") {
|
|
99
|
+
void this.auth;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Démonte le client : arrête le refresh proactif (ticker + visibilité + BroadcastChannel),
|
|
104
|
+
* déconnecte le realtime, vide les listeners d'auth. Idempotent. À appeler en teardown
|
|
105
|
+
* (React Strict Mode / HMR / tests).
|
|
106
|
+
*/
|
|
107
|
+
dispose() {
|
|
108
|
+
if (this._disposed) return;
|
|
109
|
+
this._disposed = true;
|
|
110
|
+
this._auth?.dispose();
|
|
111
|
+
this._realtime?.disconnect();
|
|
112
|
+
}
|
|
113
|
+
// -- Lazy service getters ---------------------------------------------------
|
|
114
|
+
get auth() {
|
|
115
|
+
if (!this._auth) {
|
|
116
|
+
this._auth = new auth$1.AuthService(this, {
|
|
117
|
+
autoRefresh: this._autoRefresh,
|
|
118
|
+
persistSession: this._persistSession,
|
|
119
|
+
detectSessionInUrl: this._detectSessionInUrl
|
|
120
|
+
});
|
|
121
|
+
this._auth.onAuthStateChange(({ event, accessToken }) => {
|
|
122
|
+
if (this._realtime) {
|
|
123
|
+
if (accessToken) {
|
|
124
|
+
this._realtime.setAuth(accessToken);
|
|
125
|
+
} else if (event === "SIGNED_OUT") {
|
|
126
|
+
this._realtime.setAuth("");
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
});
|
|
130
|
+
}
|
|
131
|
+
return this._auth;
|
|
132
|
+
}
|
|
133
|
+
get authAdmin() {
|
|
134
|
+
if (isBrowserContext()) {
|
|
135
|
+
throw new Error(
|
|
136
|
+
"[aurabase] S\xC9CURIT\xC9 : authAdmin est inaccessible dans un contexte navigateur. L'API admin requiert une cl\xE9 service_role qui ne doit JAMAIS \xEAtre expos\xE9e c\xF4t\xE9 client (elle fuiterait dans le bundle). Utilisez createAdminClient() c\xF4t\xE9 serveur uniquement."
|
|
137
|
+
);
|
|
138
|
+
}
|
|
139
|
+
if (!this._authAdmin) this._authAdmin = new auth$1.AuthAdminService(this);
|
|
140
|
+
return this._authAdmin;
|
|
141
|
+
}
|
|
142
|
+
get db() {
|
|
143
|
+
if (!this._db) this._db = new db.DatabaseService(this);
|
|
144
|
+
return this._db;
|
|
145
|
+
}
|
|
146
|
+
get storage() {
|
|
147
|
+
if (!this._storage) this._storage = new storage.StorageService(this);
|
|
148
|
+
return this._storage;
|
|
149
|
+
}
|
|
150
|
+
get realtime() {
|
|
151
|
+
if (!this._realtime) this._realtime = new realtime.RealtimeService(this);
|
|
152
|
+
return this._realtime;
|
|
153
|
+
}
|
|
154
|
+
get functions() {
|
|
155
|
+
if (!this._functions) this._functions = new functions.FunctionsService(this);
|
|
156
|
+
return this._functions;
|
|
157
|
+
}
|
|
158
|
+
get ai() {
|
|
159
|
+
if (!this._ai) this._ai = new ai.AiService(this);
|
|
160
|
+
return this._ai;
|
|
161
|
+
}
|
|
162
|
+
get notifications() {
|
|
163
|
+
if (!this._notifications) this._notifications = new notifications.NotificationsService(this);
|
|
164
|
+
return this._notifications;
|
|
165
|
+
}
|
|
166
|
+
from(table) {
|
|
167
|
+
return this.db.from(table);
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Shortcut: call a stored procedure / PostgreSQL function via RPC (Supabase-compatible API).
|
|
171
|
+
* Equivalent to `aura.db.rpc(fn, args, options)`.
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* ```ts
|
|
175
|
+
* const { data, error } = await aura.rpc('echo_test', { message: 'hello' })
|
|
176
|
+
* ```
|
|
177
|
+
*/
|
|
178
|
+
rpc(fn, args, options) {
|
|
179
|
+
return this.db.rpc(fn, args, options);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Shortcut: create a realtime channel with Supabase-compatible API.
|
|
183
|
+
* Equivalent to `aura.realtime.channel(name)`.
|
|
184
|
+
*
|
|
185
|
+
* @example
|
|
186
|
+
* ```ts
|
|
187
|
+
* const channel = aura.channel('room-1')
|
|
188
|
+
* .on('postgres_changes', { event: 'INSERT', schema: 'public', table: 'messages' }, cb)
|
|
189
|
+
* .subscribe()
|
|
190
|
+
* ```
|
|
191
|
+
*/
|
|
192
|
+
channel(name, options) {
|
|
193
|
+
return this.realtime.channel(name, options);
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Shortcut: remove a realtime channel by name or AuraChannel instance.
|
|
197
|
+
* Equivalent to `aura.realtime.removeChannel(channel)`.
|
|
198
|
+
*/
|
|
199
|
+
removeChannel(channel) {
|
|
200
|
+
return this.realtime.removeChannel(channel);
|
|
201
|
+
}
|
|
202
|
+
/**
|
|
203
|
+
* Shortcut: remove all realtime channels and unsubscribe.
|
|
204
|
+
* Equivalent to `aura.realtime.removeAllChannels()`.
|
|
205
|
+
*/
|
|
206
|
+
removeAllChannels() {
|
|
207
|
+
return this.realtime.removeAllChannels();
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Shortcut: list all active realtime channels.
|
|
211
|
+
* Equivalent to `aura.realtime.getChannels()`.
|
|
212
|
+
*/
|
|
213
|
+
getChannels() {
|
|
214
|
+
return this.realtime.getChannels();
|
|
215
|
+
}
|
|
216
|
+
};
|
|
217
|
+
var MAX_CHUNK_SIZE = 3600;
|
|
218
|
+
function createServerClient(baseUrl, apiKey, options) {
|
|
219
|
+
const cookieName = `aura-${core.clientScope(baseUrl)}-auth`;
|
|
220
|
+
const store = new core.LocalAuthStore(cookieName);
|
|
221
|
+
const idxRe = new RegExp(`^${cookieName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\.(\\d+)$`);
|
|
222
|
+
const incoming = options.cookies.getAll();
|
|
223
|
+
const numbered = incoming.filter((c) => idxRe.test(c.name)).sort((a, b) => Number(a.name.match(idxRe)[1]) - Number(b.name.match(idxRe)[1]));
|
|
224
|
+
const base = incoming.find((c) => c.name === cookieName);
|
|
225
|
+
const decodedValue = numbered.length > 0 ? numbered.map((c) => c.value).join("") : base?.value;
|
|
226
|
+
if (decodedValue) {
|
|
227
|
+
store.loadFromCookie(`${cookieName}=${encodeURIComponent(decodedValue)}`);
|
|
228
|
+
}
|
|
229
|
+
const initialNames = incoming.filter((c) => c.name === cookieName || idxRe.test(c.name)).map((c) => c.name);
|
|
230
|
+
const defaultCookieOpts = {
|
|
231
|
+
path: "/",
|
|
232
|
+
secure: baseUrl.startsWith("https://"),
|
|
233
|
+
sameSite: "Lax",
|
|
234
|
+
httpOnly: true,
|
|
235
|
+
maxAge: 60 * 60 * 24 * 30,
|
|
236
|
+
// 30 days
|
|
237
|
+
...options.cookieOptions
|
|
238
|
+
};
|
|
239
|
+
store.onChange(() => {
|
|
240
|
+
const toSet = [];
|
|
241
|
+
const used = /* @__PURE__ */ new Set();
|
|
242
|
+
if (store.token) {
|
|
243
|
+
const cookieStr = store.exportToCookie();
|
|
244
|
+
const eqIdx = cookieStr.indexOf("=");
|
|
245
|
+
const rawEncoded = eqIdx >= 0 ? cookieStr.slice(eqIdx + 1).split(";")[0] : "";
|
|
246
|
+
const decoded = rawEncoded ? decodeURIComponent(rawEncoded) : "";
|
|
247
|
+
if (decoded.length <= MAX_CHUNK_SIZE) {
|
|
248
|
+
toSet.push({ name: cookieName, value: decoded, options: defaultCookieOpts });
|
|
249
|
+
used.add(cookieName);
|
|
250
|
+
} else {
|
|
251
|
+
let idx = 0;
|
|
252
|
+
for (let i = 0; i < decoded.length; i += MAX_CHUNK_SIZE, idx++) {
|
|
253
|
+
const name = `${cookieName}.${idx}`;
|
|
254
|
+
toSet.push({
|
|
255
|
+
name,
|
|
256
|
+
value: decoded.slice(i, i + MAX_CHUNK_SIZE),
|
|
257
|
+
options: defaultCookieOpts
|
|
258
|
+
});
|
|
259
|
+
used.add(name);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
const expireOpts = { ...defaultCookieOpts, maxAge: 0 };
|
|
264
|
+
for (const name of initialNames) {
|
|
265
|
+
if (!used.has(name)) toSet.push({ name, value: "", options: expireOpts });
|
|
266
|
+
}
|
|
267
|
+
if (toSet.length > 0) options.cookies.setAll(toSet);
|
|
268
|
+
});
|
|
269
|
+
return new AuraClient(baseUrl, apiKey, {
|
|
270
|
+
auth: { persistSession: false, storage: store }
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// src/nextjs.ts
|
|
275
|
+
async function loadNextModule(specifier) {
|
|
276
|
+
try {
|
|
277
|
+
const mod = await import(
|
|
278
|
+
/* @vite-ignore */
|
|
279
|
+
specifier
|
|
280
|
+
);
|
|
281
|
+
return mod;
|
|
282
|
+
} catch {
|
|
283
|
+
return null;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
function createAuthMiddleware(options = {}) {
|
|
287
|
+
return async function middleware(request) {
|
|
288
|
+
const nextServer = await loadNextModule("next/server");
|
|
289
|
+
if (!nextServer?.NextResponse) {
|
|
290
|
+
throw new Error(
|
|
291
|
+
"[@aurabase/nextjs] Next.js n'est pas install\xE9. createAuthMiddleware n\xE9cessite next/server."
|
|
292
|
+
);
|
|
293
|
+
}
|
|
294
|
+
const { NextResponse } = nextServer;
|
|
295
|
+
const projectUrl = options.projectUrl ?? process.env.NEXT_PUBLIC_AURABASE_URL ?? process.env.AURABASE_URL ?? "";
|
|
296
|
+
const anonKey = options.anonKey ?? process.env.NEXT_PUBLIC_AURABASE_ANON_KEY ?? process.env.AURABASE_ANON_KEY ?? "";
|
|
297
|
+
if (!projectUrl || !anonKey) {
|
|
298
|
+
console.warn(
|
|
299
|
+
"[@aurabase/nextjs] Variables d'environnement manquantes : NEXT_PUBLIC_AURABASE_URL ou NEXT_PUBLIC_AURABASE_ANON_KEY non d\xE9finies."
|
|
300
|
+
);
|
|
301
|
+
return NextResponse.next({ request });
|
|
302
|
+
}
|
|
303
|
+
const response = NextResponse.next({ request });
|
|
304
|
+
const cookieHandler = {
|
|
305
|
+
getAll: () => request.cookies.getAll(),
|
|
306
|
+
setAll: (cookiesToSet) => {
|
|
307
|
+
cookiesToSet.forEach(({ name, value, options: cookieOpts }) => {
|
|
308
|
+
request.cookies.set(name, value);
|
|
309
|
+
response.cookies.set(name, value, cookieOpts);
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
const client = createServerClient(projectUrl, anonKey, {
|
|
314
|
+
cookies: cookieHandler
|
|
315
|
+
});
|
|
316
|
+
const { data: sessionData } = await client.auth.getSession();
|
|
317
|
+
const session = sessionData?.session ?? null;
|
|
318
|
+
const user = session?.user ?? null;
|
|
319
|
+
const pathname = request.nextUrl.pathname;
|
|
320
|
+
const publicPatterns = options.publicRoutes ?? ["/", "/login", "/signup", "/auth/callback"];
|
|
321
|
+
const isPublic = publicPatterns.some((pattern) => {
|
|
322
|
+
if (pattern.endsWith("*")) {
|
|
323
|
+
return pathname.startsWith(pattern.slice(0, -1));
|
|
324
|
+
}
|
|
325
|
+
return pathname === pattern;
|
|
326
|
+
});
|
|
327
|
+
if (!isPublic && !user) {
|
|
328
|
+
const loginUrl = new URL(options.loginUrl ?? "/login", request.url);
|
|
329
|
+
loginUrl.searchParams.set("redirectTo", pathname);
|
|
330
|
+
return NextResponse.redirect(loginUrl);
|
|
331
|
+
}
|
|
332
|
+
if (options.onAuthenticated) {
|
|
333
|
+
const customResponse = await options.onAuthenticated({ user, session, request });
|
|
334
|
+
if (customResponse) return customResponse;
|
|
335
|
+
}
|
|
336
|
+
return response;
|
|
337
|
+
};
|
|
338
|
+
}
|
|
339
|
+
function createClientForServerComponent(cookieStore, projectUrl, apiKey) {
|
|
340
|
+
const url = projectUrl ?? process.env.NEXT_PUBLIC_AURABASE_URL ?? process.env.AURABASE_URL ?? "";
|
|
341
|
+
const key = apiKey ?? process.env.NEXT_PUBLIC_AURABASE_ANON_KEY ?? process.env.AURABASE_ANON_KEY ?? "";
|
|
342
|
+
return createServerClient(url, key, {
|
|
343
|
+
cookies: {
|
|
344
|
+
getAll: () => cookieStore.getAll(),
|
|
345
|
+
setAll: () => {
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
function createClientForServerAction(cookieStore, projectUrl, apiKey) {
|
|
351
|
+
const url = projectUrl ?? process.env.NEXT_PUBLIC_AURABASE_URL ?? process.env.AURABASE_URL ?? "";
|
|
352
|
+
const key = apiKey ?? process.env.NEXT_PUBLIC_AURABASE_ANON_KEY ?? process.env.AURABASE_ANON_KEY ?? "";
|
|
353
|
+
return createServerClient(url, key, {
|
|
354
|
+
cookies: {
|
|
355
|
+
getAll: () => cookieStore.getAll(),
|
|
356
|
+
setAll: (cookiesToSet) => {
|
|
357
|
+
cookiesToSet.forEach(({ name, value, options }) => {
|
|
358
|
+
cookieStore.set?.(name, value, options);
|
|
359
|
+
});
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
async function auth(options) {
|
|
365
|
+
const nextHeaders = await loadNextModule("next/headers");
|
|
366
|
+
if (!nextHeaders?.cookies) {
|
|
367
|
+
throw new Error("[@aurabase/nextjs] auth() ne peut \xEAtre appel\xE9 que dans un environnement Next.js App Router.");
|
|
368
|
+
}
|
|
369
|
+
const cookieStore = await nextHeaders.cookies();
|
|
370
|
+
const client = createClientForServerComponent(cookieStore, options?.projectUrl, options?.apiKey);
|
|
371
|
+
const { data } = await client.auth.getSession();
|
|
372
|
+
const session = data?.session ?? null;
|
|
373
|
+
const user = session?.user ?? null;
|
|
374
|
+
return {
|
|
375
|
+
userId: user?.id ?? null,
|
|
376
|
+
user,
|
|
377
|
+
session
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
async function currentUser(options) {
|
|
381
|
+
const { user } = await auth(options);
|
|
382
|
+
return user;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
exports.auth = auth;
|
|
386
|
+
exports.createAuthMiddleware = createAuthMiddleware;
|
|
387
|
+
exports.createClientForServerAction = createClientForServerAction;
|
|
388
|
+
exports.createClientForServerComponent = createClientForServerComponent;
|
|
389
|
+
exports.currentUser = currentUser;
|