@sentroy-co/client-sdk 2.13.7 → 2.13.9
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/auth/admin/index.d.ts +153 -0
- package/dist/auth/admin/index.d.ts.map +1 -0
- package/dist/auth/admin/index.js +228 -0
- package/dist/auth/admin/index.js.map +1 -0
- package/dist/auth/client.d.ts +212 -0
- package/dist/auth/client.d.ts.map +1 -0
- package/dist/auth/client.js +623 -0
- package/dist/auth/client.js.map +1 -0
- package/dist/auth/http.d.ts +19 -0
- package/dist/auth/http.d.ts.map +1 -0
- package/dist/auth/http.js +74 -0
- package/dist/auth/http.js.map +1 -0
- package/dist/auth/index.d.ts +16 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +20 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/react/index.d.ts +100 -0
- package/dist/auth/react/index.d.ts.map +1 -0
- package/dist/auth/react/index.js +231 -0
- package/dist/auth/react/index.js.map +1 -0
- package/dist/auth/types.d.ts +105 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +21 -0
- package/dist/auth/types.js.map +1 -0
- package/package.json +20 -1
- package/src/auth/admin/index.ts +387 -0
- package/src/auth/client.ts +778 -0
- package/src/auth/http.ts +101 -0
- package/src/auth/index.ts +35 -0
- package/src/auth/react/index.tsx +351 -0
- package/src/auth/types.ts +126 -0
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthHttp = void 0;
|
|
4
|
+
const types_1 = require("./types");
|
|
5
|
+
/**
|
|
6
|
+
* Auth-as-a-Service shared HTTP layer. Project's signup/login/refresh
|
|
7
|
+
* endpoints'iyle aynı format (JSON request + JSON response, 401/403/4xx
|
|
8
|
+
* tek-tip `{error, error_description}` shape).
|
|
9
|
+
*
|
|
10
|
+
* `apiKey` opsiyonel — browser SDK end-user akışında apiKey-less
|
|
11
|
+
* (server-only güvenlik), admin SDK her zaman set'li.
|
|
12
|
+
*/
|
|
13
|
+
const DEFAULT_AUTH_BASE_URL = "https://auth.sentroy.com";
|
|
14
|
+
class AuthHttp {
|
|
15
|
+
baseUrl;
|
|
16
|
+
projectSlug;
|
|
17
|
+
apiKey;
|
|
18
|
+
constructor(opts) {
|
|
19
|
+
this.baseUrl = (opts.authBaseUrl || DEFAULT_AUTH_BASE_URL).replace(/\/+$/, "");
|
|
20
|
+
this.projectSlug = opts.projectSlug;
|
|
21
|
+
this.apiKey = opts.apiKey;
|
|
22
|
+
}
|
|
23
|
+
url(path) {
|
|
24
|
+
const p = path.startsWith("/") ? path : `/${path}`;
|
|
25
|
+
return `${this.baseUrl}/api/v1/auth/${this.projectSlug}${p}`;
|
|
26
|
+
}
|
|
27
|
+
async request(path, init = {}) {
|
|
28
|
+
const headers = new Headers(init.headers);
|
|
29
|
+
headers.set("Accept", "application/json");
|
|
30
|
+
if (init.json !== undefined) {
|
|
31
|
+
headers.set("Content-Type", "application/json");
|
|
32
|
+
}
|
|
33
|
+
// Auth precedence: explicit `bearer` (user access token) > project `apiKey`.
|
|
34
|
+
// Caller chooses the one that fits the endpoint.
|
|
35
|
+
if (init.bearer) {
|
|
36
|
+
headers.set("Authorization", `Bearer ${init.bearer}`);
|
|
37
|
+
}
|
|
38
|
+
else if (this.apiKey) {
|
|
39
|
+
headers.set("Authorization", `Bearer ${this.apiKey}`);
|
|
40
|
+
}
|
|
41
|
+
const res = await fetch(this.url(path), {
|
|
42
|
+
...init,
|
|
43
|
+
headers,
|
|
44
|
+
body: init.json !== undefined ? JSON.stringify(init.json) : init.body,
|
|
45
|
+
});
|
|
46
|
+
let payload = null;
|
|
47
|
+
const ct = res.headers.get("content-type") ?? "";
|
|
48
|
+
if (ct.includes("application/json")) {
|
|
49
|
+
try {
|
|
50
|
+
payload = await res.json();
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
payload = null;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
if (!res.ok) {
|
|
57
|
+
const err = payload && typeof payload === "object"
|
|
58
|
+
? payload
|
|
59
|
+
: {};
|
|
60
|
+
throw new types_1.SentroyAuthError(err.error ?? "http_error", err.error_description ?? `HTTP ${res.status}`, res.status);
|
|
61
|
+
}
|
|
62
|
+
// Sentroy admin endpoints wrap in `{data}`; public endpoints sometimes
|
|
63
|
+
// too. SDK auto-unwraps when present so callers don't keep .data on
|
|
64
|
+
// every call.
|
|
65
|
+
if (payload &&
|
|
66
|
+
typeof payload === "object" &&
|
|
67
|
+
"data" in payload) {
|
|
68
|
+
return payload.data;
|
|
69
|
+
}
|
|
70
|
+
return payload;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
exports.AuthHttp = AuthHttp;
|
|
74
|
+
//# sourceMappingURL=http.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http.js","sourceRoot":"","sources":["../../src/auth/http.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentroy Auth-as-a-Service — browser/server SDK entry.
|
|
3
|
+
*
|
|
4
|
+
* import { SentroyAuth } from "@sentroy-co/client-sdk/auth"
|
|
5
|
+
* const auth = new SentroyAuth({ projectSlug: "my-app" })
|
|
6
|
+
*
|
|
7
|
+
* For server admin operations (verifyIdToken, etc):
|
|
8
|
+
* import { SentroyAuthAdmin } from "@sentroy-co/client-sdk/auth/admin"
|
|
9
|
+
*
|
|
10
|
+
* For React integration:
|
|
11
|
+
* import { SentroyAuthProvider, useAuth } from "@sentroy-co/client-sdk/auth/react"
|
|
12
|
+
*/
|
|
13
|
+
export { SentroyAuth } from "./client";
|
|
14
|
+
export type { SentroyAuthOptions, AuthStateChangeListener, AuthStorageAdapter, } from "./client";
|
|
15
|
+
export { SentroyAuthError, type SentroyAuthUser, type SignupResponse, type LoginResponse, type AuthTokensResponse, type LoginOutcome, type MfaChallengeResponse, type SessionSummary, type ActivityEntry, type MfaStatus, type MfaEnrollResponse, type MfaVerifyEnrollmentResponse, type PasskeySummary, type SocialProvider, } from "./types";
|
|
16
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,UAAU,CAAA;AACtC,YAAY,EACV,kBAAkB,EAClB,uBAAuB,EACvB,kBAAkB,GACnB,MAAM,UAAU,CAAA;AACjB,OAAO,EACL,gBAAgB,EAChB,KAAK,eAAe,EACpB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,kBAAkB,EACvB,KAAK,YAAY,EACjB,KAAK,oBAAoB,EACzB,KAAK,cAAc,EACnB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,iBAAiB,EACtB,KAAK,2BAA2B,EAChC,KAAK,cAAc,EACnB,KAAK,cAAc,GACpB,MAAM,SAAS,CAAA"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sentroy Auth-as-a-Service — browser/server SDK entry.
|
|
4
|
+
*
|
|
5
|
+
* import { SentroyAuth } from "@sentroy-co/client-sdk/auth"
|
|
6
|
+
* const auth = new SentroyAuth({ projectSlug: "my-app" })
|
|
7
|
+
*
|
|
8
|
+
* For server admin operations (verifyIdToken, etc):
|
|
9
|
+
* import { SentroyAuthAdmin } from "@sentroy-co/client-sdk/auth/admin"
|
|
10
|
+
*
|
|
11
|
+
* For React integration:
|
|
12
|
+
* import { SentroyAuthProvider, useAuth } from "@sentroy-co/client-sdk/auth/react"
|
|
13
|
+
*/
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.SentroyAuthError = exports.SentroyAuth = void 0;
|
|
16
|
+
var client_1 = require("./client");
|
|
17
|
+
Object.defineProperty(exports, "SentroyAuth", { enumerable: true, get: function () { return client_1.SentroyAuth; } });
|
|
18
|
+
var types_1 = require("./types");
|
|
19
|
+
Object.defineProperty(exports, "SentroyAuthError", { enumerable: true, get: function () { return types_1.SentroyAuthError; } });
|
|
20
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;GAWG;;;AAEH,mCAAsC;AAA7B,qGAAA,WAAW,OAAA;AAMpB,iCAegB;AAdd,yGAAA,gBAAgB,OAAA"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import { SentroyAuth, type SentroyAuthOptions } from "../client";
|
|
3
|
+
import type { SentroyAuthUser, SessionSummary, ActivityEntry, MfaStatus, PasskeySummary } from "../types";
|
|
4
|
+
/**
|
|
5
|
+
* Sentroy Auth React integration.
|
|
6
|
+
*
|
|
7
|
+
* <SentroyAuthProvider projectSlug="my-app">
|
|
8
|
+
* <App />
|
|
9
|
+
* </SentroyAuthProvider>
|
|
10
|
+
*
|
|
11
|
+
* const { user, loading, signIn, signOut } = useAuth()
|
|
12
|
+
*
|
|
13
|
+
* Provider içeride tek bir `SentroyAuth` instance tutar (mount/unmount
|
|
14
|
+
* arasında stable), `onAuthStateChanged` ile React state'i senkron tutar.
|
|
15
|
+
* `loading` ilk render → restore tamam mı henüz değil ayrımı için.
|
|
16
|
+
*
|
|
17
|
+
* Yeni method'lar (MFA, magic link, passkey, social, /me/*) tüm
|
|
18
|
+
* `auth` instance üzerinden erişilebilir — context'te kısayol olarak
|
|
19
|
+
* en sık kullanılanlar mevcut.
|
|
20
|
+
*/
|
|
21
|
+
interface AuthContextValue {
|
|
22
|
+
/** Underlying SDK instance — gelişmiş senaryolarda doğrudan kullan. */
|
|
23
|
+
auth: SentroyAuth;
|
|
24
|
+
user: SentroyAuthUser | null;
|
|
25
|
+
/** True iken provider ilk state'i restore etmiş değil — UI'da
|
|
26
|
+
* "spinner" göster, "redirect to /login" tetikleme. */
|
|
27
|
+
loading: boolean;
|
|
28
|
+
signIn: SentroyAuth["signIn"];
|
|
29
|
+
signUp: SentroyAuth["signUp"];
|
|
30
|
+
signOut: SentroyAuth["signOut"];
|
|
31
|
+
sendPasswordReset: SentroyAuth["sendPasswordReset"];
|
|
32
|
+
verifyEmail: SentroyAuth["verifyEmail"];
|
|
33
|
+
verifyMfa: SentroyAuth["verifyMfa"];
|
|
34
|
+
sendMagicLink: SentroyAuth["sendMagicLink"];
|
|
35
|
+
consumeMagicLink: SentroyAuth["consumeMagicLink"];
|
|
36
|
+
acceptInvitation: SentroyAuth["acceptInvitation"];
|
|
37
|
+
socialAuthorizeUrl: SentroyAuth["socialAuthorizeUrl"];
|
|
38
|
+
consumeRedirectFragment: SentroyAuth["consumeRedirectFragment"];
|
|
39
|
+
}
|
|
40
|
+
export declare function SentroyAuthProvider({ children, autoConsumeFragment, ...opts }: SentroyAuthOptions & {
|
|
41
|
+
children: ReactNode;
|
|
42
|
+
/** Mount'ta `window.location.hash`'ten social-login fragment'ı
|
|
43
|
+
* consume et — default true. RP'nin redirectUri'sinde session
|
|
44
|
+
* otomatik kurulur. */
|
|
45
|
+
autoConsumeFragment?: boolean;
|
|
46
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
47
|
+
export declare function useAuth(): AuthContextValue;
|
|
48
|
+
/**
|
|
49
|
+
* Convenience: yalnızca current user istenirse. `loading` durumunda null
|
|
50
|
+
* dönerken bekleyebilirsin.
|
|
51
|
+
*/
|
|
52
|
+
export declare function useUser(): SentroyAuthUser | null;
|
|
53
|
+
/**
|
|
54
|
+
* Reactive sessions hook — `/me/sessions` çağırır, refresh trigger eden
|
|
55
|
+
* `refresh()` döner. Manual revoke sonrası caller `refresh()` çağırır.
|
|
56
|
+
*/
|
|
57
|
+
export declare function useSessions(): {
|
|
58
|
+
sessions: SessionSummary[] | null;
|
|
59
|
+
loading: boolean;
|
|
60
|
+
error: Error | null;
|
|
61
|
+
refresh: () => Promise<void>;
|
|
62
|
+
revoke: (id: string) => Promise<void>;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Reactive activity log hook — `/me/activity`. RP'nin "recent activity"
|
|
66
|
+
* tab'ı için.
|
|
67
|
+
*/
|
|
68
|
+
export declare function useActivity(): {
|
|
69
|
+
activity: ActivityEntry[] | null;
|
|
70
|
+
loading: boolean;
|
|
71
|
+
error: Error | null;
|
|
72
|
+
refresh: () => Promise<void>;
|
|
73
|
+
};
|
|
74
|
+
/**
|
|
75
|
+
* Reactive MFA status. enroll / verify / disable wrapper'ları, status
|
|
76
|
+
* otomatik yeniden çekilir.
|
|
77
|
+
*/
|
|
78
|
+
export declare function useMfa(): {
|
|
79
|
+
status: MfaStatus | null;
|
|
80
|
+
loading: boolean;
|
|
81
|
+
error: Error | null;
|
|
82
|
+
refresh: () => Promise<void>;
|
|
83
|
+
enrollTotp: SentroyAuth["mfa"]["enrollTotp"];
|
|
84
|
+
verifyTotpEnrollment: (code: string) => Promise<void>;
|
|
85
|
+
disableTotp: (currentPassword: string) => Promise<void>;
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Reactive passkey list — list/delete/register, mutation sonrası
|
|
89
|
+
* otomatik refresh.
|
|
90
|
+
*/
|
|
91
|
+
export declare function usePasskeys(): {
|
|
92
|
+
passkeys: PasskeySummary[] | null;
|
|
93
|
+
loading: boolean;
|
|
94
|
+
error: Error | null;
|
|
95
|
+
refresh: () => Promise<void>;
|
|
96
|
+
register: (deviceName?: string) => Promise<void>;
|
|
97
|
+
remove: (id: string) => Promise<void>;
|
|
98
|
+
};
|
|
99
|
+
export {};
|
|
100
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/react/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
"use client";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.SentroyAuthProvider = SentroyAuthProvider;
|
|
5
|
+
exports.useAuth = useAuth;
|
|
6
|
+
exports.useUser = useUser;
|
|
7
|
+
exports.useSessions = useSessions;
|
|
8
|
+
exports.useActivity = useActivity;
|
|
9
|
+
exports.useMfa = useMfa;
|
|
10
|
+
exports.usePasskeys = usePasskeys;
|
|
11
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
12
|
+
const react_1 = require("react");
|
|
13
|
+
const client_1 = require("../client");
|
|
14
|
+
const AuthContext = (0, react_1.createContext)(null);
|
|
15
|
+
function SentroyAuthProvider({ children, autoConsumeFragment = true, ...opts }) {
|
|
16
|
+
// Single instance — opts deep-compare'a girersek dependency drift'i
|
|
17
|
+
// restart'a yol açar. Caller `projectSlug` değiştirmemeli runtime'da.
|
|
18
|
+
const auth = (0, react_1.useMemo)(() => new client_1.SentroyAuth(opts),
|
|
19
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
20
|
+
[opts.projectSlug, opts.authBaseUrl, opts.apiKey]);
|
|
21
|
+
const [user, setUser] = (0, react_1.useState)(auth.user);
|
|
22
|
+
const [loading, setLoading] = (0, react_1.useState)(true);
|
|
23
|
+
(0, react_1.useEffect)(() => {
|
|
24
|
+
const unsubscribe = auth.onAuthStateChanged((u) => {
|
|
25
|
+
setUser(u);
|
|
26
|
+
setLoading(false);
|
|
27
|
+
});
|
|
28
|
+
return unsubscribe;
|
|
29
|
+
}, [auth]);
|
|
30
|
+
// Social login redirect handler — fragment varsa otomatik consume
|
|
31
|
+
(0, react_1.useEffect)(() => {
|
|
32
|
+
if (!autoConsumeFragment)
|
|
33
|
+
return;
|
|
34
|
+
if (typeof window === "undefined")
|
|
35
|
+
return;
|
|
36
|
+
if (!window.location.hash.includes("access_token="))
|
|
37
|
+
return;
|
|
38
|
+
auth.consumeRedirectFragment().catch(() => {
|
|
39
|
+
// Fragment varsa ama consume fail ise sessizce yut — caller
|
|
40
|
+
// gerekirse manuel tekrar dener.
|
|
41
|
+
});
|
|
42
|
+
}, [auth, autoConsumeFragment]);
|
|
43
|
+
const value = (0, react_1.useMemo)(() => ({
|
|
44
|
+
auth,
|
|
45
|
+
user,
|
|
46
|
+
loading,
|
|
47
|
+
signIn: (i) => auth.signIn(i),
|
|
48
|
+
signUp: (i) => auth.signUp(i),
|
|
49
|
+
signOut: () => auth.signOut(),
|
|
50
|
+
sendPasswordReset: (e) => auth.sendPasswordReset(e),
|
|
51
|
+
verifyEmail: (t) => auth.verifyEmail(t),
|
|
52
|
+
verifyMfa: (i) => auth.verifyMfa(i),
|
|
53
|
+
sendMagicLink: (i) => auth.sendMagicLink(i),
|
|
54
|
+
consumeMagicLink: (t) => auth.consumeMagicLink(t),
|
|
55
|
+
acceptInvitation: (i) => auth.acceptInvitation(i),
|
|
56
|
+
socialAuthorizeUrl: (p, o) => auth.socialAuthorizeUrl(p, o),
|
|
57
|
+
consumeRedirectFragment: () => auth.consumeRedirectFragment(),
|
|
58
|
+
}), [auth, user, loading]);
|
|
59
|
+
return (0, jsx_runtime_1.jsx)(AuthContext.Provider, { value: value, children: children });
|
|
60
|
+
}
|
|
61
|
+
function useAuth() {
|
|
62
|
+
const ctx = (0, react_1.useContext)(AuthContext);
|
|
63
|
+
if (!ctx) {
|
|
64
|
+
throw new Error("useAuth must be used inside <SentroyAuthProvider> — wrap your app root.");
|
|
65
|
+
}
|
|
66
|
+
return ctx;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Convenience: yalnızca current user istenirse. `loading` durumunda null
|
|
70
|
+
* dönerken bekleyebilirsin.
|
|
71
|
+
*/
|
|
72
|
+
function useUser() {
|
|
73
|
+
return useAuth().user;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Reactive sessions hook — `/me/sessions` çağırır, refresh trigger eden
|
|
77
|
+
* `refresh()` döner. Manual revoke sonrası caller `refresh()` çağırır.
|
|
78
|
+
*/
|
|
79
|
+
function useSessions() {
|
|
80
|
+
const { auth, user } = useAuth();
|
|
81
|
+
const [sessions, setSessions] = (0, react_1.useState)(null);
|
|
82
|
+
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
83
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
84
|
+
const refresh = (0, react_1.useCallback)(async () => {
|
|
85
|
+
if (!user) {
|
|
86
|
+
setSessions(null);
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
setLoading(true);
|
|
90
|
+
setError(null);
|
|
91
|
+
try {
|
|
92
|
+
const data = await auth.listSessions();
|
|
93
|
+
setSessions(data);
|
|
94
|
+
}
|
|
95
|
+
catch (e) {
|
|
96
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
97
|
+
}
|
|
98
|
+
finally {
|
|
99
|
+
setLoading(false);
|
|
100
|
+
}
|
|
101
|
+
}, [auth, user]);
|
|
102
|
+
(0, react_1.useEffect)(() => {
|
|
103
|
+
refresh();
|
|
104
|
+
}, [refresh]);
|
|
105
|
+
const revoke = (0, react_1.useCallback)(async (id) => {
|
|
106
|
+
await auth.revokeSession(id);
|
|
107
|
+
await refresh();
|
|
108
|
+
}, [auth, refresh]);
|
|
109
|
+
return { sessions, loading, error, refresh, revoke };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Reactive activity log hook — `/me/activity`. RP'nin "recent activity"
|
|
113
|
+
* tab'ı için.
|
|
114
|
+
*/
|
|
115
|
+
function useActivity() {
|
|
116
|
+
const { auth, user } = useAuth();
|
|
117
|
+
const [activity, setActivity] = (0, react_1.useState)(null);
|
|
118
|
+
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
119
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
120
|
+
const refresh = (0, react_1.useCallback)(async () => {
|
|
121
|
+
if (!user) {
|
|
122
|
+
setActivity(null);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
setLoading(true);
|
|
126
|
+
setError(null);
|
|
127
|
+
try {
|
|
128
|
+
const data = await auth.getActivity();
|
|
129
|
+
setActivity(data);
|
|
130
|
+
}
|
|
131
|
+
catch (e) {
|
|
132
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
133
|
+
}
|
|
134
|
+
finally {
|
|
135
|
+
setLoading(false);
|
|
136
|
+
}
|
|
137
|
+
}, [auth, user]);
|
|
138
|
+
(0, react_1.useEffect)(() => {
|
|
139
|
+
refresh();
|
|
140
|
+
}, [refresh]);
|
|
141
|
+
return { activity, loading, error, refresh };
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Reactive MFA status. enroll / verify / disable wrapper'ları, status
|
|
145
|
+
* otomatik yeniden çekilir.
|
|
146
|
+
*/
|
|
147
|
+
function useMfa() {
|
|
148
|
+
const { auth, user } = useAuth();
|
|
149
|
+
const [status, setStatus] = (0, react_1.useState)(null);
|
|
150
|
+
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
151
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
152
|
+
const refresh = (0, react_1.useCallback)(async () => {
|
|
153
|
+
if (!user) {
|
|
154
|
+
setStatus(null);
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
setLoading(true);
|
|
158
|
+
setError(null);
|
|
159
|
+
try {
|
|
160
|
+
const data = await auth.mfa.getStatus();
|
|
161
|
+
setStatus(data);
|
|
162
|
+
}
|
|
163
|
+
catch (e) {
|
|
164
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
setLoading(false);
|
|
168
|
+
}
|
|
169
|
+
}, [auth, user]);
|
|
170
|
+
(0, react_1.useEffect)(() => {
|
|
171
|
+
refresh();
|
|
172
|
+
}, [refresh]);
|
|
173
|
+
const verifyTotpEnrollment = (0, react_1.useCallback)(async (code) => {
|
|
174
|
+
await auth.mfa.verifyTotpEnrollment(code);
|
|
175
|
+
await refresh();
|
|
176
|
+
}, [auth, refresh]);
|
|
177
|
+
const disableTotp = (0, react_1.useCallback)(async (currentPassword) => {
|
|
178
|
+
await auth.mfa.disableTotp(currentPassword);
|
|
179
|
+
await refresh();
|
|
180
|
+
}, [auth, refresh]);
|
|
181
|
+
return {
|
|
182
|
+
status,
|
|
183
|
+
loading,
|
|
184
|
+
error,
|
|
185
|
+
refresh,
|
|
186
|
+
enrollTotp: () => auth.mfa.enrollTotp(),
|
|
187
|
+
verifyTotpEnrollment,
|
|
188
|
+
disableTotp,
|
|
189
|
+
};
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Reactive passkey list — list/delete/register, mutation sonrası
|
|
193
|
+
* otomatik refresh.
|
|
194
|
+
*/
|
|
195
|
+
function usePasskeys() {
|
|
196
|
+
const { auth, user } = useAuth();
|
|
197
|
+
const [passkeys, setPasskeys] = (0, react_1.useState)(null);
|
|
198
|
+
const [loading, setLoading] = (0, react_1.useState)(false);
|
|
199
|
+
const [error, setError] = (0, react_1.useState)(null);
|
|
200
|
+
const refresh = (0, react_1.useCallback)(async () => {
|
|
201
|
+
if (!user) {
|
|
202
|
+
setPasskeys(null);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
205
|
+
setLoading(true);
|
|
206
|
+
setError(null);
|
|
207
|
+
try {
|
|
208
|
+
const data = await auth.passkey.list();
|
|
209
|
+
setPasskeys(data);
|
|
210
|
+
}
|
|
211
|
+
catch (e) {
|
|
212
|
+
setError(e instanceof Error ? e : new Error(String(e)));
|
|
213
|
+
}
|
|
214
|
+
finally {
|
|
215
|
+
setLoading(false);
|
|
216
|
+
}
|
|
217
|
+
}, [auth, user]);
|
|
218
|
+
(0, react_1.useEffect)(() => {
|
|
219
|
+
refresh();
|
|
220
|
+
}, [refresh]);
|
|
221
|
+
const register = (0, react_1.useCallback)(async (deviceName) => {
|
|
222
|
+
await auth.passkey.register(deviceName);
|
|
223
|
+
await refresh();
|
|
224
|
+
}, [auth, refresh]);
|
|
225
|
+
const remove = (0, react_1.useCallback)(async (id) => {
|
|
226
|
+
await auth.passkey.delete(id);
|
|
227
|
+
await refresh();
|
|
228
|
+
}, [auth, refresh]);
|
|
229
|
+
return { passkeys, loading, error, refresh, register, remove };
|
|
230
|
+
}
|
|
231
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/react/index.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sentroy Auth-as-a-Service — SDK types.
|
|
3
|
+
*
|
|
4
|
+
* Public types are kept narrow on purpose: SDK shapes evolve with backend;
|
|
5
|
+
* caller code should depend on these names, not on hand-coded interfaces.
|
|
6
|
+
*/
|
|
7
|
+
export interface SentroyAuthUser {
|
|
8
|
+
id: string;
|
|
9
|
+
authProjectId: string;
|
|
10
|
+
email: string;
|
|
11
|
+
emailVerified: boolean;
|
|
12
|
+
displayName: string | null;
|
|
13
|
+
image: string | null;
|
|
14
|
+
metadata: Record<string, unknown>;
|
|
15
|
+
lastLoginAt: string | null;
|
|
16
|
+
createdAt: string;
|
|
17
|
+
updatedAt: string;
|
|
18
|
+
}
|
|
19
|
+
export interface AuthTokensResponse {
|
|
20
|
+
accessToken: string;
|
|
21
|
+
refreshToken: string;
|
|
22
|
+
expiresIn: number;
|
|
23
|
+
tokenType: "Bearer";
|
|
24
|
+
}
|
|
25
|
+
export interface SignupResponse {
|
|
26
|
+
user: SentroyAuthUser;
|
|
27
|
+
/** Email verification gerekiyorsa undefined; aksi halde set. */
|
|
28
|
+
accessToken?: string;
|
|
29
|
+
refreshToken?: string;
|
|
30
|
+
expiresIn?: number;
|
|
31
|
+
tokenType?: "Bearer";
|
|
32
|
+
emailVerificationRequired?: boolean;
|
|
33
|
+
}
|
|
34
|
+
export interface LoginResponse {
|
|
35
|
+
user: SentroyAuthUser;
|
|
36
|
+
accessToken: string;
|
|
37
|
+
refreshToken: string;
|
|
38
|
+
expiresIn: number;
|
|
39
|
+
tokenType: "Bearer";
|
|
40
|
+
}
|
|
41
|
+
export interface AuthApiError {
|
|
42
|
+
error: string;
|
|
43
|
+
error_description: string;
|
|
44
|
+
}
|
|
45
|
+
export declare class SentroyAuthError extends Error {
|
|
46
|
+
readonly code: string;
|
|
47
|
+
readonly status: number;
|
|
48
|
+
constructor(code: string, message: string, status: number);
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Login response when MFA is enrolled — first step returns mfaRequired+
|
|
52
|
+
* mfaToken; second step `verifyMfa(mfaToken, code)` issues final tokens.
|
|
53
|
+
*/
|
|
54
|
+
export interface MfaChallengeResponse {
|
|
55
|
+
mfaRequired: true;
|
|
56
|
+
mfaToken: string;
|
|
57
|
+
factorType: "totp";
|
|
58
|
+
}
|
|
59
|
+
/** Discriminated union — Login may resolve to tokens OR MFA challenge. */
|
|
60
|
+
export type LoginOutcome = {
|
|
61
|
+
kind: "tokens";
|
|
62
|
+
data: LoginResponse;
|
|
63
|
+
} | {
|
|
64
|
+
kind: "mfa";
|
|
65
|
+
data: MfaChallengeResponse;
|
|
66
|
+
};
|
|
67
|
+
export interface SessionSummary {
|
|
68
|
+
id: string;
|
|
69
|
+
refreshTokenPrefix: string;
|
|
70
|
+
userAgent: string | null;
|
|
71
|
+
ip: string | null;
|
|
72
|
+
expiresAt: string;
|
|
73
|
+
createdAt: string;
|
|
74
|
+
}
|
|
75
|
+
export interface ActivityEntry {
|
|
76
|
+
id: string;
|
|
77
|
+
action: string;
|
|
78
|
+
ipAddress: string | null;
|
|
79
|
+
createdAt: string;
|
|
80
|
+
details: Record<string, unknown> | null;
|
|
81
|
+
}
|
|
82
|
+
export interface MfaStatus {
|
|
83
|
+
enrolled: boolean;
|
|
84
|
+
factorType?: "totp";
|
|
85
|
+
verifiedAt?: string | null;
|
|
86
|
+
recoveryCodesRemaining?: number;
|
|
87
|
+
}
|
|
88
|
+
export interface MfaEnrollResponse {
|
|
89
|
+
secret: string;
|
|
90
|
+
otpauthUri: string;
|
|
91
|
+
}
|
|
92
|
+
export interface MfaVerifyEnrollmentResponse {
|
|
93
|
+
enrolled: true;
|
|
94
|
+
recoveryCodes: string[];
|
|
95
|
+
}
|
|
96
|
+
export interface PasskeySummary {
|
|
97
|
+
id: string;
|
|
98
|
+
credentialIdPrefix: string;
|
|
99
|
+
deviceName: string | null;
|
|
100
|
+
transports: string[];
|
|
101
|
+
lastUsedAt: string | null;
|
|
102
|
+
createdAt: string;
|
|
103
|
+
}
|
|
104
|
+
export type SocialProvider = "google" | "github" | "facebook" | "microsoft" | "twitter" | "apple";
|
|
105
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Sentroy Auth-as-a-Service — SDK types.
|
|
4
|
+
*
|
|
5
|
+
* Public types are kept narrow on purpose: SDK shapes evolve with backend;
|
|
6
|
+
* caller code should depend on these names, not on hand-coded interfaces.
|
|
7
|
+
*/
|
|
8
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
+
exports.SentroyAuthError = void 0;
|
|
10
|
+
class SentroyAuthError extends Error {
|
|
11
|
+
code;
|
|
12
|
+
status;
|
|
13
|
+
constructor(code, message, status) {
|
|
14
|
+
super(message);
|
|
15
|
+
this.name = "SentroyAuthError";
|
|
16
|
+
this.code = code;
|
|
17
|
+
this.status = status;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.SentroyAuthError = SentroyAuthError;
|
|
21
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AA6CH,MAAa,gBAAiB,SAAQ,KAAK;IAChC,IAAI,CAAQ;IACZ,MAAM,CAAQ;IACvB,YAAY,IAAY,EAAE,OAAe,EAAE,MAAc;QACvD,KAAK,CAAC,OAAO,CAAC,CAAA;QACd,IAAI,CAAC,IAAI,GAAG,kBAAkB,CAAA;QAC9B,IAAI,CAAC,IAAI,GAAG,IAAI,CAAA;QAChB,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;IACtB,CAAC;CACF;AATD,4CASC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sentroy-co/client-sdk",
|
|
3
|
-
"version": "2.13.
|
|
3
|
+
"version": "2.13.9",
|
|
4
4
|
"description": "TypeScript SDK + CLI for the Sentroy platform — mail, storage, env vault + React components.",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -38,6 +38,21 @@
|
|
|
38
38
|
"types": "./dist/vault/react.d.ts",
|
|
39
39
|
"import": "./dist/vault/react.js",
|
|
40
40
|
"require": "./dist/vault/react.js"
|
|
41
|
+
},
|
|
42
|
+
"./auth": {
|
|
43
|
+
"types": "./dist/auth/index.d.ts",
|
|
44
|
+
"import": "./dist/auth/index.js",
|
|
45
|
+
"require": "./dist/auth/index.js"
|
|
46
|
+
},
|
|
47
|
+
"./auth/admin": {
|
|
48
|
+
"types": "./dist/auth/admin/index.d.ts",
|
|
49
|
+
"import": "./dist/auth/admin/index.js",
|
|
50
|
+
"require": "./dist/auth/admin/index.js"
|
|
51
|
+
},
|
|
52
|
+
"./auth/react": {
|
|
53
|
+
"types": "./dist/auth/react/index.d.ts",
|
|
54
|
+
"import": "./dist/auth/react/index.js",
|
|
55
|
+
"require": "./dist/auth/react/index.js"
|
|
41
56
|
}
|
|
42
57
|
},
|
|
43
58
|
"files": [
|
|
@@ -80,10 +95,14 @@
|
|
|
80
95
|
"node": ">=18.0.0"
|
|
81
96
|
},
|
|
82
97
|
"peerDependencies": {
|
|
98
|
+
"@simplewebauthn/browser": "^13.0.0",
|
|
83
99
|
"react": ">=18.0.0",
|
|
84
100
|
"react-dom": ">=18.0.0"
|
|
85
101
|
},
|
|
86
102
|
"peerDependenciesMeta": {
|
|
103
|
+
"@simplewebauthn/browser": {
|
|
104
|
+
"optional": true
|
|
105
|
+
},
|
|
87
106
|
"react": {
|
|
88
107
|
"optional": true
|
|
89
108
|
},
|