nocal-auth-sdk 0.1.8 → 0.1.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.
@@ -1,10 +1,30 @@
1
1
  export interface NocalAuthOptions {
2
2
  authorizeUrl?: string;
3
+ clientId?: string;
4
+ redirectUri?: string;
5
+ scope?: string;
6
+ state?: string;
3
7
  [key: string]: any;
4
8
  }
9
+ export interface NocalPopupResult {
10
+ success: boolean;
11
+ data?: Record<string, any>;
12
+ error?: string;
13
+ message?: string;
14
+ }
15
+ export interface LoginWithPopupOptions {
16
+ url?: string;
17
+ popupName?: string;
18
+ width?: number;
19
+ height?: number;
20
+ features?: string;
21
+ }
5
22
  export declare class NocalAuth {
6
23
  private authorizeUrl;
7
- [key: string]: any;
24
+ private options;
8
25
  constructor(options?: NocalAuthOptions);
9
- loginWithPopup(): Promise<unknown>;
26
+ static notifyPopupResult(result: NocalPopupResult, targetWindow?: Window | null): boolean;
27
+ getAuthorizeUrl(): string;
28
+ static loginWithPopup(options?: LoginWithPopupOptions): Promise<unknown>;
29
+ loginWithPopup(options?: LoginWithPopupOptions): Promise<unknown>;
10
30
  }
package/dist/NocalAuth.js CHANGED
@@ -1,19 +1,61 @@
1
1
  export class NocalAuth {
2
2
  constructor(options = {}) {
3
- this.authorizeUrl = options.authorizeUrl || "";
3
+ this.options = options;
4
+ this.authorizeUrl =
5
+ options.authorizeUrl || "https://auth.nocal.vn/oauth/authorize";
4
6
  }
5
- loginWithPopup() {
6
- // Thêm check an toàn nếu chạy ở môi trường SSR (Next.js/Nuxt) không có window
7
+ static notifyPopupResult(result, targetWindow = typeof window !== "undefined"
8
+ ? window.opener
9
+ : null) {
10
+ if (typeof window === "undefined")
11
+ return false;
12
+ const opener = targetWindow ?? window.opener;
13
+ if (!opener)
14
+ return false;
15
+ const payload = {
16
+ type: "nocal_auth_result",
17
+ success: result.success,
18
+ ...(result.success
19
+ ? { data: result.data ?? {} }
20
+ : {
21
+ error: result.error || "AUTH_FAILED",
22
+ message: result.message || result.error || "AUTH_FAILED",
23
+ }),
24
+ };
25
+ opener.postMessage(payload, "*");
26
+ return true;
27
+ }
28
+ getAuthorizeUrl() {
29
+ const url = new URL(this.authorizeUrl || "https://auth.nocal.vn/oauth/authorize");
30
+ const params = {
31
+ client_id: this.options.clientId,
32
+ redirect_uri: this.options.redirectUri,
33
+ scope: this.options.scope,
34
+ state: this.options.state,
35
+ ...this.options,
36
+ };
37
+ Object.entries(params).forEach(([key, value]) => {
38
+ if (value === undefined || value === null || value === "")
39
+ return;
40
+ if (key === "authorizeUrl")
41
+ return;
42
+ url.searchParams.set(key, String(value));
43
+ });
44
+ return url.toString();
45
+ }
46
+ static loginWithPopup(options = {}) {
7
47
  if (typeof window === "undefined") {
8
48
  return Promise.reject(new Error("loginWithPopup() can only be used in a browser environment"));
9
49
  }
50
+ const url = options.url || "https://auth.nocal.vn/oauth/authorize";
51
+ const width = options.width ?? 500;
52
+ const height = options.height ?? 700;
53
+ const left = window.screenX + (window.innerWidth - width) / 2;
54
+ const top = window.screenY + (window.innerHeight - height) / 2;
55
+ const features = options.features ??
56
+ `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`;
10
57
  return new Promise((resolve, reject) => {
11
- const width = 500;
12
- const height = 700;
13
- const left = window.screenX + (window.innerWidth - width) / 2;
14
- const top = window.screenY + (window.innerHeight - height) / 2;
15
- const features = `width=${width},height=${height},left=${left},top=${top},resizable=yes,scrollbars=yes`;
16
- const popup = window.open(this.authorizeUrl, "nocal_auth_popup", features);
58
+ const popup = window.open(url, options.popupName ?? "nocal_auth_popup", features);
17
59
  if (!popup)
18
60
  return reject(new Error("POPUP_BLOCKED"));
19
61
  popup.focus();
@@ -33,10 +75,10 @@ export class NocalAuth {
33
75
  return;
34
76
  cleanup();
35
77
  if (payload.success) {
36
- resolve(payload.data);
78
+ resolve(payload.data ?? {});
37
79
  }
38
80
  else {
39
- reject(new Error(payload.error || "AUTH_FAILED"));
81
+ reject(new Error(payload.error || payload.message || "AUTH_FAILED"));
40
82
  }
41
83
  };
42
84
  window.addEventListener("message", handleMessage);
@@ -47,10 +89,16 @@ export class NocalAuth {
47
89
  reject(new Error("POPUP_CLOSED"));
48
90
  }
49
91
  }
50
- catch (e) {
51
- // Bỏ qua lỗi Cross-Origin khi popup chuyển hướng
92
+ catch {
93
+ // Ignore cross-origin checks while popup is redirecting.
52
94
  }
53
95
  }, 500);
54
96
  });
55
97
  }
