@websolutespa/bom-mixer-models 0.0.1

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.
Files changed (41) hide show
  1. package/.turbo/turbo-build.log +17 -0
  2. package/CHANGELOG.md +7 -0
  3. package/dist/index.d.ts +409 -0
  4. package/dist/index.js +2574 -0
  5. package/dist/index.mjs +2519 -0
  6. package/package.json +54 -0
  7. package/src/cart/cart.ts +31 -0
  8. package/src/category/category.service.ts +43 -0
  9. package/src/category/category.ts +26 -0
  10. package/src/checkout/checkout.service.ts +351 -0
  11. package/src/checkout/checkout.ts +65 -0
  12. package/src/country/country.service.ts +9 -0
  13. package/src/feature_type/feature_type.service.ts +10 -0
  14. package/src/feature_type/feature_type.ts +13 -0
  15. package/src/index.ts +33 -0
  16. package/src/label/label.service.ts +24 -0
  17. package/src/label/label.ts +7 -0
  18. package/src/layout/layout.service.ts +51 -0
  19. package/src/layout/layout.ts +27 -0
  20. package/src/link/link.ts +7 -0
  21. package/src/list/list.service.ts +19 -0
  22. package/src/list/list.ts +11 -0
  23. package/src/locale/locale.service.ts +11 -0
  24. package/src/locale/locale.ts +9 -0
  25. package/src/market/market.service.ts +10 -0
  26. package/src/market/market.ts +11 -0
  27. package/src/media/media.ts +14 -0
  28. package/src/menu/menu.service.ts +22 -0
  29. package/src/menu/menu.ts +11 -0
  30. package/src/order/order.service.ts +29 -0
  31. package/src/order/order.ts +31 -0
  32. package/src/page/page.service.ts +132 -0
  33. package/src/page/page.ts +53 -0
  34. package/src/province/province.service.ts +9 -0
  35. package/src/region/region.service.ts +9 -0
  36. package/src/route/route.interceptor.ts +30 -0
  37. package/src/route/route.service.ts +203 -0
  38. package/src/route/route.ts +29 -0
  39. package/src/store/store.ts +24 -0
  40. package/src/user/user.ts +57 -0
  41. package/tsconfig.json +16 -0
