@jay-framework/wix-members 0.19.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/dist/contracts/auth-callback.jay-contract +21 -0
- package/dist/contracts/auth-callback.jay-contract.d.ts +20 -0
- package/dist/contracts/login-indicator.jay-contract +37 -0
- package/dist/contracts/login-indicator.jay-contract.d.ts +29 -0
- package/dist/contracts/protected-page.jay-contract +15 -0
- package/dist/contracts/protected-page.jay-contract.d.ts +22 -0
- package/dist/index.client-lddj65uZ.d.ts +108 -0
- package/dist/index.client.d.ts +5 -0
- package/dist/index.client.js +164 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.js +177 -0
- package/package.json +69 -0
- package/plugin.yaml +25 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
name: auth-callback
|
|
2
|
+
description: Handles OAuth callback after Wix-hosted login/register. Place as keyed component on the callback page.
|
|
3
|
+
|
|
4
|
+
tags:
|
|
5
|
+
- tag: isProcessing
|
|
6
|
+
type: variant
|
|
7
|
+
dataType: boolean
|
|
8
|
+
phase: fast+interactive
|
|
9
|
+
description: Whether the auth callback is being processed
|
|
10
|
+
|
|
11
|
+
- tag: hasError
|
|
12
|
+
type: variant
|
|
13
|
+
dataType: boolean
|
|
14
|
+
phase: fast+interactive
|
|
15
|
+
description: Whether the callback processing failed
|
|
16
|
+
|
|
17
|
+
- tag: errorMessage
|
|
18
|
+
type: data
|
|
19
|
+
dataType: string
|
|
20
|
+
phase: fast+interactive
|
|
21
|
+
description: Error message if callback processing failed
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {JayContract} from "@jay-framework/runtime";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export interface AuthCallbackViewState {
|
|
5
|
+
isProcessing: boolean,
|
|
6
|
+
hasError: boolean,
|
|
7
|
+
errorMessage: string
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type AuthCallbackSlowViewState = {};
|
|
11
|
+
|
|
12
|
+
export type AuthCallbackFastViewState = Pick<AuthCallbackViewState, 'isProcessing' | 'hasError' | 'errorMessage'>;
|
|
13
|
+
|
|
14
|
+
export type AuthCallbackInteractiveViewState = Pick<AuthCallbackViewState, 'isProcessing' | 'hasError' | 'errorMessage'>;
|
|
15
|
+
|
|
16
|
+
export interface AuthCallbackRefs {}
|
|
17
|
+
|
|
18
|
+
export interface AuthCallbackRepeatedRefs {}
|
|
19
|
+
|
|
20
|
+
export type AuthCallbackContract = JayContract<AuthCallbackViewState, AuthCallbackRefs, AuthCallbackSlowViewState, AuthCallbackFastViewState, AuthCallbackInteractiveViewState>
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: login-indicator
|
|
2
|
+
description: Shows member login state in site header/navigation. Provides login/register/logout buttons that redirect to Wix-hosted auth pages.
|
|
3
|
+
|
|
4
|
+
tags:
|
|
5
|
+
- tag: isLoggedIn
|
|
6
|
+
type: variant
|
|
7
|
+
dataType: boolean
|
|
8
|
+
phase: fast+interactive
|
|
9
|
+
description: Whether a member is currently logged in
|
|
10
|
+
|
|
11
|
+
- tag: memberName
|
|
12
|
+
type: data
|
|
13
|
+
dataType: string
|
|
14
|
+
phase: fast+interactive
|
|
15
|
+
description: Logged-in member's display name
|
|
16
|
+
|
|
17
|
+
- tag: memberAvatar
|
|
18
|
+
type: data
|
|
19
|
+
dataType: string
|
|
20
|
+
phase: fast+interactive
|
|
21
|
+
description: URL of member's profile image
|
|
22
|
+
|
|
23
|
+
- tag: isLoading
|
|
24
|
+
type: variant
|
|
25
|
+
dataType: boolean
|
|
26
|
+
phase: fast+interactive
|
|
27
|
+
description: Whether auth state is being resolved
|
|
28
|
+
|
|
29
|
+
- tag: loginButton
|
|
30
|
+
type: interactive
|
|
31
|
+
elementType: HTMLButtonElement
|
|
32
|
+
description: Redirects to Wix-hosted login/register page
|
|
33
|
+
|
|
34
|
+
- tag: logoutButton
|
|
35
|
+
type: interactive
|
|
36
|
+
elementType: HTMLButtonElement
|
|
37
|
+
description: Triggers logout
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {HTMLElementCollectionProxy, HTMLElementProxy, JayContract} from "@jay-framework/runtime";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export interface LoginIndicatorViewState {
|
|
5
|
+
isLoggedIn: boolean,
|
|
6
|
+
memberName: string,
|
|
7
|
+
memberAvatar: string,
|
|
8
|
+
isLoading: boolean
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export type LoginIndicatorSlowViewState = {};
|
|
12
|
+
|
|
13
|
+
export type LoginIndicatorFastViewState = Pick<LoginIndicatorViewState, 'isLoggedIn' | 'memberName' | 'memberAvatar' | 'isLoading'>;
|
|
14
|
+
|
|
15
|
+
export type LoginIndicatorInteractiveViewState = Pick<LoginIndicatorViewState, 'isLoggedIn' | 'memberName' | 'memberAvatar' | 'isLoading'>;
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
export interface LoginIndicatorRefs {
|
|
19
|
+
loginButton: HTMLElementProxy<LoginIndicatorViewState, HTMLButtonElement>,
|
|
20
|
+
logoutButton: HTMLElementProxy<LoginIndicatorViewState, HTMLButtonElement>
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
export interface LoginIndicatorRepeatedRefs {
|
|
25
|
+
loginButton: HTMLElementCollectionProxy<LoginIndicatorViewState, HTMLButtonElement>,
|
|
26
|
+
logoutButton: HTMLElementCollectionProxy<LoginIndicatorViewState, HTMLButtonElement>
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type LoginIndicatorContract = JayContract<LoginIndicatorViewState, LoginIndicatorRefs, LoginIndicatorSlowViewState, LoginIndicatorFastViewState, LoginIndicatorInteractiveViewState>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
name: protected-page
|
|
2
|
+
description: Page-level login guard. Redirects visitors to login page if not authenticated. Use as a keyed component in the page head.
|
|
3
|
+
|
|
4
|
+
props:
|
|
5
|
+
- name: loginUrl
|
|
6
|
+
type: string
|
|
7
|
+
default: '/login'
|
|
8
|
+
description: URL to redirect to when visitor is not logged in
|
|
9
|
+
|
|
10
|
+
tags:
|
|
11
|
+
- tag: isLoggedIn
|
|
12
|
+
type: variant
|
|
13
|
+
dataType: boolean
|
|
14
|
+
phase: fast+interactive
|
|
15
|
+
description: Whether the current visitor is a logged-in member (always true when page renders)
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {JayContract} from "@jay-framework/runtime";
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
export interface ProtectedPageViewState {
|
|
5
|
+
isLoggedIn: boolean
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export type ProtectedPageSlowViewState = {};
|
|
9
|
+
|
|
10
|
+
export type ProtectedPageFastViewState = Pick<ProtectedPageViewState, 'isLoggedIn'>;
|
|
11
|
+
|
|
12
|
+
export type ProtectedPageInteractiveViewState = Pick<ProtectedPageViewState, 'isLoggedIn'>;
|
|
13
|
+
|
|
14
|
+
export interface ProtectedPageRefs {}
|
|
15
|
+
|
|
16
|
+
export interface ProtectedPageRepeatedRefs {}
|
|
17
|
+
|
|
18
|
+
export interface ProtectedPageProps {
|
|
19
|
+
loginUrl?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export type ProtectedPageContract = JayContract<ProtectedPageViewState, ProtectedPageRefs, ProtectedPageSlowViewState, ProtectedPageFastViewState, ProtectedPageInteractiveViewState, ProtectedPageProps>
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import * as _jay_framework_runtime from '@jay-framework/runtime';
|
|
2
|
+
import { EventEmitter, HTMLElementProxy } from '@jay-framework/runtime';
|
|
3
|
+
import { Getter } from '@jay-framework/reactive';
|
|
4
|
+
import * as _jay_framework_fullstack_component from '@jay-framework/fullstack-component';
|
|
5
|
+
import { Signals, PageProps, RequestCookies } from '@jay-framework/fullstack-component';
|
|
6
|
+
import * as _jay_framework_component from '@jay-framework/component';
|
|
7
|
+
|
|
8
|
+
interface WixMembersInitData {
|
|
9
|
+
authCallbackUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
interface ReactiveMemberIndicator {
|
|
12
|
+
isLoggedIn: Getter<boolean>;
|
|
13
|
+
isLoading: Getter<boolean>;
|
|
14
|
+
memberName: Getter<string>;
|
|
15
|
+
memberAvatar: Getter<string>;
|
|
16
|
+
}
|
|
17
|
+
interface AuthCallbackResult {
|
|
18
|
+
success: boolean;
|
|
19
|
+
redirectTo: string;
|
|
20
|
+
error?: string;
|
|
21
|
+
}
|
|
22
|
+
interface WixMembersContext {
|
|
23
|
+
memberIndicator: ReactiveMemberIndicator;
|
|
24
|
+
redirectToLogin(callbackUrl?: string): Promise<string>;
|
|
25
|
+
handleAuthCallback(url?: string): Promise<AuthCallbackResult>;
|
|
26
|
+
logout(): Promise<void>;
|
|
27
|
+
refreshMemberState(): void;
|
|
28
|
+
onLogin: EventEmitter<void, any>;
|
|
29
|
+
onLogout: EventEmitter<void, any>;
|
|
30
|
+
}
|
|
31
|
+
declare const WIX_MEMBERS_CONTEXT: _jay_framework_runtime.ContextMarker<WixMembersContext>;
|
|
32
|
+
declare function provideWixMembersContext(initData: WixMembersInitData): WixMembersContext;
|
|
33
|
+
|
|
34
|
+
interface LoginIndicatorViewState {
|
|
35
|
+
isLoggedIn: boolean,
|
|
36
|
+
memberName: string,
|
|
37
|
+
memberAvatar: string,
|
|
38
|
+
isLoading: boolean
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
type LoginIndicatorSlowViewState = {};
|
|
42
|
+
|
|
43
|
+
type LoginIndicatorFastViewState = Pick<LoginIndicatorViewState, 'isLoggedIn' | 'memberName' | 'memberAvatar' | 'isLoading'>;
|
|
44
|
+
|
|
45
|
+
type LoginIndicatorInteractiveViewState = Pick<LoginIndicatorViewState, 'isLoggedIn' | 'memberName' | 'memberAvatar' | 'isLoading'>;
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
interface LoginIndicatorRefs {
|
|
49
|
+
loginButton: HTMLElementProxy<LoginIndicatorViewState, HTMLButtonElement>,
|
|
50
|
+
logoutButton: HTMLElementProxy<LoginIndicatorViewState, HTMLButtonElement>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
interface WixMembersService {
|
|
54
|
+
}
|
|
55
|
+
declare const WIX_MEMBERS_SERVICE: _jay_framework_fullstack_component.ServiceMarker<WixMembersService>;
|
|
56
|
+
|
|
57
|
+
interface LoginIndicatorFastCarryForward {
|
|
58
|
+
}
|
|
59
|
+
declare const loginIndicator: _jay_framework_fullstack_component.JayStackComponentDefinition<LoginIndicatorRefs, LoginIndicatorSlowViewState, LoginIndicatorFastViewState, LoginIndicatorInteractiveViewState, [WixMembersService], [Signals<LoginIndicatorFastViewState>, LoginIndicatorFastCarryForward, WixMembersContext], PageProps, {}, _jay_framework_component.JayComponentCore<PageProps, LoginIndicatorInteractiveViewState>>;
|
|
60
|
+
|
|
61
|
+
interface AuthCallbackViewState {
|
|
62
|
+
isProcessing: boolean,
|
|
63
|
+
hasError: boolean,
|
|
64
|
+
errorMessage: string
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
type AuthCallbackSlowViewState = {};
|
|
68
|
+
|
|
69
|
+
type AuthCallbackFastViewState = Pick<AuthCallbackViewState, 'isProcessing' | 'hasError' | 'errorMessage'>;
|
|
70
|
+
|
|
71
|
+
type AuthCallbackInteractiveViewState = Pick<AuthCallbackViewState, 'isProcessing' | 'hasError' | 'errorMessage'>;
|
|
72
|
+
|
|
73
|
+
interface AuthCallbackRefs {}
|
|
74
|
+
|
|
75
|
+
interface AuthCallbackFastCarryForward {
|
|
76
|
+
}
|
|
77
|
+
declare const authCallback: _jay_framework_fullstack_component.JayStackComponentDefinition<AuthCallbackRefs, AuthCallbackSlowViewState, AuthCallbackFastViewState, AuthCallbackInteractiveViewState, [WixMembersService], [Signals<AuthCallbackFastViewState>, AuthCallbackFastCarryForward, WixMembersContext], PageProps, {}, _jay_framework_component.JayComponentCore<PageProps, AuthCallbackInteractiveViewState>>;
|
|
78
|
+
|
|
79
|
+
interface ProtectedPageViewState {
|
|
80
|
+
isLoggedIn: boolean
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
type ProtectedPageSlowViewState = {};
|
|
84
|
+
|
|
85
|
+
type ProtectedPageFastViewState = Pick<ProtectedPageViewState, 'isLoggedIn'>;
|
|
86
|
+
|
|
87
|
+
type ProtectedPageInteractiveViewState = Pick<ProtectedPageViewState, 'isLoggedIn'>;
|
|
88
|
+
|
|
89
|
+
interface ProtectedPageRefs {}
|
|
90
|
+
|
|
91
|
+
interface ProtectedPageProps {
|
|
92
|
+
loginUrl?: string;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
interface ProtectedPageFastCarryForward {
|
|
96
|
+
}
|
|
97
|
+
type FastProps = PageProps & ProtectedPageProps & RequestCookies;
|
|
98
|
+
declare const protectedPage: _jay_framework_fullstack_component.JayStackComponentDefinition<ProtectedPageRefs, ProtectedPageSlowViewState, ProtectedPageFastViewState, ProtectedPageInteractiveViewState, [WixMembersService], [_jay_framework_fullstack_component.Signals<ProtectedPageFastViewState>, ProtectedPageFastCarryForward], FastProps, {}, _jay_framework_component.JayComponentCore<FastProps, ProtectedPageInteractiveViewState>> & {
|
|
99
|
+
withClientDefaults(fn: (props: FastProps) => {
|
|
100
|
+
viewState: ProtectedPageFastViewState;
|
|
101
|
+
carryForward?: any;
|
|
102
|
+
}): _jay_framework_fullstack_component.JayStackComponentDefinition<ProtectedPageRefs, ProtectedPageSlowViewState, ProtectedPageFastViewState, ProtectedPageInteractiveViewState, [WixMembersService], [_jay_framework_fullstack_component.Signals<ProtectedPageFastViewState>, ProtectedPageFastCarryForward], FastProps, {}, _jay_framework_component.JayComponentCore<FastProps, ProtectedPageInteractiveViewState>> & /*elided*/ any;
|
|
103
|
+
withInteractive(comp: _jay_framework_component.ComponentConstructor<FastProps, ProtectedPageRefs, ProtectedPageInteractiveViewState, [_jay_framework_fullstack_component.Signals<ProtectedPageFastViewState>, ProtectedPageFastCarryForward], _jay_framework_component.JayComponentCore<FastProps, ProtectedPageInteractiveViewState>>): _jay_framework_fullstack_component.JayStackComponentDefinition<ProtectedPageRefs, ProtectedPageSlowViewState, ProtectedPageFastViewState, ProtectedPageInteractiveViewState, [WixMembersService], [_jay_framework_fullstack_component.Signals<ProtectedPageFastViewState>, ProtectedPageFastCarryForward], FastProps, {}, _jay_framework_component.JayComponentCore<FastProps, ProtectedPageInteractiveViewState>>;
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
declare const init: _jay_framework_fullstack_component.JayInit<WixMembersInitData>;
|
|
107
|
+
|
|
108
|
+
export { type AuthCallbackResult as A, type ReactiveMemberIndicator as R, type WixMembersService as W, WIX_MEMBERS_SERVICE as a, WIX_MEMBERS_CONTEXT as b, type WixMembersContext as c, type WixMembersInitData as d, authCallback as e, protectedPage as f, init as i, loginIndicator as l, provideWixMembersContext as p };
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { A as AuthCallbackResult, R as ReactiveMemberIndicator, b as WIX_MEMBERS_CONTEXT, c as WixMembersContext, e as authCallback, i as init, l as loginIndicator, f as protectedPage } from './index.client-lddj65uZ.js';
|
|
2
|
+
import '@jay-framework/runtime';
|
|
3
|
+
import '@jay-framework/reactive';
|
|
4
|
+
import '@jay-framework/fullstack-component';
|
|
5
|
+
import '@jay-framework/component';
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { createJayContext, useGlobalContext } from "@jay-framework/runtime";
|
|
2
|
+
import { registerReactiveGlobalContext, createSignal, useReactive, createEvent, createEffect } from "@jay-framework/component";
|
|
3
|
+
import { WIX_CLIENT_CONTEXT } from "@jay-framework/wix-server-client/client";
|
|
4
|
+
import { makeJayStackComponent, makeJayInit } from "@jay-framework/fullstack-component";
|
|
5
|
+
const AUTH_COOKIE_NAME = "wix_auth_role";
|
|
6
|
+
function setAuthCookie(role) {
|
|
7
|
+
if (typeof document === "undefined") return;
|
|
8
|
+
if (role === "member") {
|
|
9
|
+
document.cookie = `${AUTH_COOKIE_NAME}=member; path=/; SameSite=Lax`;
|
|
10
|
+
} else {
|
|
11
|
+
document.cookie = `${AUTH_COOKIE_NAME}=; path=/; max-age=0`;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
const WIX_MEMBERS_CONTEXT = createJayContext("wix:members");
|
|
15
|
+
const OAUTH_DATA_KEY = "wix_members_oauth_data";
|
|
16
|
+
function provideWixMembersContext(initData) {
|
|
17
|
+
const wixClientContext = useGlobalContext(WIX_CLIENT_CONTEXT);
|
|
18
|
+
const wixClient = wixClientContext.client;
|
|
19
|
+
const auth = wixClient.auth;
|
|
20
|
+
const membersContext = registerReactiveGlobalContext(WIX_MEMBERS_CONTEXT, () => {
|
|
21
|
+
const [isLoggedIn, setIsLoggedIn] = createSignal(false);
|
|
22
|
+
const [isLoading, setIsLoading] = createSignal(true);
|
|
23
|
+
const [memberName, setMemberName] = createSignal("");
|
|
24
|
+
const [memberAvatar, setMemberAvatar] = createSignal("");
|
|
25
|
+
const reactive = useReactive();
|
|
26
|
+
const onLogin = createEvent();
|
|
27
|
+
const onLogout = createEvent();
|
|
28
|
+
function updateMemberSignals(loggedIn, name = "", avatar = "") {
|
|
29
|
+
reactive.batchReactions(() => {
|
|
30
|
+
setIsLoggedIn(loggedIn);
|
|
31
|
+
setIsLoading(false);
|
|
32
|
+
setMemberName(name);
|
|
33
|
+
setMemberAvatar(avatar);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
function getCallbackUrl() {
|
|
37
|
+
if (initData.authCallbackUrl) return initData.authCallbackUrl;
|
|
38
|
+
return window.location.origin + "/auth/callback";
|
|
39
|
+
}
|
|
40
|
+
async function redirectToLogin(callbackUrl) {
|
|
41
|
+
const redirectUri = callbackUrl || getCallbackUrl();
|
|
42
|
+
const oauthData = auth.generateOAuthData(redirectUri, window.location.href);
|
|
43
|
+
sessionStorage.setItem(OAUTH_DATA_KEY, JSON.stringify(oauthData));
|
|
44
|
+
const { authUrl } = await auth.getAuthUrl(oauthData, {
|
|
45
|
+
prompt: "login",
|
|
46
|
+
responseMode: "query"
|
|
47
|
+
});
|
|
48
|
+
return authUrl;
|
|
49
|
+
}
|
|
50
|
+
async function handleAuthCallback(url) {
|
|
51
|
+
const storedData = sessionStorage.getItem(OAUTH_DATA_KEY);
|
|
52
|
+
if (!storedData) {
|
|
53
|
+
return { success: false, redirectTo: "/", error: "No OAuth data found" };
|
|
54
|
+
}
|
|
55
|
+
const oauthData = JSON.parse(storedData);
|
|
56
|
+
sessionStorage.removeItem(OAUTH_DATA_KEY);
|
|
57
|
+
const { code, state, error, errorDescription } = auth.parseFromUrl(
|
|
58
|
+
url || window.location.href,
|
|
59
|
+
"query"
|
|
60
|
+
);
|
|
61
|
+
if (error) {
|
|
62
|
+
return {
|
|
63
|
+
success: false,
|
|
64
|
+
redirectTo: oauthData.originalUri || "/",
|
|
65
|
+
error: errorDescription || error
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
const memberTokens = await auth.getMemberTokens(code, state, oauthData);
|
|
69
|
+
auth.setTokens(memberTokens);
|
|
70
|
+
setAuthCookie("member");
|
|
71
|
+
updateMemberSignals(true);
|
|
72
|
+
onLogin.emit();
|
|
73
|
+
return {
|
|
74
|
+
success: true,
|
|
75
|
+
redirectTo: oauthData.originalUri || "/"
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
async function logout() {
|
|
79
|
+
try {
|
|
80
|
+
await auth.logout(window.location.href);
|
|
81
|
+
} catch {
|
|
82
|
+
}
|
|
83
|
+
const visitorTokens = await auth.generateVisitorTokens();
|
|
84
|
+
auth.setTokens(visitorTokens);
|
|
85
|
+
setAuthCookie("visitor");
|
|
86
|
+
updateMemberSignals(false);
|
|
87
|
+
onLogout.emit();
|
|
88
|
+
}
|
|
89
|
+
function refreshMemberState() {
|
|
90
|
+
const loggedIn = auth.loggedIn();
|
|
91
|
+
setAuthCookie(loggedIn ? "member" : "visitor");
|
|
92
|
+
updateMemberSignals(loggedIn);
|
|
93
|
+
}
|
|
94
|
+
return {
|
|
95
|
+
memberIndicator: {
|
|
96
|
+
isLoggedIn,
|
|
97
|
+
isLoading,
|
|
98
|
+
memberName,
|
|
99
|
+
memberAvatar
|
|
100
|
+
},
|
|
101
|
+
redirectToLogin,
|
|
102
|
+
handleAuthCallback,
|
|
103
|
+
logout,
|
|
104
|
+
refreshMemberState,
|
|
105
|
+
onLogin,
|
|
106
|
+
onLogout
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
return membersContext;
|
|
110
|
+
}
|
|
111
|
+
function LoginIndicatorInteractive(_props, refs, _viewStateSignals, _carryForward, membersContext) {
|
|
112
|
+
refs.loginButton?.onclick(async () => {
|
|
113
|
+
const url = await membersContext.redirectToLogin();
|
|
114
|
+
window.location.href = url;
|
|
115
|
+
});
|
|
116
|
+
refs.logoutButton?.onclick(() => {
|
|
117
|
+
membersContext.logout();
|
|
118
|
+
});
|
|
119
|
+
return {
|
|
120
|
+
render: () => ({
|
|
121
|
+
isLoggedIn: membersContext.memberIndicator.isLoggedIn(),
|
|
122
|
+
memberName: membersContext.memberIndicator.memberName(),
|
|
123
|
+
memberAvatar: membersContext.memberIndicator.memberAvatar(),
|
|
124
|
+
isLoading: membersContext.memberIndicator.isLoading()
|
|
125
|
+
})
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
const loginIndicator = makeJayStackComponent().withProps().withContexts(WIX_MEMBERS_CONTEXT).withInteractive(LoginIndicatorInteractive);
|
|
129
|
+
function AuthCallbackInteractive(_props, _refs, viewStateSignals, _carryForward, membersContext) {
|
|
130
|
+
const { isProcessing: [, setIsProcessing], hasError: [hasError, setHasError], errorMessage: [errorMessage, setErrorMessage] } = viewStateSignals;
|
|
131
|
+
createEffect(() => {
|
|
132
|
+
membersContext.handleAuthCallback().then((result) => {
|
|
133
|
+
setIsProcessing(false);
|
|
134
|
+
if (result.success) {
|
|
135
|
+
window.location.href = result.redirectTo;
|
|
136
|
+
} else {
|
|
137
|
+
setHasError(true);
|
|
138
|
+
setErrorMessage(result.error || "Authentication failed.");
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
render: () => ({
|
|
144
|
+
isProcessing: !hasError(),
|
|
145
|
+
hasError: hasError(),
|
|
146
|
+
errorMessage: errorMessage()
|
|
147
|
+
})
|
|
148
|
+
};
|
|
149
|
+
}
|
|
150
|
+
const authCallback = makeJayStackComponent().withProps().withContexts(WIX_MEMBERS_CONTEXT).withInteractive(AuthCallbackInteractive);
|
|
151
|
+
const protectedPage = makeJayStackComponent().withProps();
|
|
152
|
+
const init = makeJayInit().withClient(async (data) => {
|
|
153
|
+
console.log("[wix-members] Initializing client-side members context...");
|
|
154
|
+
const membersContext = provideWixMembersContext(data);
|
|
155
|
+
membersContext.refreshMemberState();
|
|
156
|
+
console.log("[wix-members] Client initialization complete");
|
|
157
|
+
});
|
|
158
|
+
export {
|
|
159
|
+
WIX_MEMBERS_CONTEXT,
|
|
160
|
+
authCallback,
|
|
161
|
+
init,
|
|
162
|
+
loginIndicator,
|
|
163
|
+
protectedPage
|
|
164
|
+
};
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { W as WixMembersService } from './index.client-lddj65uZ.js';
|
|
2
|
+
export { A as AuthCallbackResult, R as ReactiveMemberIndicator, b as WIX_MEMBERS_CONTEXT, a as WIX_MEMBERS_SERVICE, c as WixMembersContext, d as WixMembersInitData, e as authCallback, i as init, l as loginIndicator, f as protectedPage, p as provideWixMembersContext } from './index.client-lddj65uZ.js';
|
|
3
|
+
import '@jay-framework/runtime';
|
|
4
|
+
import '@jay-framework/reactive';
|
|
5
|
+
import '@jay-framework/fullstack-component';
|
|
6
|
+
import '@jay-framework/component';
|
|
7
|
+
|
|
8
|
+
declare function provideWixMembersService(): WixMembersService;
|
|
9
|
+
|
|
10
|
+
declare const AUTH_COOKIE_NAME = "wix_auth_role";
|
|
11
|
+
declare function setAuthCookie(role: 'member' | 'visitor'): void;
|
|
12
|
+
|
|
13
|
+
export { AUTH_COOKIE_NAME, WixMembersService, provideWixMembersService, setAuthCookie };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
import { registerService, getService } from "@jay-framework/stack-server-runtime";
|
|
2
|
+
import { createJayService, makeJayStackComponent, RenderPipeline, redirect3xx, makeJayInit } from "@jay-framework/fullstack-component";
|
|
3
|
+
import { createJayContext, useGlobalContext } from "@jay-framework/runtime";
|
|
4
|
+
import { registerReactiveGlobalContext, createSignal, useReactive, createEvent } from "@jay-framework/component";
|
|
5
|
+
import { WIX_CLIENT_CONTEXT, WIX_CLIENT_SERVICE } from "@jay-framework/wix-server-client";
|
|
6
|
+
const WIX_MEMBERS_SERVICE = createJayService("Wix Members Service");
|
|
7
|
+
function provideWixMembersService() {
|
|
8
|
+
const service = {};
|
|
9
|
+
registerService(WIX_MEMBERS_SERVICE, service);
|
|
10
|
+
return service;
|
|
11
|
+
}
|
|
12
|
+
const AUTH_COOKIE_NAME = "wix_auth_role";
|
|
13
|
+
function setAuthCookie(role) {
|
|
14
|
+
if (typeof document === "undefined") return;
|
|
15
|
+
if (role === "member") {
|
|
16
|
+
document.cookie = `${AUTH_COOKIE_NAME}=member; path=/; SameSite=Lax`;
|
|
17
|
+
} else {
|
|
18
|
+
document.cookie = `${AUTH_COOKIE_NAME}=; path=/; max-age=0`;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
const WIX_MEMBERS_CONTEXT = createJayContext("wix:members");
|
|
22
|
+
const OAUTH_DATA_KEY = "wix_members_oauth_data";
|
|
23
|
+
function provideWixMembersContext(initData) {
|
|
24
|
+
const wixClientContext = useGlobalContext(WIX_CLIENT_CONTEXT);
|
|
25
|
+
const wixClient = wixClientContext.client;
|
|
26
|
+
const auth = wixClient.auth;
|
|
27
|
+
const membersContext = registerReactiveGlobalContext(WIX_MEMBERS_CONTEXT, () => {
|
|
28
|
+
const [isLoggedIn, setIsLoggedIn] = createSignal(false);
|
|
29
|
+
const [isLoading, setIsLoading] = createSignal(true);
|
|
30
|
+
const [memberName, setMemberName] = createSignal("");
|
|
31
|
+
const [memberAvatar, setMemberAvatar] = createSignal("");
|
|
32
|
+
const reactive = useReactive();
|
|
33
|
+
const onLogin = createEvent();
|
|
34
|
+
const onLogout = createEvent();
|
|
35
|
+
function updateMemberSignals(loggedIn, name = "", avatar = "") {
|
|
36
|
+
reactive.batchReactions(() => {
|
|
37
|
+
setIsLoggedIn(loggedIn);
|
|
38
|
+
setIsLoading(false);
|
|
39
|
+
setMemberName(name);
|
|
40
|
+
setMemberAvatar(avatar);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
function getCallbackUrl() {
|
|
44
|
+
if (initData.authCallbackUrl) return initData.authCallbackUrl;
|
|
45
|
+
return window.location.origin + "/auth/callback";
|
|
46
|
+
}
|
|
47
|
+
async function redirectToLogin(callbackUrl) {
|
|
48
|
+
const redirectUri = callbackUrl || getCallbackUrl();
|
|
49
|
+
const oauthData = auth.generateOAuthData(redirectUri, window.location.href);
|
|
50
|
+
sessionStorage.setItem(OAUTH_DATA_KEY, JSON.stringify(oauthData));
|
|
51
|
+
const { authUrl } = await auth.getAuthUrl(oauthData, {
|
|
52
|
+
prompt: "login",
|
|
53
|
+
responseMode: "query"
|
|
54
|
+
});
|
|
55
|
+
return authUrl;
|
|
56
|
+
}
|
|
57
|
+
async function handleAuthCallback(url) {
|
|
58
|
+
const storedData = sessionStorage.getItem(OAUTH_DATA_KEY);
|
|
59
|
+
if (!storedData) {
|
|
60
|
+
return { success: false, redirectTo: "/", error: "No OAuth data found" };
|
|
61
|
+
}
|
|
62
|
+
const oauthData = JSON.parse(storedData);
|
|
63
|
+
sessionStorage.removeItem(OAUTH_DATA_KEY);
|
|
64
|
+
const { code, state, error, errorDescription } = auth.parseFromUrl(
|
|
65
|
+
url || window.location.href,
|
|
66
|
+
"query"
|
|
67
|
+
);
|
|
68
|
+
if (error) {
|
|
69
|
+
return {
|
|
70
|
+
success: false,
|
|
71
|
+
redirectTo: oauthData.originalUri || "/",
|
|
72
|
+
error: errorDescription || error
|
|
73
|
+
};
|
|
74
|
+
}
|
|
75
|
+
const memberTokens = await auth.getMemberTokens(code, state, oauthData);
|
|
76
|
+
auth.setTokens(memberTokens);
|
|
77
|
+
setAuthCookie("member");
|
|
78
|
+
updateMemberSignals(true);
|
|
79
|
+
onLogin.emit();
|
|
80
|
+
return {
|
|
81
|
+
success: true,
|
|
82
|
+
redirectTo: oauthData.originalUri || "/"
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
async function logout() {
|
|
86
|
+
try {
|
|
87
|
+
await auth.logout(window.location.href);
|
|
88
|
+
} catch {
|
|
89
|
+
}
|
|
90
|
+
const visitorTokens = await auth.generateVisitorTokens();
|
|
91
|
+
auth.setTokens(visitorTokens);
|
|
92
|
+
setAuthCookie("visitor");
|
|
93
|
+
updateMemberSignals(false);
|
|
94
|
+
onLogout.emit();
|
|
95
|
+
}
|
|
96
|
+
function refreshMemberState() {
|
|
97
|
+
const loggedIn = auth.loggedIn();
|
|
98
|
+
setAuthCookie(loggedIn ? "member" : "visitor");
|
|
99
|
+
updateMemberSignals(loggedIn);
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
memberIndicator: {
|
|
103
|
+
isLoggedIn,
|
|
104
|
+
isLoading,
|
|
105
|
+
memberName,
|
|
106
|
+
memberAvatar
|
|
107
|
+
},
|
|
108
|
+
redirectToLogin,
|
|
109
|
+
handleAuthCallback,
|
|
110
|
+
logout,
|
|
111
|
+
refreshMemberState,
|
|
112
|
+
onLogin,
|
|
113
|
+
onLogout
|
|
114
|
+
};
|
|
115
|
+
});
|
|
116
|
+
return membersContext;
|
|
117
|
+
}
|
|
118
|
+
async function renderFastChanging$2(_props, _membersService) {
|
|
119
|
+
const Pipeline = RenderPipeline.for();
|
|
120
|
+
return Pipeline.ok(null).toPhaseOutput(() => ({
|
|
121
|
+
viewState: {
|
|
122
|
+
isLoggedIn: false,
|
|
123
|
+
memberName: "",
|
|
124
|
+
memberAvatar: "",
|
|
125
|
+
isLoading: true
|
|
126
|
+
},
|
|
127
|
+
carryForward: {}
|
|
128
|
+
}));
|
|
129
|
+
}
|
|
130
|
+
const loginIndicator = makeJayStackComponent().withProps().withServices(WIX_MEMBERS_SERVICE).withFastRender(renderFastChanging$2);
|
|
131
|
+
async function renderFastChanging$1(_props, _membersService) {
|
|
132
|
+
const Pipeline = RenderPipeline.for();
|
|
133
|
+
return Pipeline.ok(null).toPhaseOutput(() => ({
|
|
134
|
+
viewState: {
|
|
135
|
+
isProcessing: true,
|
|
136
|
+
hasError: false,
|
|
137
|
+
errorMessage: ""
|
|
138
|
+
},
|
|
139
|
+
carryForward: {}
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
const authCallback = makeJayStackComponent().withProps().withServices(WIX_MEMBERS_SERVICE).withFastRender(renderFastChanging$1);
|
|
143
|
+
async function renderFastChanging(props, _membersService) {
|
|
144
|
+
const Pipeline = RenderPipeline.for();
|
|
145
|
+
const authRole = props.cookies[AUTH_COOKIE_NAME];
|
|
146
|
+
if (authRole !== "member") {
|
|
147
|
+
const loginUrl = props.loginUrl || "/login";
|
|
148
|
+
return redirect3xx(302, loginUrl);
|
|
149
|
+
}
|
|
150
|
+
return Pipeline.ok(null).toPhaseOutput(() => ({
|
|
151
|
+
viewState: {
|
|
152
|
+
isLoggedIn: true
|
|
153
|
+
},
|
|
154
|
+
carryForward: {},
|
|
155
|
+
responseHeaders: { "Cache-Control": "no-store" }
|
|
156
|
+
}));
|
|
157
|
+
}
|
|
158
|
+
const protectedPage = makeJayStackComponent().withProps().withServices(WIX_MEMBERS_SERVICE).withFastRender(renderFastChanging);
|
|
159
|
+
const init = makeJayInit().withServer(async () => {
|
|
160
|
+
console.log("[wix-members] Initializing Wix Members service...");
|
|
161
|
+
getService(WIX_CLIENT_SERVICE);
|
|
162
|
+
provideWixMembersService();
|
|
163
|
+
console.log("[wix-members] Server initialization complete");
|
|
164
|
+
return {};
|
|
165
|
+
});
|
|
166
|
+
export {
|
|
167
|
+
AUTH_COOKIE_NAME,
|
|
168
|
+
WIX_MEMBERS_CONTEXT,
|
|
169
|
+
WIX_MEMBERS_SERVICE,
|
|
170
|
+
authCallback,
|
|
171
|
+
init,
|
|
172
|
+
loginIndicator,
|
|
173
|
+
protectedPage,
|
|
174
|
+
provideWixMembersContext,
|
|
175
|
+
provideWixMembersService,
|
|
176
|
+
setAuthCookie
|
|
177
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@jay-framework/wix-members",
|
|
3
|
+
"version": "0.19.7",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "Wix Members authentication package for Jay Framework",
|
|
6
|
+
"license": "Apache-2.0",
|
|
7
|
+
"main": "dist/index.js",
|
|
8
|
+
"files": [
|
|
9
|
+
"dist",
|
|
10
|
+
"plugin.yaml"
|
|
11
|
+
],
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"default": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"./client": {
|
|
18
|
+
"types": "./dist/index.client.d.ts",
|
|
19
|
+
"default": "./dist/index.client.js"
|
|
20
|
+
},
|
|
21
|
+
"./plugin.yaml": "./plugin.yaml",
|
|
22
|
+
"./login-indicator.jay-contract": "./dist/contracts/login-indicator.jay-contract",
|
|
23
|
+
"./auth-callback.jay-contract": "./dist/contracts/auth-callback.jay-contract",
|
|
24
|
+
"./protected-page.jay-contract": "./dist/contracts/protected-page.jay-contract"
|
|
25
|
+
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "npm run clean && npm run definitions && npm run build:client && npm run build:server && npm run build:copy-contract && npm run build:types && npm run validate",
|
|
28
|
+
"definitions": "jay-cli definitions lib",
|
|
29
|
+
"validate": "jay-stack-cli validate-plugin",
|
|
30
|
+
"build:client": "vite build",
|
|
31
|
+
"build:server": "vite build --ssr",
|
|
32
|
+
"build:copy-contract": "mkdir -p dist/contracts && cp lib/contracts/*.jay-contract* dist/contracts/",
|
|
33
|
+
"build:types": "tsup lib/index.ts lib/index.client.ts --dts-only --format esm",
|
|
34
|
+
"build:check-types": "tsc",
|
|
35
|
+
"clean": "rimraf dist",
|
|
36
|
+
"confirm": "npm run clean && npm run build && npm run test",
|
|
37
|
+
"test": ":"
|
|
38
|
+
},
|
|
39
|
+
"dependencies": {
|
|
40
|
+
"@jay-framework/component": "^0.19.7",
|
|
41
|
+
"@jay-framework/fullstack-component": "^0.19.7",
|
|
42
|
+
"@jay-framework/reactive": "^0.19.7",
|
|
43
|
+
"@jay-framework/runtime": "^0.19.7",
|
|
44
|
+
"@jay-framework/secure": "^0.19.7",
|
|
45
|
+
"@jay-framework/stack-client-runtime": "^0.19.7",
|
|
46
|
+
"@jay-framework/stack-server-runtime": "^0.19.7",
|
|
47
|
+
"@jay-framework/wix-server-client": "^0.19.7",
|
|
48
|
+
"@jay-framework/wix-utils": "^0.19.7",
|
|
49
|
+
"@wix/redirects": "^1.0.88",
|
|
50
|
+
"@wix/sdk": "^1.21.5",
|
|
51
|
+
"@wix/sdk-runtime": "^1.0.11"
|
|
52
|
+
},
|
|
53
|
+
"devDependencies": {
|
|
54
|
+
"@babel/core": "^7.23.7",
|
|
55
|
+
"@babel/preset-env": "^7.23.8",
|
|
56
|
+
"@babel/preset-typescript": "^7.23.3",
|
|
57
|
+
"@jay-framework/compiler-jay-stack": "^0.19.7",
|
|
58
|
+
"@jay-framework/jay-cli": "^0.19.7",
|
|
59
|
+
"@jay-framework/vite-plugin": "^0.19.7",
|
|
60
|
+
"@jay-framework/wix-dev-environment": "^0.6.12",
|
|
61
|
+
"nodemon": "^3.0.3",
|
|
62
|
+
"rimraf": "^5.0.5",
|
|
63
|
+
"tslib": "^2.6.2",
|
|
64
|
+
"tsup": "^8.5.1",
|
|
65
|
+
"typescript": "^5.3.3",
|
|
66
|
+
"vite": "^5.0.11",
|
|
67
|
+
"vitest": "^1.2.0"
|
|
68
|
+
}
|
|
69
|
+
}
|
package/plugin.yaml
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
name: wix-members
|
|
2
|
+
|
|
3
|
+
contracts:
|
|
4
|
+
- name: login-indicator
|
|
5
|
+
contract: login-indicator.jay-contract
|
|
6
|
+
component: loginIndicator
|
|
7
|
+
description: Shows member auth state in site header, with login/register/logout buttons
|
|
8
|
+
- name: auth-callback
|
|
9
|
+
contract: auth-callback.jay-contract
|
|
10
|
+
component: authCallback
|
|
11
|
+
description: Handles OAuth callback after Wix-hosted login/register
|
|
12
|
+
- name: protected-page
|
|
13
|
+
contract: protected-page.jay-contract
|
|
14
|
+
component: protectedPage
|
|
15
|
+
description: Page-level login guard — redirects visitors to login page
|
|
16
|
+
|
|
17
|
+
services:
|
|
18
|
+
- name: wix-members
|
|
19
|
+
marker: WIX_MEMBERS_SERVICE
|
|
20
|
+
description: Server-side member operations via Wix Members API
|
|
21
|
+
|
|
22
|
+
contexts:
|
|
23
|
+
- name: wix-members
|
|
24
|
+
marker: WIX_MEMBERS_CONTEXT
|
|
25
|
+
description: Client-side member auth state, redirect login/register/logout operations
|