98
+ loginWithPopup(options = {}) {
99
+ return NocalAuth.loginWithPopup({
100
+ ...options,
101
+ url: options.url || this.getAuthorizeUrl(),
102
+ });
103
+ }
56
104
  }
@@ -0,0 +1,46 @@
1
+ import * as _supabase_auth_js from '@supabase/auth-js';
2
+ import { User, Session } from '@supabase/supabase-js';
3
+ export { Session, User } from '@supabase/supabase-js';
4
+
5
+ interface NocalClientConfig {
6
+ clientId: string;
7
+ redirectUri: string;
8
+ }
9
+ type NocalOAuthProvider = "google" | "facebook" | "github" | "apple";
10
+ interface OAuthLoginReq {
11
+ provider?: NocalOAuthProvider;
12
+ redirectTo?: string;
13
+ }
14
+
15
+ declare class NocalAuthSDK {
16
+ private supabase;
17
+ private clientId;
18
+ private redirectUri;
19
+ constructor(config: NocalClientConfig);
20
+ /**
21
+ * Mở Popup UI Đăng nhập/Đăng ký tập trung của Nocal
22
+ */
23
+ signInWithNocal(req?: OAuthLoginReq): Promise<User>;
24
+ /**
25
+ * Lấy thông tin User hiện tại
26
+ */
27
+ getUser(): Promise<User | null>;
28
+ /**
29
+ * Lấy Session / Access Token hiện tại
30
+ */
31
+ getSession(): Promise<Session | null>;
32
+ /**
33
+ * Đăng xuất khỏi hệ thống
34
+ */
35
+ signOut(): Promise<void>;
36
+ /**
37
+ * Lắng nghe sự kiện đăng nhập / đăng xuất
38
+ */
39
+ onAuthStateChange(callback: (event: string, session: Session | null) => void): {
40
+ data: {
41
+ subscription: _supabase_auth_js.Subscription;
42
+ };
43
+ };
44
+ }
45
+
46
+ export { NocalAuthSDK, type NocalClientConfig, type NocalOAuthProvider, type OAuthLoginReq };
package/dist/index.d.ts CHANGED
@@ -1,2 +1,32 @@
1
- export { NocalAuth } from "./NocalAuth";
2
- export type { NocalAuthOptions } from "./NocalAuth";
1
+ import { NocalClientConfig, OAuthLoginReq, User as NocalUser, Session as NocalSession } from "./types";
2
+ export declare class NocalAuthSDK {
3
+ private supabase;
4
+ private clientId;
5
+ private redirectUri;
6
+ constructor(config: NocalClientConfig);
7
+ /**
8
+ * Mở Popup UI Đăng nhập/Đăng ký tập trung của Nocal
9
+ */
10
+ signInWithNocal(req?: OAuthLoginReq): Promise<NocalUser>;
11
+ /**
12
+ * Lấy thông tin User hiện tại
13
+ */
14
+ getUser(): Promise<NocalUser | null>;
15
+ /**
16
+ * Lấy Session / Access Token hiện tại
17
+ */
18
+ getSession(): Promise<NocalSession | null>;
19
+ /**
20
+ * Đăng xuất khỏi hệ thống
21
+ */
22
+ signOut(): Promise<void>;
23
+ /**
24
+ * Lắng nghe sự kiện đăng nhập / đăng xuất
25
+ */
26
+ onAuthStateChange(callback: (event: string, session: NocalSession | null) => void): {
27
+ data: {
28
+ subscription: import("@supabase/auth-js").Subscription;
29
+ };
30
+ };
31
+ }
32
+ export * from "./types";
package/dist/index.js CHANGED
@@ -1 +1,109 @@
1
- export { NocalAuth } from "./NocalAuth";
1
+ import { createClient, } from "@supabase/supabase-js";
2
+ const NOCAL_AUTH_SERVER_URL = "https://hldymiruucsqqzicnwdv.supabase.co";
3
+ const NOCAL_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhsZHltaXJ1dWNzcXF6aWNud2R2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODk2MTQ2NzAsImV4cCI6MjEwNTE5MDY3MH0.dLaPWdgTV8mRVToNT1XLg1EUjHvyvRRK2qc0DQAu8YI";
4
+ export class NocalAuthSDK {
5
+ constructor(config) {
6
+ this.clientId = config.clientId;
7
+ this.redirectUri = config.redirectUri;
8
+ this.supabase = createClient(NOCAL_AUTH_SERVER_URL, NOCAL_ANON_KEY, {
9
+ auth: {
10
+ autoRefreshToken: true,
11
+ persistSession: true,
12
+ detectSessionInUrl: true,
13
+ },
14
+ });
15
+ }
16
+ /**
17
+ * Mở Popup UI Đăng nhập/Đăng ký tập trung của Nocal
18
+ */
19
+ async signInWithNocal(req) {
20
+ const targetRedirect = req?.redirectTo || this.redirectUri;
21
+ const provider = (req?.provider || "google");
22
+ // 1. Gọi Supabase SDK để sinh URL ủy quyền chuẩn OAuth 2.0 / PKCE
23
+ const { data, error } = await this.supabase.auth.signInWithOAuth({
24
+ provider,
25
+ options: {
26
+ redirectTo: targetRedirect,
27
+ skipBrowserRedirect: true, // Lấy URL trả về, không nhảy trang tab chính
28
+ queryParams: {
29
+ client_id: this.clientId, // Gắn Client ID để Auth Server nhận diện App
30
+ },
31
+ },
32
+ });
33
+ if (error)
34
+ throw error;
35
+ if (!data?.url)
36
+ throw new Error("CANNOT_GENERATE_AUTH_URL");
37
+ // 2. Tính toán kích thước và căn giữa màn hình Popup
38
+ const width = 480;
39
+ const height = 680;
40
+ const left = typeof window !== "undefined"
41
+ ? window.screenX + (window.outerWidth - width) / 2
42
+ : 0;
43
+ const top = typeof window !== "undefined"
44
+ ? window.screenY + (window.outerHeight - height) / 2
45
+ : 0;
46
+ // 3. Mở Cửa sổ Popup chứa UI đăng nhập Nocal
47
+ const popup = window.open(data.url, "NocalAuthPopup", `width=${width},height=${height},left=${left},top=${top},status=yes,scrollbars=yes`);
48
+ if (!popup) {
49
+ throw new Error("POPUP_BLOCKED");
50
+ }
51
+ // 4. Lắng nghe và kiểm tra khi Popup đóng
52
+ return new Promise((resolve, reject) => {
53
+ const isPopupClosed = () => {
54
+ try {
55
+ return popup.closed;
56
+ }
57
+ catch (e) {
58
+ return false;
59
+ }
60
+ };
61
+ const timer = setInterval(async () => {
62
+ if (isPopupClosed()) {
63
+ clearInterval(timer);
64
+ // Sau khi popup đóng, lấy session đã đăng nhập
65
+ const { data: sessionData } = await this.supabase.auth.getSession();
66
+ if (sessionData?.session?.user) {
67
+ resolve(sessionData.session.user);
68
+ }
69
+ else {
70
+ reject(new Error("LOGIN_CANCELLED_OR_FAILED"));
71
+ }
72
+ }
73
+ }, 500);
74
+ });
75
+ }
76
+ /**
77
+ * Lấy thông tin User hiện tại
78
+ */
79
+ async getUser() {
80
+ const { data: { user }, error, } = await this.supabase.auth.getUser();
81
+ if (error)
82
+ throw error;
83
+ return user;
84
+ }
85
+ /**
86
+ * Lấy Session / Access Token hiện tại
87
+ */
88
+ async getSession() {
89
+ const { data: { session }, error, } = await this.supabase.auth.getSession();
90
+ if (error)
91
+ throw error;
92
+ return session;
93
+ }
94
+ /**
95
+ * Đăng xuất khỏi hệ thống
96
+ */
97
+ async signOut() {
98
+ const { error } = await this.supabase.auth.signOut();
99
+ if (error)
100
+ throw error;
101
+ }
102
+ /**
103
+ * Lắng nghe sự kiện đăng nhập / đăng xuất
104
+ */
105
+ onAuthStateChange(callback) {
106
+ return this.supabase.auth.onAuthStateChange(callback);
107
+ }
108
+ }
109
+ export * from "./types";
package/dist/index.mjs ADDED
@@ -0,0 +1,110 @@
1
+ // src/index.ts
2
+ import {
3
+ createClient
4
+ } from "@supabase/supabase-js";
5
+ var NOCAL_AUTH_SERVER_URL = "https://hldymiruucsqqzicnwdv.supabase.co";
6
+ var NOCAL_ANON_KEY = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiJzdXBhYmFzZSIsInJlZiI6ImhsZHltaXJ1dWNzcXF6aWNud2R2Iiwicm9sZSI6ImFub24iLCJpYXQiOjE3ODk2MTQ2NzAsImV4cCI6MjEwNTE5MDY3MH0.dLaPWdgTV8mRVToNT1XLg1EUjHvyvRRK2qc0DQAu8YI";
7
+ var NocalAuthSDK = class {
8
+ constructor(config) {
9
+ this.clientId = config.clientId;
10
+ this.redirectUri = config.redirectUri;
11
+ this.supabase = createClient(NOCAL_AUTH_SERVER_URL, NOCAL_ANON_KEY, {
12
+ auth: {
13
+ autoRefreshToken: true,
14
+ persistSession: true,
15
+ detectSessionInUrl: true
16
+ }
17
+ });
18
+ }
19
+ /**
20
+ * Mở Popup UI Đăng nhập/Đăng ký tập trung của Nocal
21
+ */
22
+ async signInWithNocal(req) {
23
+ const targetRedirect = req?.redirectTo || this.redirectUri;
24
+ const provider = req?.provider || "google";
25
+ const { data, error } = await this.supabase.auth.signInWithOAuth({
26
+ provider,
27
+ options: {
28
+ redirectTo: targetRedirect,
29
+ skipBrowserRedirect: true,
30
+ // Lấy URL trả về, không nhảy trang tab chính
31
+ queryParams: {
32
+ client_id: this.clientId
33
+ // Gắn Client ID để Auth Server nhận diện App
34
+ }
35
+ }
36
+ });
37
+ if (error) throw error;
38
+ if (!data?.url) throw new Error("CANNOT_GENERATE_AUTH_URL");
39
+ const width = 480;
40
+ const height = 680;
41
+ const left = typeof window !== "undefined" ? window.screenX + (window.outerWidth - width) / 2 : 0;
42
+ const top = typeof window !== "undefined" ? window.screenY + (window.outerHeight - height) / 2 : 0;
43
+ const popup = window.open(
44
+ data.url,
45
+ "NocalAuthPopup",
46
+ `width=${width},height=${height},left=${left},top=${top},status=yes,scrollbars=yes`
47
+ );
48
+ if (!popup) {
49
+ throw new Error("POPUP_BLOCKED");
50
+ }
51
+ return new Promise((resolve, reject) => {
52
+ const isPopupClosed = () => {
53
+ try {
54
+ return popup.closed;
55
+ } catch (e) {
56
+ return false;
57
+ }
58
+ };
59
+ const timer = setInterval(async () => {
60
+ if (isPopupClosed()) {
61
+ clearInterval(timer);
62
+ const { data: sessionData } = await this.supabase.auth.getSession();
63
+ if (sessionData?.session?.user) {
64
+ resolve(sessionData.session.user);
65
+ } else {
66
+ reject(new Error("LOGIN_CANCELLED_OR_FAILED"));
67
+ }
68
+ }
69
+ }, 500);
70
+ });
71
+ }
72
+ /**
73
+ * Lấy thông tin User hiện tại
74
+ */
75
+ async getUser() {
76
+ const {
77
+ data: { user },
78
+ error
79
+ } = await this.supabase.auth.getUser();
80
+ if (error) throw error;
81
+ return user;
82
+ }
83
+ /**
84
+ * Lấy Session / Access Token hiện tại
85
+ */
86
+ async getSession() {
87
+ const {
88
+ data: { session },
89
+ error
90
+ } = await this.supabase.auth.getSession();
91
+ if (error) throw error;
92
+ return session;
93
+ }
94
+ /**
95
+ * Đăng xuất khỏi hệ thống
96
+ */
97
+ async signOut() {
98
+ const { error } = await this.supabase.auth.signOut();
99
+ if (error) throw error;
100
+ }
101
+ /**
102
+ * Lắng nghe sự kiện đăng nhập / đăng xuất
103
+ */
104
+ onAuthStateChange(callback) {
105
+ return this.supabase.auth.onAuthStateChange(callback);
106
+ }
107
+ };
108
+ export {
109
+ NocalAuthSDK
110
+ };
@@ -0,0 +1,11 @@
1
+ import { User, Session } from "@supabase/supabase-js";
2
+ export interface NocalClientConfig {
3
+ clientId: string;
4
+ redirectUri: string;
5
+ }
6
+ export type NocalOAuthProvider = "google" | "facebook" | "github" | "apple";
7
+ export interface OAuthLoginReq {
8
+ provider?: NocalOAuthProvider;
9
+ redirectTo?: string;
10
+ }
11
+ export type { User, Session };
package/dist/types.js ADDED
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "nocal-auth-sdk",
3
- "version": "0.1.8",
3
+ "version": "0.1.9",
4
4
  "description": "Nocal Auth - client-side SDK for Login with Nocal (popup flow)",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",