@@ -0,0 +1,51 @@
1
+ import { ILabel } from '../label/label';
2
+ import { getLabels } from '../label/label.service';
3
+ import { ILocale } from '../locale/locale';
4
+ import { getLocales } from '../locale/locale.service';
5
+ import { IMarket } from '../market/market';
6
+ import { getMarkets } from '../market/market.service';
7
+ import { IRouteLink } from '../route/route';
8
+ import { getRouteLinkTree } from '../route/route.service';
9
+ import { ILayout } from './layout';
10
+
11
+ export async function getLayout(market: string, locale: string): Promise<ILayout> {
12
+ // const store = await getStore<IModelStore>();
13
+ const markets: IMarket[] = await getMarkets({ locale });
14
+ const locales: ILocale[] = await getLocales({ locale });
15
+ const labels: ILabel[] = await getLabels({ locale });
16
+ const tree = await getRouteLinkTree(market, locale);
17
+ const firstLevelRoutes = tree?.items || [];
18
+ const flatTopLevelRoutes = tree ? [tree, ...firstLevelRoutes] : [];
19
+ const topLevelRoutes = flatTopLevelRoutes.reduce((object, route: IRouteLink) => {
20
+ object[route.id] = route;
21
+ return object;
22
+ }, {} as { [key: string]: IRouteLink });
23
+ const topLevelHrefs = flatTopLevelRoutes.reduce((object, route: IRouteLink) => {
24
+ if (route.href) {
25
+ object[route.id] = route.href;
26
+ }
27
+ return object;
28
+ }, {} as { [key: string]: string });
29
+ const navs = {
30
+ primary: (tree && tree.items ? tree.items : []),
31
+ secondary: [],
32
+ footer: [],
33
+ };
34
+ /*
35
+ // get known routes eg 'reserved_area', 'login', 'homepage';
36
+ const knownRoutes = await getRoutesForSchemas(['homepage', 'login', 'reserved_area'], market, locale);
37
+ // console.log('knownRoutes', knownRoutes);
38
+ */
39
+ // console.log('getLayout', market, locale);
40
+ return {
41
+ markets,
42
+ market,
43
+ locales,
44
+ locale,
45
+ labels,
46
+ tree,
47
+ navs,
48
+ topLevelRoutes,
49
+ topLevelHrefs,
50
+ };
51
+ }
@@ -0,0 +1,27 @@
1
+ import { ILabel } from '../label/label';
2
+ import { ILocale } from '../locale/locale';
3
+ import { IMarket } from '../market/market';
4
+ import { IRouteLink } from '../route/route';
5
+
6
+ export type ILayout = {
7
+ market: string;
8
+ locale: string;
9
+ markets: IMarket[];
10
+ locales: ILocale[];
11
+ labels: ILabel[];
12
+ tree?: IRouteLink;
13
+ navs: {
14
+ [key: string]: IRouteLink[],
15
+ };
16
+ topLevelRoutes: {
17
+ [key: string]: IRouteLink;
18
+ };
19
+ topLevelHrefs: {
20
+ [key: string]: string;
21
+ };
22
+ /*
23
+ knownRoutes?: {
24
+ [key: string]: string;
25
+ };
26
+ */
27
+ };
@@ -0,0 +1,7 @@
1
+
2
+ export type ILink = {
3
+ href: string;
4
+ title: string;
5
+ type?: string;
6
+ secure?: boolean;
7
+ };
@@ -0,0 +1,19 @@
1
+ import { getStore } from '@websolutespa/bom-mixer-store';
2
+ import { IModelStore } from '../store/store';
3
+ import { IKeyedList, IList } from './list';
4
+
5
+ export async function getLists(locale?: string): Promise<IList[]> {
6
+ const store = await getStore<IModelStore>();
7
+ const items = await store.list.findMany({ locale });
8
+ return items;
9
+ }
10
+
11
+ export async function getListByKeys(keys: string[], locale?: string): Promise<{ [key: string]: IList[] }> {
12
+ const store = await getStore<IModelStore>();
13
+ const items = await store.list.findMany({ locale });
14
+ const lists: { [key: string]: IList[] } = {};
15
+ (items.filter((x: IList) => x.key && keys.includes(x.key)) as IKeyedList[]).forEach(x => {
16
+ lists[x.key] = items.filter((i: any) => i.listId === x.id);
17
+ });
18
+ return lists;
19
+ }
@@ -0,0 +1,11 @@
1
+ import { IEquatable, INamedEntity } from '@websolutespa/bom-mixer-core';
2
+
3
+ export type IList = INamedEntity & {
4
+ key?: string;
5
+ listId?: IEquatable;
6
+ items?: IList[];
7
+ };
8
+
9
+ export type IKeyedList = IList & {
10
+ key: string;
11
+ };
@@ -0,0 +1,11 @@
1
+ import { QueryParams } from '@websolutespa/bom-mixer-core';
2
+ import { getStore } from '@websolutespa/bom-mixer-store';
3
+ import { IModelStore } from '../store/store';
4
+ import { ILocale } from './locale';
5
+
6
+ export async function getLocales(params: QueryParams = {}): Promise<ILocale[]> {
7
+ const store = await getStore<IModelStore>();
8
+ const items = await store.locale.findMany(params);
9
+ return items;
10
+ }
11
+
@@ -0,0 +1,9 @@
1
+ import { IEntity } from '@websolutespa/bom-mixer-core';
2
+
3
+ export type ILocale = IEntity & {
4
+ id: string;
5
+ // schema?: string;
6
+ title?: string;
7
+ isActive?: boolean;
8
+ isDefault?: boolean;
9
+ };
@@ -0,0 +1,10 @@
1
+ import { QueryParams } from '@websolutespa/bom-mixer-core';
2
+ import { getStore } from '@websolutespa/bom-mixer-store';
3
+ import { IModelStore } from '../store/store';
4
+ import { IMarket } from './market';
5
+
6
+ export async function getMarkets(params: QueryParams = {}): Promise<IMarket[]> {
7
+ const store = await getStore<IModelStore>();
8
+ const items = await store.market.findMany(params);
9
+ return items;
10
+ }
@@ -0,0 +1,11 @@
1
+ import { IEntity } from '@websolutespa/bom-mixer-core';
2
+
3
+ export type IMarket = IEntity & {
4
+ id: string;
5
+ title?: string;
6
+ isActive?: boolean;
7
+ isDefault?: boolean;
8
+ countries?: string[];
9
+ languages?: string[];
10
+ defaultLanguage?: string;
11
+ };
@@ -0,0 +1,14 @@
1
+
2
+ export type IMediaType = 'image' | 'video' | string;
3
+
4
+ export type IMedia = {
5
+ src: string;
6
+ type: IMediaType;
7
+ alt?: string;
8
+ title?: string;
9
+ abstract?: string;
10
+ width?: number;
11
+ height?: number;
12
+ url?: string; // !!! todo remap payloadcms media
13
+ media?: IMedia; // !!! todo remap payloadcms media
14
+ };
@@ -0,0 +1,22 @@
1
+ import { IEquatable } from '@websolutespa/bom-mixer-core';
2
+ import { getStore } from '@websolutespa/bom-mixer-store';
3
+ import { IModelStore } from '../store/store';
4
+ import { IMenu } from './menu';
5
+
6
+ export async function getMenu(id: IEquatable): Promise<IMenu | undefined> {
7
+ const store = await getStore<IModelStore>();
8
+ const item = await store.menu.findOne({
9
+ where: {
10
+ id: {
11
+ equals: id,
12
+ }
13
+ },
14
+ });
15
+ return item;
16
+ }
17
+
18
+ export async function getMenus(): Promise<IMenu[]> {
19
+ const store = await getStore<IModelStore>();
20
+ const items = await store.menu.findMany();
21
+ return items;
22
+ }
@@ -0,0 +1,11 @@
1
+ import { IEntity, IEquatable } from '@websolutespa/bom-mixer-core';
2
+
3
+ export type IMenu = IEntity & {
4
+ id: IEquatable;
5
+ items: IMenuItem[];
6
+ };
7
+
8
+ export type IMenuItem = {
9
+ name: string;
10
+ href: string;
11
+ };
@@ -0,0 +1,29 @@
1
+ import { IEquatable } from '@websolutespa/bom-mixer-core';
2
+ import { OrderDefaults } from '@websolutespa/bom-mixer-mock';
3
+ import { getRoutesForTemplates } from '../route/route.service';
4
+ import { IOrderDetail } from './order';
5
+
6
+ export async function getOrders(market: string, locale: string): Promise<IOrderDetail[]> {
7
+ const knownRoutes = await getRoutesForTemplates(['reserved_area_order_detail'], market, locale);
8
+ return OrderDefaults.items.map(x => {
9
+ const orderDetail: IOrderDetail = {
10
+ ...x,
11
+ href: `${knownRoutes.reserved_area_order_detail}?orderId=${x.id}`,
12
+ };
13
+ return orderDetail;
14
+ });
15
+ }
16
+
17
+ export async function getOrder(id: IEquatable, market: string, locale: string): Promise<IOrderDetail | null> {
18
+ const knownRoutes = await getRoutesForTemplates(['reserved_area_order_detail'], market, locale);
19
+ const order = OrderDefaults.items.find(x => String(x.id) === String(id)) || null;
20
+ if (order) {
21
+ const orderDetail: IOrderDetail = {
22
+ ...order,
23
+ href: `${knownRoutes.reserved_area_order_detail}?orderId=${order.id}`,
24
+ };
25
+ return orderDetail;
26
+ }
27
+ return order;
28
+ }
29
+
@@ -0,0 +1,31 @@
1
+ import { IEquatable, ValueOf } from '@websolutespa/bom-mixer-core';
2
+ import { ICheckout } from '../checkout/checkout';
3
+
4
+ export const IOrderStatus = {
5
+ Pending: 'pending', // Customer started the checkout process but did not complete it. Incomplete orders are assigned a "Pending" status and can be found under the More tab in the View Orders screen.
6
+ AwaitingPayment: 'awaitingPayment', // Customer has completed the checkout process, but payment has yet to be confirmed. Authorize only transactions that are not yet captured have this status.
7
+ AwaitingFulfillment: 'awaitingFulfillment', // Customer has completed the checkout process and payment has been confirmed.
8
+ AwaitingShipment: 'awaitingShipment', // Order has been pulled and packaged and is awaiting collection from a shipping provider.
9
+ AwaitingPickup: 'awaitingPickup', // Order has been packaged and is awaiting customer pickup from a seller-specified location.
10
+ PartiallyShipped: 'partiallyShipped', // Only some items in the order have been shipped.
11
+ Completed: 'completed', // Order has been shipped/picked up, and receipt is confirmed; client has paid for their digital product, and their file(s) are available for download.
12
+ Shipped: 'shipped', // Order has been shipped, but receipt has not been confirmed; seller has used the Ship Items action. A listing of all orders with a "Shipped" status can be found under the More tab of the View Orders screen.
13
+ Cancelled: 'cancelled', // Seller has cancelled an order, due to a stock inconsistency or other reasons. Stock levels will automatically update depending on your Inventory Settings. Cancelling an order will not refund the order. This status is triggered automatically when an order using an authorize-only payment gateway is voided in the control panel before capturing payment.
14
+ Declined: 'declined', // Seller has marked the order as declined.
15
+ Refunded: 'refunded', // Seller has used the Refund action to refund the whole order. A listing of all orders with a "Refunded" status can be found under the More tab of the View Orders screen.
16
+ Disputed: 'disputed', // Customer has initiated a dispute resolution process for the PayPal transaction that paid for the order or the seller has marked the order as a fraudulent order.
17
+ ManualVerificationRequired: 'manualVerificationRequired', // Order on hold while some aspect, such as tax-exempt documentation, is manually confirmed. Orders with this status must be updated manually. Capturing funds or other order actions will not automatically update the status of an order marked Manual Verification Required.
18
+ PartiallyRefunded: 'partiallyRefunded', // Seller has partially refunded the order.
19
+ };
20
+
21
+ export type IOrderStatusValue = ValueOf<typeof IOrderStatus>;
22
+
23
+ export type IOrder = ICheckout & {
24
+ id: IEquatable;
25
+ date: Date | string;
26
+ status: IOrderStatusValue;
27
+ };
28
+
29
+ export type IOrderDetail = IOrder & {
30
+ href: string;
31
+ };
@@ -0,0 +1,132 @@
1
+ import { IEquatable, QueryParams } from '@websolutespa/bom-mixer-core';
2
+ import { getStore } from '@websolutespa/bom-mixer-store';
3
+ import { ICategory } from '../category/category';
4
+ import { getSegments } from '../category/category.service';
5
+ import { resolveLabel } from '../label/label.service';
6
+ import { ILayout } from '../layout/layout';
7
+ import { getLayout } from '../layout/layout.service';
8
+ import { IRouteLink, SchemaType } from '../route/route';
9
+ import { getBreadcrumbFromSegments } from '../route/route.service';
10
+ import { IModelStore } from '../store/store';
11
+ import { IPage } from './page';
12
+
13
+ export async function findPage<T extends IPage>(schema: string, params?: QueryParams): Promise<T | undefined> {
14
+ const store = await getStore<IModelStore>();
15
+ const collection = store[schema];
16
+ if (!collection) {
17
+ throw `PageService.findPage: Collection not found [${schema}]`;
18
+ }
19
+ const page = await collection.findOne(params) as T;
20
+ if (page) {
21
+ return page;
22
+ } else {
23
+ console.log('PageService.getPage.notfound', schema, params);
24
+ return;
25
+ }
26
+ }
27
+
28
+ export async function getPage<T extends IPage>(schema: string, id: IEquatable, market?: string, locale?: string): Promise<T | undefined> {
29
+ const store = await getStore<IModelStore>();
30
+ const page = await findPage(schema, {
31
+ where: {
32
+ id: {
33
+ equals: id,
34
+ },
35
+ }, market, locale
36
+ }) as T;
37
+ // console.log(page, market, locale);
38
+ if (page) {
39
+ const routes = await store.route.findMany({
40
+ where: {
41
+ page: {
42
+ equals: id,
43
+ },
44
+ schema: {
45
+ equals: schema,
46
+ },
47
+ }
48
+ });
49
+ const currentRoute = routes.find((x: any) => x.market === market && x.locale === locale);
50
+ if (!currentRoute) {
51
+ throw ('No route found for page ' + schema + ':' + id + ' in market ' + market + ' and locale ' + locale);
52
+ }
53
+ const alternates = routes.filter((x: any) => x.market !== market || x.locale !== locale);
54
+ const segments: ICategory[] = await getSegments(page);
55
+ const breadcrumb: IRouteLink[] = await getBreadcrumbFromSegments(segments, market, locale);
56
+ const parentRoute: IRouteLink | undefined = breadcrumb.length > 1 ? breadcrumb[breadcrumb.length - 2] : undefined;
57
+ return {
58
+ ...page,
59
+ href: currentRoute.id, // !!! route?
60
+ alternates,
61
+ breadcrumb,
62
+ parentRoute,
63
+ } as T;
64
+ } else {
65
+ console.log('PageService.getPage.notfound', schema, id, locale);
66
+ return;
67
+ }
68
+ }
69
+
70
+ export async function getPageCategory<T extends IPage>(schema: string, page?: IPage, market?: string, locale?: string): Promise<T | undefined> {
71
+ if (!page) {
72
+ return;
73
+ }
74
+ const store = await getStore<IModelStore>();
75
+ const category = await findPage(schema, {
76
+ where: {
77
+ category: {
78
+ equals: typeof page.category === 'object' ? page.category.id : page.category,
79
+ }
80
+ }, market, locale
81
+ }) as T;
82
+ // console.log(page, market, locale);
83
+ if (category) {
84
+ const routes = await store.route.findMany({
85
+ where: {
86
+ schema: {
87
+ equals: schema,
88
+ },
89
+ page: {
90
+ equals: category.id,
91
+ },
92
+ }
93
+ });
94
+ const currentRoute = routes.find((x: any) => x.market === market && x.locale === locale);
95
+ if (!currentRoute) {
96
+ throw ('No route found for page ' + schema + ':' + category.id + ' in market ' + market + ' and locale ' + locale);
97
+ }
98
+ return {
99
+ ...category,
100
+ href: currentRoute.id,
101
+ } as T;
102
+ } else {
103
+ console.log('PageService.getPageCategory.notfound', schema, locale);
104
+ return;
105
+ }
106
+ }
107
+
108
+ export async function getErrorPageLayout(): Promise<{ layout: ILayout, page: IPage }> {
109
+ const defaultMarket = 'ww';
110
+ const defaultLocale = 'en';
111
+ const layout = await getLayout(defaultMarket, defaultLocale);
112
+ const title = resolveLabel(layout.labels, 'notfound.title');
113
+ const abstract = resolveLabel(layout.labels, 'notfound.abstract');
114
+ const page = {
115
+ id: 'notfound',
116
+ schema: 'notfound' as SchemaType,
117
+ href: '',
118
+ alternates: [],
119
+ breadcrumb: [],
120
+ title,
121
+ abstract,
122
+ category: 'homepage',
123
+ meta: {
124
+ title,
125
+ description: abstract,
126
+ keywords: '',
127
+ robots: 'all',
128
+ },
129
+ };
130
+ return { layout, page };
131
+ }
132
+
@@ -0,0 +1,53 @@
1
+ import { IEntity } from '@websolutespa/bom-mixer-core';
2
+ import { ICategory } from '../category/category';
3
+ import { ILayout } from '../layout/layout';
4
+ import { IMedia } from '../media/media';
5
+ import { IRoute, IRouteLink, IRouteParams } from '../route/route';
6
+
7
+ export type IMeta = {
8
+ title?: string;
9
+ description?: string;
10
+ keywords?: string;
11
+ robots?: string;
12
+ };
13
+
14
+ export type IImage = {
15
+ url: string;
16
+ type?: string;
17
+ alt?: string;
18
+ title?: string;
19
+ caption?: string;
20
+ width?: number;
21
+ height?: number;
22
+ };
23
+
24
+ export type IPage = IEntity & {
25
+ category: string | number | ICategory;
26
+ slug?: string;
27
+ href: string;
28
+ alternates: IRoute[];
29
+ breadcrumb: IRouteLink[];
30
+ parentRoute?: IRouteLink;
31
+ title?: string;
32
+ abstract?: string;
33
+ description?: string;
34
+ content?: string;
35
+ createdAt?: Date;
36
+ updatedAt?: Date;
37
+ meta?: IMeta;
38
+ media?: IMedia;
39
+ [key: string]: any;
40
+ };
41
+
42
+ export type PageProps<T extends IPage = IPage> = {
43
+ layout: ILayout;
44
+ page: T;
45
+ params: IRouteParams;
46
+ locales?: string[];
47
+ locale?: string;
48
+ defaultLocale?: string;
49
+ };
50
+
51
+ /*
52
+ export type IPageLayout = IPage & ILayout & { }
53
+ */
@@ -0,0 +1,9 @@
1
+ import { INamedEntity } from '@websolutespa/bom-mixer-core';
2
+ import { getStore } from '@websolutespa/bom-mixer-store';
3
+ import { IModelStore } from '../store/store';
4
+
5
+ export async function getProvinces(locale?: string): Promise<INamedEntity[]> {
6
+ const store = await getStore<IModelStore>();
7
+ const items = await store.i18n_province.findMany({ locale });
8
+ return items;
9
+ }
@@ -0,0 +1,9 @@
1
+ import { INamedEntity } from '@websolutespa/bom-mixer-core';
2
+ import { getStore } from '@websolutespa/bom-mixer-store';
3
+ import { IModelStore } from '../store/store';
4
+
5
+ export async function getRegions(locale?: string): Promise<INamedEntity[]> {
6
+ const store = await getStore<IModelStore>();
7
+ const items = await store.i18n_region.findMany({ locale });
8
+ return items;
9
+ }
@@ -0,0 +1,30 @@
1
+ import { apiPost } from '@websolutespa/bom-mixer-core';
2
+ import { NextFetchEvent, NextRequest, NextResponse } from 'next/server';
3
+ import { IRoute } from './route';
4
+ import { resolveRoute } from './route.service';
5
+
6
+ export async function routeInterceptor(request: NextRequest, next: NextFetchEvent) {
7
+ let url = request.nextUrl;
8
+ let route: IRoute;
9
+ // console.log('routeInterceptor.url', url.pathname);
10
+ try {
11
+ route = await apiPost('/route', { pathname: url.pathname });
12
+ // console.log('route', route);
13
+ if (!route) {
14
+ console.log('routeInterceptor.route.notfound', url.pathname);
15
+ return;
16
+ }
17
+ } catch (error: any) {
18
+ console.log('routeInterceptor.error', url.pathname, error, error.url, error.status, error.statusText);
19
+ return;
20
+ }
21
+ // console.log('routeInterceptor.route.found', url.pathname, '->', route);
22
+ url = request.nextUrl.clone();
23
+ const resolvedPathname = resolveRoute(route);
24
+ // console.log('resolvedPathname', resolvedPathname);
25
+ url.pathname = resolvedPathname;
26
+ // console.log('routeInterceptor.route', route.schema, route.page, route.market, route.locale);
27
+ const response = NextResponse.rewrite(url);
28
+ // const response = NextResponse.redirect(url);
29
+ return response;
30
+ }