@motherbase/client 1.2.4 → 1.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +95 -42
- package/dist/admin.d.ts +81 -0
- package/dist/admin.d.ts.map +1 -0
- package/dist/admin.js +85 -0
- package/dist/admin.js.map +1 -0
- package/dist/auth.d.ts +35 -5
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +52 -17
- package/dist/auth.js.map +1 -1
- package/dist/channel.d.ts +15 -0
- package/dist/channel.d.ts.map +1 -1
- package/dist/channel.js +53 -19
- package/dist/channel.js.map +1 -1
- package/dist/cookie.d.ts +3 -1
- package/dist/cookie.d.ts.map +1 -1
- package/dist/cookie.js +14 -2
- package/dist/cookie.js.map +1 -1
- package/dist/database.d.ts +169 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +2 -0
- package/dist/database.js.map +1 -0
- package/dist/http.d.ts +11 -0
- package/dist/http.d.ts.map +1 -1
- package/dist/http.js +10 -1
- package/dist/http.js.map +1 -1
- package/dist/index.d.ts +53 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +68 -2
- package/dist/index.js.map +1 -1
- package/dist/mfa.d.ts +109 -0
- package/dist/mfa.d.ts.map +1 -0
- package/dist/mfa.js +134 -0
- package/dist/mfa.js.map +1 -0
- package/dist/postgrest.d.ts +207 -32
- package/dist/postgrest.d.ts.map +1 -1
- package/dist/postgrest.js +349 -54
- package/dist/postgrest.js.map +1 -1
- package/dist/realtime.d.ts +15 -3
- package/dist/realtime.d.ts.map +1 -1
- package/dist/realtime.js +24 -1
- package/dist/realtime.js.map +1 -1
- package/dist/storage.d.ts +33 -16
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +70 -21
- package/dist/storage.js.map +1 -1
- package/package.json +52 -51
package/dist/index.d.ts
CHANGED
|
@@ -4,15 +4,30 @@ import { StorageClient } from './storage.js';
|
|
|
4
4
|
import { FunctionsClient } from './functions.js';
|
|
5
5
|
import { RealtimeModule } from './realtime.js';
|
|
6
6
|
import { RealtimeChannel, type RealtimeChannelOptions } from './channel.js';
|
|
7
|
-
import {
|
|
7
|
+
import type { PostgrestCount, PostgrestResponse } from './postgrest.js';
|
|
8
8
|
import type { ClientOptions } from './types.js';
|
|
9
|
+
/** Options for `client.rpc(fn, args, options)`, mirroring supabase-js. */
|
|
10
|
+
export interface RpcOptions {
|
|
11
|
+
/** Send the request as HEAD: no rows, only the count. */
|
|
12
|
+
head?: boolean;
|
|
13
|
+
/** Use the read-only GET form, with the arguments as query parameters. */
|
|
14
|
+
get?: boolean;
|
|
15
|
+
count?: PostgrestCount;
|
|
16
|
+
}
|
|
17
|
+
import type { DefaultSchemaName, FunctionArgs, FunctionName, FunctionReturns, GenericDatabase, GenericSchema, InsertOf, RelationName, RowOf, SchemaOf, TypedQuery, UpdateOf } from './database.js';
|
|
9
18
|
/**
|
|
10
19
|
* Supabase-js-compatible client for a Motherbase backend.
|
|
11
20
|
*
|
|
12
21
|
* Drop-in shaped: `client.from(table).select()…`, `client.auth.signInWithPassword()`,
|
|
13
22
|
* `client.storage.from(bucket)`, `client.channel(name)`, `client.functions.invoke()`.
|
|
23
|
+
*
|
|
24
|
+
* Pass the type generated by `motherbase gen types typescript` to get real
|
|
25
|
+
* inference: `createClient<Database>(url, key)` then types every row, rejects
|
|
26
|
+
* unknown columns in `.select()`, checks `.insert()` payloads against the
|
|
27
|
+
* Insert shape and types `.rpc()` from `Functions`. Without it the client
|
|
28
|
+
* behaves exactly as it did before generics existed.
|
|
14
29
|
*/
|
|
15
|
-
export declare class MotherbaseClient {
|
|
30
|
+
export declare class MotherbaseClient<Database = GenericDatabase, SchemaName = DefaultSchemaName<Database>, Schema extends GenericSchema = SchemaOf<Database, SchemaName>> {
|
|
16
31
|
private readonly url;
|
|
17
32
|
/** Accepted for supabase-js signature parity; sent as an `apikey` header when set. */
|
|
18
33
|
readonly key?: string | undefined;
|
|
@@ -27,8 +42,29 @@ export declare class MotherbaseClient {
|
|
|
27
42
|
constructor(url: string,
|
|
28
43
|
/** Accepted for supabase-js signature parity; sent as an `apikey` header when set. */
|
|
29
44
|
key?: string | undefined, options?: ClientOptions);
|
|
30
|
-
/**
|
|
31
|
-
|
|
45
|
+
/**
|
|
46
|
+
* Start a PostgREST-style query against a table or view.
|
|
47
|
+
*
|
|
48
|
+
* The first overload is the typed path: with a generated `Database` the
|
|
49
|
+
* relation name is checked and the row/insert/update types come from it.
|
|
50
|
+
* The second keeps the pre-generics form (`from<MyRow>('t')`) working; its
|
|
51
|
+
* `never` default makes the parameter unusable unless `Row` is passed
|
|
52
|
+
* explicitly, so a bare `from('typo')` still has to satisfy the first
|
|
53
|
+
* overload rather than silently falling through to an unchecked one.
|
|
54
|
+
*/
|
|
55
|
+
from<Name extends RelationName<Schema>>(table: Name): TypedQuery<RowOf<Schema, Name>, InsertOf<Schema, Name>, UpdateOf<Schema, Name>>;
|
|
56
|
+
from<Row extends object = never>(table: [Row] extends [never] ? never : string): TypedQuery<Row, Partial<Row>, Partial<Row>>;
|
|
57
|
+
/**
|
|
58
|
+
* Call a database function, typed from the generated `Functions` map.
|
|
59
|
+
*
|
|
60
|
+
* The transport is `POST /rest/v1/rpc/<fn>`, which the REST layer gains in
|
|
61
|
+
* Phase 2.8. The typing is independent of that work: it reads only the
|
|
62
|
+
* generated `Database`, so it is correct the moment the route exists.
|
|
63
|
+
*
|
|
64
|
+
* `get` and `head` switch to the read-only forms, which carry their arguments
|
|
65
|
+
* as query parameters rather than as a body, exactly as supabase-js does.
|
|
66
|
+
*/
|
|
67
|
+
rpc<Name extends FunctionName<Schema>>(fn: Name, args?: FunctionArgs<Schema, Name>, options?: RpcOptions): Promise<PostgrestResponse<FunctionReturns<Schema, Name>>>;
|
|
32
68
|
/** Create (or reuse) a realtime channel. */
|
|
33
69
|
channel(name: string, opts?: RealtimeChannelOptions): RealtimeChannel;
|
|
34
70
|
/** Unsubscribe and drop a channel. */
|
|
@@ -44,14 +80,25 @@ export declare class MotherbaseClient {
|
|
|
44
80
|
* @param url Backend API base URL.
|
|
45
81
|
* @param key Anon/publishable key (optional). Sent as an `apikey` header.
|
|
46
82
|
* @param options Session storage, fetch override, extra headers.
|
|
83
|
+
*
|
|
84
|
+
* @example
|
|
85
|
+
* ```ts
|
|
86
|
+
* import type { Database } from './database.types'
|
|
87
|
+
* const client = createClient<Database>(url, anonKey)
|
|
88
|
+
* ```
|
|
47
89
|
*/
|
|
48
|
-
export declare function createClient(url: string, key?: string, options?: ClientOptions): MotherbaseClient
|
|
90
|
+
export declare function createClient<Database = GenericDatabase, SchemaName = DefaultSchemaName<Database>, Schema extends GenericSchema = SchemaOf<Database, SchemaName>>(url: string, key?: string, options?: ClientOptions): MotherbaseClient<Database, SchemaName, Schema>;
|
|
49
91
|
export { BackendError } from './http.js';
|
|
50
92
|
export { memoryStorage, localStorageStorage };
|
|
51
93
|
export { cookieStorage, serverCookieStorage } from './cookie.js';
|
|
52
94
|
export { PostgrestQueryBuilder } from './postgrest.js';
|
|
53
|
-
export type { PostgrestSingleBuilder } from './postgrest.js';
|
|
95
|
+
export type { PostgrestSingleBuilder, PostgrestTextBuilder, PostgrestExplainBuilder, PostgrestResponse, PostgrestPrimitive, PostgrestArrayOperand, PostgrestFilterOperator, PostgrestIsValue, PostgrestCount, TextSearchType, ReferencedTableOption, OrderOptions, SelectOptions, InsertOptions, UpsertOptions, MutateOptions, ExplainOptions, } from './postgrest.js';
|
|
96
|
+
export type { GenericDatabase, GenericSchema, GenericTable, GenericView, GenericFunction, DefaultSchemaName, SchemaOf, Relations, RelationName, RowOf, InsertOf, UpdateOf, FunctionName, FunctionArgs, FunctionReturns, TypedQuery, TypedSingleQuery, SelectResult, ValidateSelect, UnknownSelectColumns, EmbeddedSelectSeam, ColumnName, FilterValue, } from './database.js';
|
|
54
97
|
export { AuthClient } from './auth.js';
|
|
98
|
+
export { MfaClient } from './mfa.js';
|
|
99
|
+
export { AuthAdminClient } from './admin.js';
|
|
100
|
+
export type { AdminListUsersParams, AdminUserList, AdminCreateUserParams, AdminCreatedUser, AdminUpdateUserParams, } from './admin.js';
|
|
101
|
+
export type { MfaFactor, MfaEnrollResponse, MfaChallengeResponse } from './mfa.js';
|
|
55
102
|
export type { SignUpCredentials, SignInWithPasswordCredentials, SignInWithOtpCredentials, VerifyOtpParams, SignInWithOAuthCredentials, UpdateUserAttributes, DeleteUserAttributes, Subscription, } from './auth.js';
|
|
56
103
|
export { StorageClient, StorageBucket } from './storage.js';
|
|
57
104
|
export type { UploadOptions, UploadResult } from './storage.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { HttpClient } from './http.js';
|
|
1
|
+
import { HttpClient, toError } from './http.js';
|
|
2
|
+
import { contractPath } from '@motherbase/contracts';
|
|
2
3
|
import { SessionStore, memoryStorage, localStorageStorage } from './session.js';
|
|
3
4
|
import { AuthClient } from './auth.js';
|
|
4
5
|
import { StorageClient } from './storage.js';
|
|
@@ -11,6 +12,12 @@ import { PostgrestQueryBuilder } from './postgrest.js';
|
|
|
11
12
|
*
|
|
12
13
|
* Drop-in shaped: `client.from(table).select()…`, `client.auth.signInWithPassword()`,
|
|
13
14
|
* `client.storage.from(bucket)`, `client.channel(name)`, `client.functions.invoke()`.
|
|
15
|
+
*
|
|
16
|
+
* Pass the type generated by `motherbase gen types typescript` to get real
|
|
17
|
+
* inference: `createClient<Database>(url, key)` then types every row, rejects
|
|
18
|
+
* unknown columns in `.select()`, checks `.insert()` payloads against the
|
|
19
|
+
* Insert shape and types `.rpc()` from `Functions`. Without it the client
|
|
20
|
+
* behaves exactly as it did before generics existed.
|
|
14
21
|
*/
|
|
15
22
|
export class MotherbaseClient {
|
|
16
23
|
constructor(url,
|
|
@@ -31,9 +38,23 @@ export class MotherbaseClient {
|
|
|
31
38
|
const headers = { ...options.headers };
|
|
32
39
|
if (key)
|
|
33
40
|
headers['apikey'] = key;
|
|
41
|
+
// A secret key runs every request as service_role, which bypasses row level
|
|
42
|
+
// security. In a browser it is readable by anyone who opens devtools, so it
|
|
43
|
+
// is not "a key that leaked", it is the whole database published. Warn
|
|
44
|
+
// rather than throw: a legitimate caller may run in a runtime that defines
|
|
45
|
+
// `window` (a test harness, an Electron main process), and refusing to
|
|
46
|
+
// construct would break them for a heuristic.
|
|
47
|
+
if (key?.startsWith('mb_secret_') && typeof window !== 'undefined') {
|
|
48
|
+
console.warn('[motherbase] A secret API key was passed to createClient in a browser context. '
|
|
49
|
+
+ 'Secret keys bypass row level security and must stay server side. '
|
|
50
|
+
+ 'Use the publishable key here.');
|
|
51
|
+
}
|
|
34
52
|
this.store = new SessionStore(options.storage ?? memoryStorage());
|
|
35
53
|
// auth needs the http client, and http needs auth._refresh for the 401 path,
|
|
36
54
|
// so wire them in two steps with a late-bound refresh callback.
|
|
55
|
+
// prefer-const cannot see the closure above: `auth` is read by the refresh
|
|
56
|
+
// callback before this line's assignment happens, so it has to be a `let`.
|
|
57
|
+
// eslint-disable-next-line prefer-const
|
|
37
58
|
let auth;
|
|
38
59
|
this.http = new HttpClient(url, this.store, { autoRefresh, fetch: fetchImpl, headers }, () => auth._refresh());
|
|
39
60
|
auth = new AuthClient(this.http, this.store);
|
|
@@ -42,10 +63,47 @@ export class MotherbaseClient {
|
|
|
42
63
|
this.functions = new FunctionsClient(this.http);
|
|
43
64
|
this.realtime = new RealtimeModule(url, this.store, fetchImpl, options.realtimeIoFactory);
|
|
44
65
|
}
|
|
45
|
-
/** Start a PostgREST-style query against a table. */
|
|
46
66
|
from(table) {
|
|
47
67
|
return new PostgrestQueryBuilder(this.http, table);
|
|
48
68
|
}
|
|
69
|
+
/**
|
|
70
|
+
* Call a database function, typed from the generated `Functions` map.
|
|
71
|
+
*
|
|
72
|
+
* The transport is `POST /rest/v1/rpc/<fn>`, which the REST layer gains in
|
|
73
|
+
* Phase 2.8. The typing is independent of that work: it reads only the
|
|
74
|
+
* generated `Database`, so it is correct the moment the route exists.
|
|
75
|
+
*
|
|
76
|
+
* `get` and `head` switch to the read-only forms, which carry their arguments
|
|
77
|
+
* as query parameters rather than as a body, exactly as supabase-js does.
|
|
78
|
+
*/
|
|
79
|
+
async rpc(fn, args, options = {}) {
|
|
80
|
+
try {
|
|
81
|
+
const method = options.head ? 'HEAD' : options.get ? 'GET' : 'POST';
|
|
82
|
+
const params = new URLSearchParams();
|
|
83
|
+
if (method !== 'POST') {
|
|
84
|
+
for (const [name, value] of Object.entries((args ?? {}))) {
|
|
85
|
+
if (value === undefined)
|
|
86
|
+
continue;
|
|
87
|
+
params.append(name, Array.isArray(value) ? `{${value.join(',')}}` : String(value));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
const query = params.toString();
|
|
91
|
+
const path = `${contractPath.rest('rpc')}/${encodeURIComponent(fn)}${query ? `?${query}` : ''}`;
|
|
92
|
+
const headers = options.count ? { Prefer: `count=${options.count}` } : undefined;
|
|
93
|
+
const result = await this.http.requestWithHeaders(path, {
|
|
94
|
+
method,
|
|
95
|
+
body: method === 'POST' ? (args ?? {}) : undefined,
|
|
96
|
+
headers,
|
|
97
|
+
});
|
|
98
|
+
const range = result.headers.get('content-range');
|
|
99
|
+
const total = range?.split('/')[1];
|
|
100
|
+
const count = total && total !== '*' && Number.isFinite(Number(total)) ? Number(total) : null;
|
|
101
|
+
return { data: options.head ? null : result.data, error: null, count };
|
|
102
|
+
}
|
|
103
|
+
catch (err) {
|
|
104
|
+
return { data: null, error: toError(err), count: null };
|
|
105
|
+
}
|
|
106
|
+
}
|
|
49
107
|
/** Create (or reuse) a realtime channel. */
|
|
50
108
|
channel(name, opts = {}) {
|
|
51
109
|
const existing = this.channels.get(name);
|
|
@@ -78,6 +136,12 @@ export class MotherbaseClient {
|
|
|
78
136
|
* @param url Backend API base URL.
|
|
79
137
|
* @param key Anon/publishable key (optional). Sent as an `apikey` header.
|
|
80
138
|
* @param options Session storage, fetch override, extra headers.
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```ts
|
|
142
|
+
* import type { Database } from './database.types'
|
|
143
|
+
* const client = createClient<Database>(url, anonKey)
|
|
144
|
+
* ```
|
|
81
145
|
*/
|
|
82
146
|
export function createClient(url, key, options = {}) {
|
|
83
147
|
return new MotherbaseClient(url, key, options);
|
|
@@ -87,6 +151,8 @@ export { memoryStorage, localStorageStorage };
|
|
|
87
151
|
export { cookieStorage, serverCookieStorage } from './cookie.js';
|
|
88
152
|
export { PostgrestQueryBuilder } from './postgrest.js';
|
|
89
153
|
export { AuthClient } from './auth.js';
|
|
154
|
+
export { MfaClient } from './mfa.js';
|
|
155
|
+
export { AuthAdminClient } from './admin.js';
|
|
90
156
|
export { StorageClient, StorageBucket } from './storage.js';
|
|
91
157
|
export { FunctionsClient } from './functions.js';
|
|
92
158
|
export { RealtimeChannel } from './channel.js';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/mfa.d.ts
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { HttpClient } from './http.js';
|
|
2
|
+
import type { MotherbaseResponse } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Two-factor authentication, shaped like `supabase.auth.mfa`.
|
|
5
|
+
*
|
|
6
|
+
* The server has shipped TOTP with backup codes and trusted devices since the
|
|
7
|
+
* beginning; only the client namespace was missing, which meant the product's
|
|
8
|
+
* strongest auth feature could not be reached from the SDK that sells it.
|
|
9
|
+
*
|
|
10
|
+
* The mapping onto Better Auth is not one-to-one, and the differences are stated
|
|
11
|
+
* per method rather than papered over:
|
|
12
|
+
*
|
|
13
|
+
* * A factor here is TOTP or nothing. Better Auth models two-factor as a
|
|
14
|
+
* property of the user, not as a list of enrolled factors, so `listFactors`
|
|
15
|
+
* reports the single TOTP factor rather than an arbitrary set, and there is
|
|
16
|
+
* no phone factor to enrol.
|
|
17
|
+
* * Enrolment needs the user's password. supabase-js does not ask for one;
|
|
18
|
+
* Better Auth does, because enabling two-factor is a credential change.
|
|
19
|
+
* * `challenge()` is a local no-op for TOTP: there is nothing to send, the
|
|
20
|
+
* code is already on the user's device. It exists so the supabase-js
|
|
21
|
+
* challenge/verify sequence compiles unchanged. For the email or SMS second
|
|
22
|
+
* factor, `challenge()` does send a code.
|
|
23
|
+
*/
|
|
24
|
+
export interface MfaFactor {
|
|
25
|
+
id: string;
|
|
26
|
+
/** Always `totp` today. */
|
|
27
|
+
factor_type: 'totp';
|
|
28
|
+
status: 'verified' | 'unverified';
|
|
29
|
+
friendly_name?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface MfaEnrollResponse {
|
|
32
|
+
id: string;
|
|
33
|
+
type: 'totp';
|
|
34
|
+
totp: {
|
|
35
|
+
/** otpauth:// URI to render as a QR code. */
|
|
36
|
+
uri: string;
|
|
37
|
+
/** The shared secret, for users who type it in by hand. */
|
|
38
|
+
secret: string;
|
|
39
|
+
};
|
|
40
|
+
/** One-time codes to store somewhere safe. Shown only at enrolment. */
|
|
41
|
+
backupCodes: string[];
|
|
42
|
+
}
|
|
43
|
+
export interface MfaChallengeResponse {
|
|
44
|
+
id: string;
|
|
45
|
+
expires_at: number | null;
|
|
46
|
+
}
|
|
47
|
+
export declare class MfaClient {
|
|
48
|
+
private readonly http;
|
|
49
|
+
/** Re-reads the session after a verify, so a stepped-up token is persisted. */
|
|
50
|
+
private readonly onVerified;
|
|
51
|
+
constructor(http: HttpClient,
|
|
52
|
+
/** Re-reads the session after a verify, so a stepped-up token is persisted. */
|
|
53
|
+
onVerified: () => Promise<void>);
|
|
54
|
+
/**
|
|
55
|
+
* Start TOTP enrolment. Returns the otpauth URI, the secret and the backup
|
|
56
|
+
* codes. The factor is not usable until `verify()` accepts a code from it.
|
|
57
|
+
*/
|
|
58
|
+
enroll(params: {
|
|
59
|
+
password: string;
|
|
60
|
+
issuer?: string;
|
|
61
|
+
}): Promise<MotherbaseResponse<MfaEnrollResponse>>;
|
|
62
|
+
/**
|
|
63
|
+
* For TOTP this resolves immediately and sends nothing: the code already lives
|
|
64
|
+
* on the user's device. Pass `channel` to send a second-factor code by email
|
|
65
|
+
* or SMS instead, when the project has that enabled.
|
|
66
|
+
*/
|
|
67
|
+
challenge(params?: {
|
|
68
|
+
factorId?: string;
|
|
69
|
+
channel?: 'email' | 'sms';
|
|
70
|
+
}): Promise<MotherbaseResponse<MfaChallengeResponse>>;
|
|
71
|
+
/**
|
|
72
|
+
* Verify a code. `code` is a TOTP code by default; set `type` to `otp` for an
|
|
73
|
+
* emailed or texted second factor, or `backup` to spend a recovery code.
|
|
74
|
+
*/
|
|
75
|
+
verify(params: {
|
|
76
|
+
code: string;
|
|
77
|
+
factorId?: string;
|
|
78
|
+
challengeId?: string;
|
|
79
|
+
type?: 'totp' | 'otp' | 'backup';
|
|
80
|
+
/** Remember this device for the project's configured trust window. */
|
|
81
|
+
trustDevice?: boolean;
|
|
82
|
+
}): Promise<MotherbaseResponse<{
|
|
83
|
+
verified: true;
|
|
84
|
+
}>>;
|
|
85
|
+
/** Turn two-factor off. Requires the password, as enabling did. */
|
|
86
|
+
unenroll(params: {
|
|
87
|
+
password: string;
|
|
88
|
+
factorId?: string;
|
|
89
|
+
}): Promise<MotherbaseResponse<{
|
|
90
|
+
id: string;
|
|
91
|
+
}>>;
|
|
92
|
+
/** Issue a fresh set of backup codes, invalidating the previous set. */
|
|
93
|
+
regenerateBackupCodes(params: {
|
|
94
|
+
password: string;
|
|
95
|
+
}): Promise<MotherbaseResponse<{
|
|
96
|
+
backupCodes: string[];
|
|
97
|
+
}>>;
|
|
98
|
+
/**
|
|
99
|
+
* The user's factors. Reads the TOTP URI: getting one back means TOTP is
|
|
100
|
+
* enrolled, a failure means it is not. There is no list endpoint to call
|
|
101
|
+
* because there is no list, and inventing one client-side would be a lie about
|
|
102
|
+
* what the server models.
|
|
103
|
+
*/
|
|
104
|
+
listFactors(): Promise<MotherbaseResponse<{
|
|
105
|
+
totp: MfaFactor[];
|
|
106
|
+
all: MfaFactor[];
|
|
107
|
+
}>>;
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=mfa.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mfa.d.ts","sourceRoot":"","sources":["../src/mfa.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,YAAY,CAAC;AAErD;;;;;;;;;;;;;;;;;;;;GAoBG;AAEH,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,2BAA2B;IAC3B,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,UAAU,GAAG,YAAY,CAAC;IAClC,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,iBAAiB;IAChC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE;QACJ,6CAA6C;QAC7C,GAAG,EAAE,MAAM,CAAC;QACZ,2DAA2D;QAC3D,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;IACF,uEAAuE;IACvE,WAAW,EAAE,MAAM,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,oBAAoB;IACnC,EAAE,EAAE,MAAM,CAAC;IACX,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;CAC3B;AAaD,qBAAa,SAAS;IAElB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,+EAA+E;IAC/E,OAAO,CAAC,QAAQ,CAAC,UAAU;gBAFV,IAAI,EAAE,UAAU;IACjC,+EAA+E;IAC9D,UAAU,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC;IAGlD;;;OAGG;IACG,MAAM,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC,iBAAiB,CAAC,CAAC;IA6B3G;;;;OAIG;IACG,SAAS,CAAC,MAAM,GAAE;QAAE,QAAQ,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,GAAG,KAAK,CAAA;KAAO,GAAG,OAAO,CACrF,kBAAkB,CAAC,oBAAoB,CAAC,CACzC;IAYD;;;OAGG;IACG,MAAM,CAAC,MAAM,EAAE;QACnB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,CAAC,EAAE,MAAM,CAAC;QAClB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,IAAI,CAAC,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,CAAC;QACjC,sEAAsE;QACtE,WAAW,CAAC,EAAE,OAAO,CAAC;KACvB,GAAG,OAAO,CAAC,kBAAkB,CAAC;QAAE,QAAQ,EAAE,IAAI,CAAA;KAAE,CAAC,CAAC;IAmBnD,mEAAmE;IAC7D,QAAQ,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;QAAE,EAAE,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAS5G,wEAAwE;IAClE,qBAAqB,CAAC,MAAM,EAAE;QAAE,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,OAAO,CAAC,kBAAkB,CAAC;QAAE,WAAW,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;IAajH;;;;;OAKG;IACG,WAAW,IAAI,OAAO,CAAC,kBAAkB,CAAC;QAAE,IAAI,EAAE,SAAS,EAAE,CAAC;QAAC,GAAG,EAAE,SAAS,EAAE,CAAA;KAAE,CAAC,CAAC;CAU1F"}
|
package/dist/mfa.js
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import { toError } from './http.js';
|
|
2
|
+
const R = {
|
|
3
|
+
enable: '/api/auth/two-factor/enable',
|
|
4
|
+
disable: '/api/auth/two-factor/disable',
|
|
5
|
+
totpUri: '/api/auth/two-factor/get-totp-uri',
|
|
6
|
+
verifyTotp: '/api/auth/two-factor/verify-totp',
|
|
7
|
+
sendOtp: '/api/auth/two-factor/send-otp',
|
|
8
|
+
verifyOtp: '/api/auth/two-factor/verify-otp',
|
|
9
|
+
verifyBackupCode: '/api/auth/two-factor/verify-backup-code',
|
|
10
|
+
generateBackupCodes: '/api/auth/two-factor/generate-backup-codes',
|
|
11
|
+
};
|
|
12
|
+
export class MfaClient {
|
|
13
|
+
constructor(http,
|
|
14
|
+
/** Re-reads the session after a verify, so a stepped-up token is persisted. */
|
|
15
|
+
onVerified) {
|
|
16
|
+
this.http = http;
|
|
17
|
+
this.onVerified = onVerified;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Start TOTP enrolment. Returns the otpauth URI, the secret and the backup
|
|
21
|
+
* codes. The factor is not usable until `verify()` accepts a code from it.
|
|
22
|
+
*/
|
|
23
|
+
async enroll(params) {
|
|
24
|
+
try {
|
|
25
|
+
const payload = await this.http.request(R.enable, {
|
|
26
|
+
method: 'POST',
|
|
27
|
+
body: { password: params.password, ...(params.issuer ? { issuer: params.issuer } : {}) },
|
|
28
|
+
raw: true,
|
|
29
|
+
});
|
|
30
|
+
const uri = payload.totpURI ?? payload.totpUri ?? '';
|
|
31
|
+
return {
|
|
32
|
+
data: {
|
|
33
|
+
// Better Auth has no per-factor id: the user is the factor. `totp` is
|
|
34
|
+
// used as a stable handle so unenroll/challenge/verify have something
|
|
35
|
+
// to take, matching the supabase-js shape.
|
|
36
|
+
id: 'totp',
|
|
37
|
+
type: 'totp',
|
|
38
|
+
totp: { uri, secret: secretFromUri(uri) },
|
|
39
|
+
backupCodes: payload.backupCodes ?? [],
|
|
40
|
+
},
|
|
41
|
+
error: null,
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
catch (err) {
|
|
45
|
+
return { data: null, error: toError(err) };
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* For TOTP this resolves immediately and sends nothing: the code already lives
|
|
50
|
+
* on the user's device. Pass `channel` to send a second-factor code by email
|
|
51
|
+
* or SMS instead, when the project has that enabled.
|
|
52
|
+
*/
|
|
53
|
+
async challenge(params = {}) {
|
|
54
|
+
if (!params.channel) {
|
|
55
|
+
return { data: { id: params.factorId ?? 'totp', expires_at: null }, error: null };
|
|
56
|
+
}
|
|
57
|
+
try {
|
|
58
|
+
await this.http.request(R.sendOtp, { method: 'POST', body: {}, raw: true });
|
|
59
|
+
return { data: { id: params.factorId ?? 'otp', expires_at: null }, error: null };
|
|
60
|
+
}
|
|
61
|
+
catch (err) {
|
|
62
|
+
return { data: null, error: toError(err) };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Verify a code. `code` is a TOTP code by default; set `type` to `otp` for an
|
|
67
|
+
* emailed or texted second factor, or `backup` to spend a recovery code.
|
|
68
|
+
*/
|
|
69
|
+
async verify(params) {
|
|
70
|
+
// All three routes take the code under the same key.
|
|
71
|
+
const route = params.type === 'backup' ? R.verifyBackupCode : params.type === 'otp' ? R.verifyOtp : R.verifyTotp;
|
|
72
|
+
try {
|
|
73
|
+
await this.http.request(route, {
|
|
74
|
+
method: 'POST',
|
|
75
|
+
body: { code: params.code, ...(params.trustDevice ? { trustDevice: true } : {}) },
|
|
76
|
+
raw: true,
|
|
77
|
+
});
|
|
78
|
+
// Verification can hand back a stepped-up session; adopt it before the
|
|
79
|
+
// caller makes its next request with the old one.
|
|
80
|
+
await this.onVerified();
|
|
81
|
+
return { data: { verified: true }, error: null };
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
return { data: null, error: toError(err) };
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/** Turn two-factor off. Requires the password, as enabling did. */
|
|
88
|
+
async unenroll(params) {
|
|
89
|
+
try {
|
|
90
|
+
await this.http.request(R.disable, { method: 'POST', body: { password: params.password }, raw: true });
|
|
91
|
+
return { data: { id: params.factorId ?? 'totp' }, error: null };
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
return { data: null, error: toError(err) };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** Issue a fresh set of backup codes, invalidating the previous set. */
|
|
98
|
+
async regenerateBackupCodes(params) {
|
|
99
|
+
try {
|
|
100
|
+
const payload = await this.http.request(R.generateBackupCodes, {
|
|
101
|
+
method: 'POST',
|
|
102
|
+
body: { password: params.password },
|
|
103
|
+
raw: true,
|
|
104
|
+
});
|
|
105
|
+
return { data: { backupCodes: payload.backupCodes ?? [] }, error: null };
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
return { data: null, error: toError(err) };
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* The user's factors. Reads the TOTP URI: getting one back means TOTP is
|
|
113
|
+
* enrolled, a failure means it is not. There is no list endpoint to call
|
|
114
|
+
* because there is no list, and inventing one client-side would be a lie about
|
|
115
|
+
* what the server models.
|
|
116
|
+
*/
|
|
117
|
+
async listFactors() {
|
|
118
|
+
try {
|
|
119
|
+
await this.http.request(R.totpUri, { method: 'POST', body: {}, raw: true });
|
|
120
|
+
const factor = { id: 'totp', factor_type: 'totp', status: 'verified', friendly_name: 'TOTP' };
|
|
121
|
+
return { data: { totp: [factor], all: [factor] }, error: null };
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Not enrolled is a normal state, not an error the caller should branch on.
|
|
125
|
+
return { data: { totp: [], all: [] }, error: null };
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
/** Pull the `secret` query parameter out of an otpauth:// URI. */
|
|
130
|
+
function secretFromUri(uri) {
|
|
131
|
+
const match = /[?&]secret=([^&]+)/i.exec(uri);
|
|
132
|
+
return match ? decodeURIComponent(match[1]) : '';
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=mfa.js.map
|
package/dist/mfa.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mfa.js","sourceRoot":"","sources":["../src/mfa.ts"],"names":[],"mappings":"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"}
|