@ai-matrx/auth 0.0.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +32 -0
- package/LICENSE +21 -0
- package/README.md +31 -1
- package/dist/auth-cookie-DWx6Q3xo.d.cts +168 -0
- package/dist/auth-cookie-DWx6Q3xo.d.ts +168 -0
- package/dist/cookies.cjs +233 -0
- package/dist/cookies.d.cts +109 -0
- package/dist/cookies.d.ts +109 -0
- package/dist/cookies.js +210 -0
- package/dist/credentials.cjs +68 -0
- package/dist/credentials.d.cts +82 -0
- package/dist/credentials.d.ts +82 -0
- package/dist/credentials.js +47 -0
- package/dist/index.cjs +189 -0
- package/dist/index.d.cts +86 -0
- package/dist/index.d.ts +86 -0
- package/dist/index.js +166 -0
- package/dist/next.cjs +655 -0
- package/dist/next.d.cts +389 -0
- package/dist/next.d.ts +389 -0
- package/dist/next.js +637 -0
- package/dist/node.cjs +61 -0
- package/dist/node.d.cts +33 -0
- package/dist/node.d.ts +33 -0
- package/dist/node.js +36 -0
- package/dist/organizations.cjs +389 -0
- package/dist/organizations.d.cts +226 -0
- package/dist/organizations.d.ts +226 -0
- package/dist/organizations.js +366 -0
- package/dist/react.cjs +206 -0
- package/dist/react.d.cts +163 -0
- package/dist/react.d.ts +163 -0
- package/dist/react.js +186 -0
- package/dist/session-DhRO4euL.d.cts +102 -0
- package/dist/session-DhRO4euL.d.ts +102 -0
- package/dist/session-identity.cjs +125 -0
- package/dist/session-identity.d.cts +100 -0
- package/dist/session-identity.d.ts +100 -0
- package/dist/session-identity.js +104 -0
- package/dist/testing.cjs +67 -0
- package/dist/testing.d.cts +38 -0
- package/dist/testing.d.ts +38 -0
- package/dist/testing.js +46 -0
- package/package.json +186 -6
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// src/credentials.ts
|
|
2
|
+
var MATRX_HEADERS = {
|
|
3
|
+
authorization: "Authorization",
|
|
4
|
+
fingerprint: "X-Fingerprint-ID",
|
|
5
|
+
organization: "X-Organization-Id",
|
|
6
|
+
actingUser: "X-Matrx-User-Id",
|
|
7
|
+
requestId: "X-Request-Id"
|
|
8
|
+
};
|
|
9
|
+
var API_KEY_PREFIX = "mx_";
|
|
10
|
+
function credentialToHeaders(credential) {
|
|
11
|
+
if (credential === null) return {};
|
|
12
|
+
switch (credential.kind) {
|
|
13
|
+
case "user":
|
|
14
|
+
return { [MATRX_HEADERS.authorization]: `Bearer ${credential.accessToken}` };
|
|
15
|
+
case "guest":
|
|
16
|
+
return { [MATRX_HEADERS.fingerprint]: credential.fingerprintId };
|
|
17
|
+
case "scoped":
|
|
18
|
+
return { [MATRX_HEADERS.authorization]: `Bearer ${credential.token}` };
|
|
19
|
+
case "service": {
|
|
20
|
+
const header = credential.secretHeader ?? MATRX_HEADERS.authorization;
|
|
21
|
+
const headers = header.toLowerCase() === "authorization" ? { [MATRX_HEADERS.authorization]: `Bearer ${credential.secret}` } : { [header]: credential.secret };
|
|
22
|
+
if (credential.actingUserId) headers[MATRX_HEADERS.actingUser] = credential.actingUserId;
|
|
23
|
+
return headers;
|
|
24
|
+
}
|
|
25
|
+
case "api_key": {
|
|
26
|
+
if (!credential.apiKey.startsWith(API_KEY_PREFIX)) {
|
|
27
|
+
throw new Error(
|
|
28
|
+
`credentialToHeaders: an api_key credential must start with "${API_KEY_PREFIX}" (AI Matrx API keys look like mx_live_...)`
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
return { [MATRX_HEADERS.authorization]: `Bearer ${credential.apiKey}` };
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function toCredentialsPort(setting) {
|
|
36
|
+
if (setting === void 0 || setting === null) return { get: async () => null };
|
|
37
|
+
if (typeof setting === "function") return { get: async () => setting() };
|
|
38
|
+
if ("get" in setting && typeof setting.get === "function") return setting;
|
|
39
|
+
const fixed = setting;
|
|
40
|
+
return { get: async () => fixed };
|
|
41
|
+
}
|
|
42
|
+
export {
|
|
43
|
+
API_KEY_PREFIX,
|
|
44
|
+
MATRX_HEADERS,
|
|
45
|
+
credentialToHeaders,
|
|
46
|
+
toCredentialsPort
|
|
47
|
+
};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var src_exports = {};
|
|
22
|
+
__export(src_exports, {
|
|
23
|
+
SecretKeyRefusedError: () => SecretKeyRefusedError,
|
|
24
|
+
SignInError: () => SignInError,
|
|
25
|
+
StorageUnavailableError: () => StorageUnavailableError,
|
|
26
|
+
browserStorage: () => browserStorage,
|
|
27
|
+
createAuthClient: () => createAuthClient,
|
|
28
|
+
extensionStorage: () => extensionStorage,
|
|
29
|
+
getPerson: () => getPerson,
|
|
30
|
+
getSession: () => getSession,
|
|
31
|
+
keyValueStorage: () => keyValueStorage,
|
|
32
|
+
memoryStorage: () => memoryStorage,
|
|
33
|
+
onSessionChange: () => onSessionChange,
|
|
34
|
+
refreshSession: () => refreshSession,
|
|
35
|
+
sessionCredentials: () => sessionCredentials,
|
|
36
|
+
signInWithOAuth: () => signInWithOAuth,
|
|
37
|
+
signInWithPassword: () => signInWithPassword,
|
|
38
|
+
signOut: () => signOut,
|
|
39
|
+
updatePerson: () => updatePerson,
|
|
40
|
+
userCredentials: () => userCredentials
|
|
41
|
+
});
|
|
42
|
+
module.exports = __toCommonJS(src_exports);
|
|
43
|
+
|
|
44
|
+
// src/session.ts
|
|
45
|
+
var SignInError = class extends Error {
|
|
46
|
+
door;
|
|
47
|
+
status;
|
|
48
|
+
code;
|
|
49
|
+
constructor(door, message, status, code) {
|
|
50
|
+
super(`${door}: ${message}`);
|
|
51
|
+
this.name = "SignInError";
|
|
52
|
+
this.door = door;
|
|
53
|
+
if (status !== void 0) this.status = status;
|
|
54
|
+
if (code !== void 0) this.code = code;
|
|
55
|
+
}
|
|
56
|
+
};
|
|
57
|
+
function check(door, data, error) {
|
|
58
|
+
if (error) throw new SignInError(door, error.message, error.status, error.code);
|
|
59
|
+
return data;
|
|
60
|
+
}
|
|
61
|
+
async function getSession(client) {
|
|
62
|
+
const { data, error } = await client.auth.getSession();
|
|
63
|
+
return check("getSession", data, error).session;
|
|
64
|
+
}
|
|
65
|
+
async function getPerson(client) {
|
|
66
|
+
const { data, error } = await client.auth.getUser();
|
|
67
|
+
if (error && (error.name === "AuthSessionMissingError" || error.status === 401)) return null;
|
|
68
|
+
return check("getPerson", data, error).user;
|
|
69
|
+
}
|
|
70
|
+
function onSessionChange(client, cb) {
|
|
71
|
+
const { data } = client.auth.onAuthStateChange(cb);
|
|
72
|
+
return () => data.subscription.unsubscribe();
|
|
73
|
+
}
|
|
74
|
+
async function signInWithPassword(client, credentials) {
|
|
75
|
+
const { data, error } = await client.auth.signInWithPassword(credentials);
|
|
76
|
+
const ok = check("signInWithPassword", data, error);
|
|
77
|
+
return { session: ok.session, person: ok.user };
|
|
78
|
+
}
|
|
79
|
+
async function signInWithOAuth(client, options) {
|
|
80
|
+
const { provider, ...rest } = options;
|
|
81
|
+
const { data, error } = await client.auth.signInWithOAuth({ provider, options: rest });
|
|
82
|
+
const ok = check("signInWithOAuth", data, error);
|
|
83
|
+
return { provider: ok.provider, url: ok.url ?? null };
|
|
84
|
+
}
|
|
85
|
+
async function signOut(client, scope = "global") {
|
|
86
|
+
const { error } = await client.auth.signOut({ scope });
|
|
87
|
+
check("signOut", null, error);
|
|
88
|
+
}
|
|
89
|
+
async function updatePerson(client, attributes) {
|
|
90
|
+
const { data, error } = await client.auth.updateUser(attributes);
|
|
91
|
+
return check("updatePerson", data, error).user;
|
|
92
|
+
}
|
|
93
|
+
function sessionCredentials(client) {
|
|
94
|
+
return {
|
|
95
|
+
async get() {
|
|
96
|
+
if (!client.auth) return null;
|
|
97
|
+
const { data } = await client.auth.getSession();
|
|
98
|
+
return data.session ? { kind: "user", accessToken: data.session.access_token } : null;
|
|
99
|
+
},
|
|
100
|
+
onChange(cb) {
|
|
101
|
+
if (!client.auth) return () => {
|
|
102
|
+
};
|
|
103
|
+
const { data } = client.auth.onAuthStateChange(() => cb());
|
|
104
|
+
return () => data.subscription.unsubscribe();
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
var userCredentials = sessionCredentials;
|
|
109
|
+
async function refreshSession(client) {
|
|
110
|
+
const { data, error } = await client.auth.refreshSession();
|
|
111
|
+
const ok = check("refreshSession", data, error);
|
|
112
|
+
if (!ok.session) throw new SignInError("refreshSession", "no session came back from the refresh");
|
|
113
|
+
return ok.session;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// src/storage.ts
|
|
117
|
+
var StorageUnavailableError = class extends Error {
|
|
118
|
+
storage;
|
|
119
|
+
constructor(storage, reason) {
|
|
120
|
+
super(`${storage} session storage is not available here: ${reason}`);
|
|
121
|
+
this.name = "StorageUnavailableError";
|
|
122
|
+
this.storage = storage;
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
function memoryStorage() {
|
|
126
|
+
const items = /* @__PURE__ */ new Map();
|
|
127
|
+
return {
|
|
128
|
+
getItem: (key) => items.get(key) ?? null,
|
|
129
|
+
setItem: (key, value) => {
|
|
130
|
+
items.set(key, value);
|
|
131
|
+
},
|
|
132
|
+
removeItem: (key) => {
|
|
133
|
+
items.delete(key);
|
|
134
|
+
},
|
|
135
|
+
size: () => items.size
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function browserStorage(kind = "local") {
|
|
139
|
+
const name = kind === "local" ? "localStorage" : "sessionStorage";
|
|
140
|
+
const store = globalThis[name];
|
|
141
|
+
if (!store) throw new StorageUnavailableError(name, "this runtime has no window storage (server, worker or Node)");
|
|
142
|
+
return {
|
|
143
|
+
getItem: (key) => store.getItem(key),
|
|
144
|
+
setItem: (key, value) => store.setItem(key, value),
|
|
145
|
+
removeItem: (key) => store.removeItem(key)
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
function extensionStorage(area) {
|
|
149
|
+
const chromeLike = globalThis.chrome;
|
|
150
|
+
const store = area ?? chromeLike?.storage?.local;
|
|
151
|
+
if (!store) throw new StorageUnavailableError("chrome.storage.local", "this is not a browser extension context");
|
|
152
|
+
return {
|
|
153
|
+
getItem: async (key) => {
|
|
154
|
+
const value = (await store.get(key))[key];
|
|
155
|
+
return typeof value === "string" ? value : null;
|
|
156
|
+
},
|
|
157
|
+
setItem: async (key, value) => {
|
|
158
|
+
await store.set({ [key]: value });
|
|
159
|
+
},
|
|
160
|
+
removeItem: async (key) => {
|
|
161
|
+
await store.remove(key);
|
|
162
|
+
}
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
function keyValueStorage(store) {
|
|
166
|
+
return {
|
|
167
|
+
getItem: async (key) => await store.get(key) ?? null,
|
|
168
|
+
setItem: (key, value) => store.set(key, value),
|
|
169
|
+
removeItem: (key) => store.remove(key)
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/client.ts
|
|
174
|
+
var import_supabase_js = require("@supabase/supabase-js");
|
|
175
|
+
var SecretKeyRefusedError = class extends Error {
|
|
176
|
+
constructor() {
|
|
177
|
+
super("createAuthClient: a secret (service-role) key signs in nobody \u2014 pass the publishable key");
|
|
178
|
+
this.name = "SecretKeyRefusedError";
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
function createAuthClient(options) {
|
|
182
|
+
if (/^sb_secret_/.test(options.key)) throw new SecretKeyRefusedError();
|
|
183
|
+
const persist = options.persist ?? true;
|
|
184
|
+
const auth = { persistSession: persist, autoRefreshToken: persist };
|
|
185
|
+
if (options.storage) auth["storage"] = options.storage;
|
|
186
|
+
if (options.storageKey) auth["storageKey"] = options.storageKey;
|
|
187
|
+
if (options.detectSessionInUrl !== void 0) auth["detectSessionInUrl"] = options.detectSessionInUrl;
|
|
188
|
+
return (0, import_supabase_js.createClient)(options.url, options.key, { auth });
|
|
189
|
+
}
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export { A as AuthClient, S as SessionSourceLike, a as SignInError, U as UserCredentialsPort, g as getPerson, b as getSession, o as onSessionChange, r as refreshSession, s as sessionCredentials, c as signInWithOAuth, d as signInWithPassword, e as signOut, u as updatePerson, f as userCredentials } from './session-DhRO4euL.cjs';
|
|
2
|
+
import { SupabaseClient } from '@supabase/supabase-js';
|
|
3
|
+
export { AuthChangeEvent, Session, User, UserAttributes } from '@supabase/supabase-js';
|
|
4
|
+
export { CredentialsPort, MatrxCredential, MatrxCredentialKind } from './credentials.cjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Session storage per platform — where a Supabase session lives between runs.
|
|
8
|
+
*
|
|
9
|
+
* supabase-js takes any `{ getItem, setItem, removeItem }` (sync or async). These are the ones
|
|
10
|
+
* every Matrx client needs, written once:
|
|
11
|
+
*
|
|
12
|
+
* browser — `browserStorage("local")` (supabase-js's own default; `"session"` = this tab only)
|
|
13
|
+
* Next.js — the cookie-backed clients in `@ai-matrx/auth/next` (the domain-wide auth cookie)
|
|
14
|
+
* extension — `extensionStorage()` over `chrome.storage.local` (shared by popup, side panel and
|
|
15
|
+
* service worker; `localStorage` does not exist in a service worker)
|
|
16
|
+
* desktop — `keyValueStorage({ get, set, remove })` over the host's store (Tauri store, keychain)
|
|
17
|
+
* Node — `fileStorage(path)` in `@ai-matrx/auth/node`, or `memoryStorage()` for a one-shot run
|
|
18
|
+
*
|
|
19
|
+
* None of these is ever silently swapped for another: a storage the platform does not have throws
|
|
20
|
+
* a named error at creation, never a quiet in-memory fallback that signs the person out on reload.
|
|
21
|
+
*/
|
|
22
|
+
/** The storage contract supabase-js reads (sync or async methods). */
|
|
23
|
+
interface SessionStorage {
|
|
24
|
+
getItem(key: string): string | null | Promise<string | null>;
|
|
25
|
+
setItem(key: string, value: string): void | Promise<void>;
|
|
26
|
+
removeItem(key: string): void | Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
declare class StorageUnavailableError extends Error {
|
|
29
|
+
readonly storage: string;
|
|
30
|
+
constructor(storage: string, reason: string);
|
|
31
|
+
}
|
|
32
|
+
/** In memory only: the session ends with the process (one-shot scripts, tests, server renders). */
|
|
33
|
+
declare function memoryStorage(): SessionStorage & {
|
|
34
|
+
readonly size: () => number;
|
|
35
|
+
};
|
|
36
|
+
/** The browser's `localStorage` (shared by every tab of the origin) or `sessionStorage` (this tab). */
|
|
37
|
+
declare function browserStorage(kind?: "local" | "session"): SessionStorage;
|
|
38
|
+
/** The structural slice of `chrome.storage.<area>` read here (MV3 promise API). */
|
|
39
|
+
interface ChromeStorageAreaLike {
|
|
40
|
+
get(keys: string): Promise<Record<string, unknown>>;
|
|
41
|
+
set(items: Record<string, unknown>): Promise<void>;
|
|
42
|
+
remove(keys: string): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A browser extension's `chrome.storage` area (default `local`): one session for the popup, side
|
|
46
|
+
* panel, content scripts' relay and the service worker. Pass `area` to inject one (tests, Firefox).
|
|
47
|
+
*/
|
|
48
|
+
declare function extensionStorage(area?: ChromeStorageAreaLike): SessionStorage;
|
|
49
|
+
/** Any async key-value store the host owns (a desktop app's Tauri store or keychain). */
|
|
50
|
+
declare function keyValueStorage(store: {
|
|
51
|
+
get(key: string): Promise<string | null | undefined>;
|
|
52
|
+
set(key: string, value: string): Promise<void>;
|
|
53
|
+
remove(key: string): Promise<void>;
|
|
54
|
+
}): SessionStorage;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* `createAuthClient` — the one Supabase client factory OUTSIDE Next.js (Next apps use
|
|
58
|
+
* `@ai-matrx/auth/next`, whose cookie clients carry the domain-wide auth cookie).
|
|
59
|
+
*
|
|
60
|
+
* const supabase = createAuthClient({ url, key, storage: extensionStorage() });
|
|
61
|
+
*
|
|
62
|
+
* The session persists in `storage` and refreshes itself (`autoRefreshToken`) unless `persist`
|
|
63
|
+
* is false (a one-shot script). The same client is what `@ai-matrx/data` and
|
|
64
|
+
* `@ai-matrx/api` (through `sessionCredentials`) read — one sign-in drives all three.
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
interface CreateAuthClientOptions {
|
|
68
|
+
/** The database URL (always `https://db.matrxserver.com` for the platform). */
|
|
69
|
+
readonly url: string;
|
|
70
|
+
/** The publishable key. Never a secret key: that is a service role, not a person. */
|
|
71
|
+
readonly key: string;
|
|
72
|
+
/** Where the session lives. Default: supabase-js's own (browser `localStorage`). */
|
|
73
|
+
readonly storage?: SessionStorage | undefined;
|
|
74
|
+
/** The storage key (default: supabase-js's per-project key). */
|
|
75
|
+
readonly storageKey?: string | undefined;
|
|
76
|
+
/** False = sign in for this run only: no storage write, no background refresh. Default true. */
|
|
77
|
+
readonly persist?: boolean | undefined;
|
|
78
|
+
/** Read OAuth / magic-link tokens from the URL on load (browser apps). Default: supabase-js's. */
|
|
79
|
+
readonly detectSessionInUrl?: boolean | undefined;
|
|
80
|
+
}
|
|
81
|
+
declare class SecretKeyRefusedError extends Error {
|
|
82
|
+
constructor();
|
|
83
|
+
}
|
|
84
|
+
declare function createAuthClient<Database = any>(options: CreateAuthClientOptions): SupabaseClient<Database>;
|
|
85
|
+
|
|
86
|
+
export { type ChromeStorageAreaLike, type CreateAuthClientOptions, SecretKeyRefusedError, type SessionStorage, StorageUnavailableError, browserStorage, createAuthClient, extensionStorage, keyValueStorage, memoryStorage };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
export { A as AuthClient, S as SessionSourceLike, a as SignInError, U as UserCredentialsPort, g as getPerson, b as getSession, o as onSessionChange, r as refreshSession, s as sessionCredentials, c as signInWithOAuth, d as signInWithPassword, e as signOut, u as updatePerson, f as userCredentials } from './session-DhRO4euL.js';
|
|
2
|
+
import { SupabaseClient } from '@supabase/supabase-js';
|
|
3
|
+
export { AuthChangeEvent, Session, User, UserAttributes } from '@supabase/supabase-js';
|
|
4
|
+
export { CredentialsPort, MatrxCredential, MatrxCredentialKind } from './credentials.js';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Session storage per platform — where a Supabase session lives between runs.
|
|
8
|
+
*
|
|
9
|
+
* supabase-js takes any `{ getItem, setItem, removeItem }` (sync or async). These are the ones
|
|
10
|
+
* every Matrx client needs, written once:
|
|
11
|
+
*
|
|
12
|
+
* browser — `browserStorage("local")` (supabase-js's own default; `"session"` = this tab only)
|
|
13
|
+
* Next.js — the cookie-backed clients in `@ai-matrx/auth/next` (the domain-wide auth cookie)
|
|
14
|
+
* extension — `extensionStorage()` over `chrome.storage.local` (shared by popup, side panel and
|
|
15
|
+
* service worker; `localStorage` does not exist in a service worker)
|
|
16
|
+
* desktop — `keyValueStorage({ get, set, remove })` over the host's store (Tauri store, keychain)
|
|
17
|
+
* Node — `fileStorage(path)` in `@ai-matrx/auth/node`, or `memoryStorage()` for a one-shot run
|
|
18
|
+
*
|
|
19
|
+
* None of these is ever silently swapped for another: a storage the platform does not have throws
|
|
20
|
+
* a named error at creation, never a quiet in-memory fallback that signs the person out on reload.
|
|
21
|
+
*/
|
|
22
|
+
/** The storage contract supabase-js reads (sync or async methods). */
|
|
23
|
+
interface SessionStorage {
|
|
24
|
+
getItem(key: string): string | null | Promise<string | null>;
|
|
25
|
+
setItem(key: string, value: string): void | Promise<void>;
|
|
26
|
+
removeItem(key: string): void | Promise<void>;
|
|
27
|
+
}
|
|
28
|
+
declare class StorageUnavailableError extends Error {
|
|
29
|
+
readonly storage: string;
|
|
30
|
+
constructor(storage: string, reason: string);
|
|
31
|
+
}
|
|
32
|
+
/** In memory only: the session ends with the process (one-shot scripts, tests, server renders). */
|
|
33
|
+
declare function memoryStorage(): SessionStorage & {
|
|
34
|
+
readonly size: () => number;
|
|
35
|
+
};
|
|
36
|
+
/** The browser's `localStorage` (shared by every tab of the origin) or `sessionStorage` (this tab). */
|
|
37
|
+
declare function browserStorage(kind?: "local" | "session"): SessionStorage;
|
|
38
|
+
/** The structural slice of `chrome.storage.<area>` read here (MV3 promise API). */
|
|
39
|
+
interface ChromeStorageAreaLike {
|
|
40
|
+
get(keys: string): Promise<Record<string, unknown>>;
|
|
41
|
+
set(items: Record<string, unknown>): Promise<void>;
|
|
42
|
+
remove(keys: string): Promise<void>;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* A browser extension's `chrome.storage` area (default `local`): one session for the popup, side
|
|
46
|
+
* panel, content scripts' relay and the service worker. Pass `area` to inject one (tests, Firefox).
|
|
47
|
+
*/
|
|
48
|
+
declare function extensionStorage(area?: ChromeStorageAreaLike): SessionStorage;
|
|
49
|
+
/** Any async key-value store the host owns (a desktop app's Tauri store or keychain). */
|
|
50
|
+
declare function keyValueStorage(store: {
|
|
51
|
+
get(key: string): Promise<string | null | undefined>;
|
|
52
|
+
set(key: string, value: string): Promise<void>;
|
|
53
|
+
remove(key: string): Promise<void>;
|
|
54
|
+
}): SessionStorage;
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* `createAuthClient` — the one Supabase client factory OUTSIDE Next.js (Next apps use
|
|
58
|
+
* `@ai-matrx/auth/next`, whose cookie clients carry the domain-wide auth cookie).
|
|
59
|
+
*
|
|
60
|
+
* const supabase = createAuthClient({ url, key, storage: extensionStorage() });
|
|
61
|
+
*
|
|
62
|
+
* The session persists in `storage` and refreshes itself (`autoRefreshToken`) unless `persist`
|
|
63
|
+
* is false (a one-shot script). The same client is what `@ai-matrx/data` and
|
|
64
|
+
* `@ai-matrx/api` (through `sessionCredentials`) read — one sign-in drives all three.
|
|
65
|
+
*/
|
|
66
|
+
|
|
67
|
+
interface CreateAuthClientOptions {
|
|
68
|
+
/** The database URL (always `https://db.matrxserver.com` for the platform). */
|
|
69
|
+
readonly url: string;
|
|
70
|
+
/** The publishable key. Never a secret key: that is a service role, not a person. */
|
|
71
|
+
readonly key: string;
|
|
72
|
+
/** Where the session lives. Default: supabase-js's own (browser `localStorage`). */
|
|
73
|
+
readonly storage?: SessionStorage | undefined;
|
|
74
|
+
/** The storage key (default: supabase-js's per-project key). */
|
|
75
|
+
readonly storageKey?: string | undefined;
|
|
76
|
+
/** False = sign in for this run only: no storage write, no background refresh. Default true. */
|
|
77
|
+
readonly persist?: boolean | undefined;
|
|
78
|
+
/** Read OAuth / magic-link tokens from the URL on load (browser apps). Default: supabase-js's. */
|
|
79
|
+
readonly detectSessionInUrl?: boolean | undefined;
|
|
80
|
+
}
|
|
81
|
+
declare class SecretKeyRefusedError extends Error {
|
|
82
|
+
constructor();
|
|
83
|
+
}
|
|
84
|
+
declare function createAuthClient<Database = any>(options: CreateAuthClientOptions): SupabaseClient<Database>;
|
|
85
|
+
|
|
86
|
+
export { type ChromeStorageAreaLike, type CreateAuthClientOptions, SecretKeyRefusedError, type SessionStorage, StorageUnavailableError, browserStorage, createAuthClient, extensionStorage, keyValueStorage, memoryStorage };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
// src/session.ts
|
|
2
|
+
var SignInError = class extends Error {
|
|
3
|
+
door;
|
|
4
|
+
status;
|
|
5
|
+
code;
|
|
6
|
+
constructor(door, message, status, code) {
|
|
7
|
+
super(`${door}: ${message}`);
|
|
8
|
+
this.name = "SignInError";
|
|
9
|
+
this.door = door;
|
|
10
|
+
if (status !== void 0) this.status = status;
|
|
11
|
+
if (code !== void 0) this.code = code;
|
|
12
|
+
}
|
|
13
|
+
};
|
|
14
|
+
function check(door, data, error) {
|
|
15
|
+
if (error) throw new SignInError(door, error.message, error.status, error.code);
|
|
16
|
+
return data;
|
|
17
|
+
}
|
|
18
|
+
async function getSession(client) {
|
|
19
|
+
const { data, error } = await client.auth.getSession();
|
|
20
|
+
return check("getSession", data, error).session;
|
|
21
|
+
}
|
|
22
|
+
async function getPerson(client) {
|
|
23
|
+
const { data, error } = await client.auth.getUser();
|
|
24
|
+
if (error && (error.name === "AuthSessionMissingError" || error.status === 401)) return null;
|
|
25
|
+
return check("getPerson", data, error).user;
|
|
26
|
+
}
|
|
27
|
+
function onSessionChange(client, cb) {
|
|
28
|
+
const { data } = client.auth.onAuthStateChange(cb);
|
|
29
|
+
return () => data.subscription.unsubscribe();
|
|
30
|
+
}
|
|
31
|
+
async function signInWithPassword(client, credentials) {
|
|
32
|
+
const { data, error } = await client.auth.signInWithPassword(credentials);
|
|
33
|
+
const ok = check("signInWithPassword", data, error);
|
|
34
|
+
return { session: ok.session, person: ok.user };
|
|
35
|
+
}
|
|
36
|
+
async function signInWithOAuth(client, options) {
|
|
37
|
+
const { provider, ...rest } = options;
|
|
38
|
+
const { data, error } = await client.auth.signInWithOAuth({ provider, options: rest });
|
|
39
|
+
const ok = check("signInWithOAuth", data, error);
|
|
40
|
+
return { provider: ok.provider, url: ok.url ?? null };
|
|
41
|
+
}
|
|
42
|
+
async function signOut(client, scope = "global") {
|
|
43
|
+
const { error } = await client.auth.signOut({ scope });
|
|
44
|
+
check("signOut", null, error);
|
|
45
|
+
}
|
|
46
|
+
async function updatePerson(client, attributes) {
|
|
47
|
+
const { data, error } = await client.auth.updateUser(attributes);
|
|
48
|
+
return check("updatePerson", data, error).user;
|
|
49
|
+
}
|
|
50
|
+
function sessionCredentials(client) {
|
|
51
|
+
return {
|
|
52
|
+
async get() {
|
|
53
|
+
if (!client.auth) return null;
|
|
54
|
+
const { data } = await client.auth.getSession();
|
|
55
|
+
return data.session ? { kind: "user", accessToken: data.session.access_token } : null;
|
|
56
|
+
},
|
|
57
|
+
onChange(cb) {
|
|
58
|
+
if (!client.auth) return () => {
|
|
59
|
+
};
|
|
60
|
+
const { data } = client.auth.onAuthStateChange(() => cb());
|
|
61
|
+
return () => data.subscription.unsubscribe();
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
var userCredentials = sessionCredentials;
|
|
66
|
+
async function refreshSession(client) {
|
|
67
|
+
const { data, error } = await client.auth.refreshSession();
|
|
68
|
+
const ok = check("refreshSession", data, error);
|
|
69
|
+
if (!ok.session) throw new SignInError("refreshSession", "no session came back from the refresh");
|
|
70
|
+
return ok.session;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// src/storage.ts
|
|
74
|
+
var StorageUnavailableError = class extends Error {
|
|
75
|
+
storage;
|
|
76
|
+
constructor(storage, reason) {
|
|
77
|
+
super(`${storage} session storage is not available here: ${reason}`);
|
|
78
|
+
this.name = "StorageUnavailableError";
|
|
79
|
+
this.storage = storage;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
function memoryStorage() {
|
|
83
|
+
const items = /* @__PURE__ */ new Map();
|
|
84
|
+
return {
|
|
85
|
+
getItem: (key) => items.get(key) ?? null,
|
|
86
|
+
setItem: (key, value) => {
|
|
87
|
+
items.set(key, value);
|
|
88
|
+
},
|
|
89
|
+
removeItem: (key) => {
|
|
90
|
+
items.delete(key);
|
|
91
|
+
},
|
|
92
|
+
size: () => items.size
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function browserStorage(kind = "local") {
|
|
96
|
+
const name = kind === "local" ? "localStorage" : "sessionStorage";
|
|
97
|
+
const store = globalThis[name];
|
|
98
|
+
if (!store) throw new StorageUnavailableError(name, "this runtime has no window storage (server, worker or Node)");
|
|
99
|
+
return {
|
|
100
|
+
getItem: (key) => store.getItem(key),
|
|
101
|
+
setItem: (key, value) => store.setItem(key, value),
|
|
102
|
+
removeItem: (key) => store.removeItem(key)
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
function extensionStorage(area) {
|
|
106
|
+
const chromeLike = globalThis.chrome;
|
|
107
|
+
const store = area ?? chromeLike?.storage?.local;
|
|
108
|
+
if (!store) throw new StorageUnavailableError("chrome.storage.local", "this is not a browser extension context");
|
|
109
|
+
return {
|
|
110
|
+
getItem: async (key) => {
|
|
111
|
+
const value = (await store.get(key))[key];
|
|
112
|
+
return typeof value === "string" ? value : null;
|
|
113
|
+
},
|
|
114
|
+
setItem: async (key, value) => {
|
|
115
|
+
await store.set({ [key]: value });
|
|
116
|
+
},
|
|
117
|
+
removeItem: async (key) => {
|
|
118
|
+
await store.remove(key);
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function keyValueStorage(store) {
|
|
123
|
+
return {
|
|
124
|
+
getItem: async (key) => await store.get(key) ?? null,
|
|
125
|
+
setItem: (key, value) => store.set(key, value),
|
|
126
|
+
removeItem: (key) => store.remove(key)
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// src/client.ts
|
|
131
|
+
import { createClient } from "@supabase/supabase-js";
|
|
132
|
+
var SecretKeyRefusedError = class extends Error {
|
|
133
|
+
constructor() {
|
|
134
|
+
super("createAuthClient: a secret (service-role) key signs in nobody \u2014 pass the publishable key");
|
|
135
|
+
this.name = "SecretKeyRefusedError";
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
function createAuthClient(options) {
|
|
139
|
+
if (/^sb_secret_/.test(options.key)) throw new SecretKeyRefusedError();
|
|
140
|
+
const persist = options.persist ?? true;
|
|
141
|
+
const auth = { persistSession: persist, autoRefreshToken: persist };
|
|
142
|
+
if (options.storage) auth["storage"] = options.storage;
|
|
143
|
+
if (options.storageKey) auth["storageKey"] = options.storageKey;
|
|
144
|
+
if (options.detectSessionInUrl !== void 0) auth["detectSessionInUrl"] = options.detectSessionInUrl;
|
|
145
|
+
return createClient(options.url, options.key, { auth });
|
|
146
|
+
}
|
|
147
|
+
export {
|
|
148
|
+
SecretKeyRefusedError,
|
|
149
|
+
SignInError,
|
|
150
|
+
StorageUnavailableError,
|
|
151
|
+
browserStorage,
|
|
152
|
+
createAuthClient,
|
|
153
|
+
extensionStorage,
|
|
154
|
+
getPerson,
|
|
155
|
+
getSession,
|
|
156
|
+
keyValueStorage,
|
|
157
|
+
memoryStorage,
|
|
158
|
+
onSessionChange,
|
|
159
|
+
refreshSession,
|
|
160
|
+
sessionCredentials,
|
|
161
|
+
signInWithOAuth,
|
|
162
|
+
signInWithPassword,
|
|
163
|
+
signOut,
|
|
164
|
+
updatePerson,
|
|
165
|
+
userCredentials
|
|
166
|
+
};
|