Skip to content

Commit

Permalink
feat: access session on ssr #26 (NTR)
Browse files Browse the repository at this point in the history
  • Loading branch information
patzick committed Dec 2, 2022
1 parent e9594e3 commit e21d67b
Show file tree
Hide file tree
Showing 23 changed files with 130 additions and 64 deletions.
5 changes: 5 additions & 0 deletions .changeset/small-kiwis-remember.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@shopware-pwa/types": minor
---

removed wrong `User` type and replaces with proper `Customer`
6 changes: 6 additions & 0 deletions .changeset/small-mayflies-add.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"@shopware-pwa/composables-next": minor
"vue-demo-store": minor
---

improved session context to be better handled on SSR
5 changes: 5 additions & 0 deletions .changeset/thirty-dodos-drop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@shopware-pwa/nuxt3-module": patch
---

`swSessionContext` available also in Nuxt `useState`
5 changes: 5 additions & 0 deletions .changeset/wild-gifts-brake.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"vue-demo-store": minor
---

added to template `useAuthGuard` which redirects to homepage if user is not logged in. You can adjust it to your desired behaviour.
1 change: 1 addition & 0 deletions packages/composables/build.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,5 +10,6 @@ export default defineBuildConfig({
"@shopware-pwa/api-client",
"@shopware-pwa/helpers-next",
"@shopware-pwa/types",
"@vueuse/core",
],
});
22 changes: 18 additions & 4 deletions packages/composables/src/internal/_useContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,26 @@ import { inject, provide, ref, Ref, unref } from "vue";
/**
* Internal context helper
*/
export function _useContext<T>(injectionName: string, context?: Ref<T> | T) {
const isNewContext = !!context;
export function _useContext<T>(
injectionName: string,
params?: {
context?: Ref<T> | T;
replace?: T;
}
) {
const isNewContext = !!params?.context;

const _context: Ref<T> = isNewContext
? (ref(unref(context)) as Ref<T>)
: (inject(injectionName) as Ref<T>);
? (ref(unref(params?.context)) as Ref<T>)
: (inject(injectionName, ref()) as Ref<T>);
provide(injectionName, _context);

/**
* Used for global context to replace it with new Value. Used mainly for session context
*/
if (!!params?.replace) {
_context.value = unref(params.replace);
}

return _context;
}
2 changes: 1 addition & 1 deletion packages/composables/src/useCategory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ export type UseCategoryReturn = {
};

export function useCategory(category?: Ref<Category>): UseCategoryReturn {
const _category = _useContext("category", category);
const _category = _useContext("category", { context: category });
if (!_category.value) {
// TODO link docs with composables context usage
throw new Error("Category context is not provided.");
Expand Down
2 changes: 1 addition & 1 deletion packages/composables/src/useNavigationContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ export type UseNavigationContextReturn = {
export function useNavigationContext(
context?: Ref<SeoUrl | null>
): UseNavigationContextReturn {
const _context = _useContext("navigation", context);
const _context = _useContext("navigation", { context: context });

const routeName = computed(() => _context.value?.routeName);
const foreignKey = computed(() => _context.value?.foreignKey || "");
Expand Down
6 changes: 4 additions & 2 deletions packages/composables/src/useProduct.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,14 @@ export function useProduct(
product?: Ref<Product> | Product,
configurator?: Ref<PropertyGroup[]> | PropertyGroup[]
): UseProductReturn {
const _product = _useContext("product", product);
const _product = _useContext("product", { context: product });
if (!_product.value) {
// TODO link docs with composables context usage
throw new Error("Product context is not provided");
}
const _configurator = _useContext("configurator", product && configurator);
const _configurator = _useContext("configurator", {
context: product && configurator,
});

function changeVariant(variant: Partial<Product>) {
_product.value = Object.assign({}, _product.value, variant);
Expand Down
25 changes: 10 additions & 15 deletions packages/composables/src/useSessionContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import {
} from "@shopware-pwa/api-client";
import { useShopwareContext } from "./useShopwareContext";
import { usePrice } from "./usePrice";
import { useUser } from "./useUser";
import { _useContext } from "./internal/_useContext";

export type UseSessionContextReturn = {
sessionContext: ComputedRef<SessionContext | undefined>;
Expand All @@ -46,7 +46,7 @@ export type UseSessionContextReturn = {
onShippingMethodChange: (
fn: (params: { shippingMethod: ShippingMethod }) => void
) => void;
userFromContext: ComputedRef<Customer | null>;
userFromContext: ComputedRef<Customer | undefined>;
};

interface IInterceptorCallbackFunction {
Expand All @@ -57,35 +57,30 @@ interface IInterceptorCallbackFunction {
* Composable for session management. Options - {@link UseSessionContextReturn}
* SessionContext contain all related data like user, currency, country, shippingMethod, paymentMethod etc.
*/
export function useSessionContext(): UseSessionContextReturn {
export function useSessionContext(
newContext?: SessionContext
): UseSessionContextReturn {
const { apiInstance } = useShopwareContext();
const { setUser } = useUser();
const { init } = usePrice();
// const { broadcast, intercept } = useIntercept();

// const { sharedRef } = useSharedState();
const storeSessionContext: Ref<SessionContext | any> = inject(
"swSessionContext",
ref()
);
provide("swSessionContext", storeSessionContext);
const _sessinContext = _useContext("swSessionContext", {
replace: newContext,
});

const onCurrencyChange = (fn: IInterceptorCallbackFunction) => {}; // intercept(INTERCEPTOR_KEYS.SESSION_SET_CURRENCY, fn);
const onPaymentMethodChange = (fn: IInterceptorCallbackFunction) => {}; // intercept(INTERCEPTOR_KEYS.SESSION_SET_PAYMENT_METHOD, fn);
const onShippingMethodChange = (fn: IInterceptorCallbackFunction) => {}; // intercept(INTERCEPTOR_KEYS.SESSION_SET_SHIPPING_METHOD, fn);

const sessionContext = computed(() => storeSessionContext.value);
const sessionContext = computed(() => _sessinContext.value);
const refreshSessionContext = async () => {
try {
const context = await getSessionContext(apiInstance);
storeSessionContext.value = context;
_sessinContext.value = context;
init({
currencyPosition: context.currency.position,
currencySymbol: context.currency.symbol,
});
if (context.customer) {
setUser(context.customer);
}
} catch (e) {
console.error("[UseSessionContext][refreshSessionContext]", e);
}
Expand Down
38 changes: 22 additions & 16 deletions packages/composables/src/useUser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,21 @@ import {
import {
Customer,
CustomerRegistrationParams,
ClientApiError,
ShopwareError,
Country,
Salutation,
ShopwareSearchParams,
PaymentMethodTranslation,
BillingAddress,
ShippingAddress,
} from "@shopware-pwa/types";
import { useShopwareContext, useCart, useInternationalization } from ".";
import {
useShopwareContext,
useCart,
useInternationalization,
useSessionContext,
} from ".";
import { _useContext } from "./internal/_useContext";
import { syncRefs } from "@vueuse/core";

export type UseUserReturn = {
login: (params: { username: string; password: string }) => Promise<void>;
Expand All @@ -44,25 +49,26 @@ export type UseUserReturn = {
updatePersonalInfo: (personals: CustomerUpdateProfileParam) => Promise<void>;
updateEmail: (updateEmailData: CustomerUpdateEmailParam) => Promise<void>;
setDefaultPaymentMethod: (paymentMethodId: string) => Promise<void>;
setUser: (user: Partial<Customer>) => void;
userDefaultPaymentMethod: ComputedRef<PaymentMethodTranslation | null>;
userDefaultBillingAddress: ComputedRef<BillingAddress | null>;
userDefaultShippingAddress: ComputedRef<ShippingAddress | null>;
};

const storeUser = ref<Partial<Customer>>();

/**
* Composable for user management. Options - {@link UseUserReturn}
*/
export function useUser(): UseUserReturn {
const { apiInstance } = useShopwareContext();
const { userFromContext, refreshSessionContext } = useSessionContext();

const _user = _useContext<Customer | undefined>("customer");
syncRefs(userFromContext, _user, {
immediate: true,
});

const { getStorefrontUrl } = useInternationalization();
const { refreshCart } = useCart();

const setUser = (user: Partial<Customer>) => {
storeUser.value = user;
};
const userDefaultPaymentMethod = computed(
() => user.value?.defaultPaymentMethod?.translated || null
);
Expand All @@ -74,14 +80,14 @@ export function useUser(): UseUserReturn {
);
const country: Ref<Country | null> = ref(null);
const salutation: Ref<Salutation | null> = ref(null);
const user = computed(() => storeUser.value);
const user = computed(() => _user.value);

async function login({
username,
password,
}: { username?: string; password?: string } = {}): Promise<void> {
await apiLogin({ username, password }, apiInstance);
await refreshUser();
await refreshSessionContext();
refreshCart();
}

Expand All @@ -92,13 +98,14 @@ export function useUser(): UseUserReturn {
{ ...params, storefrontUrl: getStorefrontUrl() } as any,
apiInstance
);
storeUser.value = customer;
_user.value = customer;
await refreshSessionContext();
return customer;
}

async function logout(): Promise<void> {
await apiLogout(apiInstance);
await refreshUser();
await refreshSessionContext();
refreshCart();
}

Expand All @@ -112,9 +119,9 @@ export function useUser(): UseUserReturn {
),
apiInstance
);
storeUser.value = (user as Customer) || {};
_user.value = user as Customer;
} catch (e) {
storeUser.value = {};
_user.value = undefined;
console.error("[useUser][refreshUser]", e);
}
}
Expand Down Expand Up @@ -172,7 +179,6 @@ export function useUser(): UseUserReturn {
salutation,
loadCountry,
country,
setUser,
defaultBillingAddressId,
defaultShippingAddressId,
userDefaultPaymentMethod,
Expand Down
5 changes: 4 additions & 1 deletion packages/nuxt3-module/plugin.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ const ShopwarePlugin = {
shopwareDefaults: options.apiDefaults,
});
app.provide("shopware", shopwareContext);
app.provide("swSessionContext", ref());
const sessionContextData = ref();
app.provide("swSessionContext", sessionContextData);
// in case someone tries to use it in nuxt specific code like middleware
useState("swSessionContext", () => sessionContextData);
},
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import { Document } from "../../checkout/document/Document";
import { ProductManufacturer } from "../product/ProductManufacturer";
import { OrderLineItem } from "../../checkout/order/OrderLineItem";
import { CustomField } from "../../common/CustomField";
import { User } from "../../system/user/User";
import { Customer } from "../../checkout/customer/Customer";

/**
* @public
Expand All @@ -33,12 +33,12 @@ export type Media = {
alt: string | null;
url: string;
fileName: string;
user: User;
user: Customer;
translations: MediaTranslation[] | null;
categories: Category[] | null;
productManufacturers: ProductManufacturer[] | null;
productMedia: ProductMedia | null;
avatarUser: User | null;
avatarUser: Customer | null;
thumbnails: MediaThumbnail[] | null;
mediaFolderId: string | null;
mediaFolder: MediaFolder | null;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { LocaleTranslation } from "./LocaleTranslation";
import { User } from "../user/User";
import { Language } from "../../framework/language/Language";
import { CustomField } from "../../common/CustomField";
import { Customer } from "../../checkout/customer/Customer";

/**
* @public
Expand All @@ -11,7 +11,7 @@ export type Locale = {
name: string | null;
territory: string | null;
translations: LocaleTranslation[] | null;
users: User[] | null;
users: Customer[] | null;
languages: Language[] | null;
customFields: CustomField | null;
};
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { StateMachineState } from "./StateMachineState";
import { StateMachine } from "./StateMachine";
import { User } from "../user/User";
import { Customer } from "../../checkout/customer/Customer";

/**
* @public
Expand All @@ -15,5 +15,5 @@ export type StateMachineHistory = {
toStateId: string;
toStateMachineState: StateMachineState | null;
userId: string;
user: User | null;
user: Customer | null;
};
6 changes: 0 additions & 6 deletions packages/types/shopware-6-client/models/system/user/User.d.ts

This file was deleted.

4 changes: 2 additions & 2 deletions packages/types/shopware-6-client/response/SessionContext.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import { PaymentMethod } from "../models/checkout/payment/PaymentMethod";
import { ShippingMethod } from "../models/checkout/shipping/ShippingMethod";
import { ShippingAddress } from "../models/checkout/customer/ShippingAddress";
import { Country } from "../models/system/country/Country";
import { User } from "../models/system/user/User";
import { Currency } from "../models/system/currency/Currency";
import { Language } from "../models/framework/language/Language";
import { Category } from "../models/content/category/Category";
import { Customer } from "../models/checkout/customer/Customer";

export type ContextTokenResponse = {
contextToken: string;
Expand Down Expand Up @@ -112,7 +112,7 @@ export type SessionContext = {
id: string;
name: string;
}[];
customer?: User;
customer?: Customer;
paymentMethod: PaymentMethod;
shippingMethod: ShippingMethod;
shippingLocation: {
Expand Down
Loading

0 comments on commit e21d67b

Please sign in to comment.