@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.
@@ -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
+ };
@@ -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