washday-sdk 1.6.87 → 1.6.88

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/api/index.js CHANGED
@@ -49,6 +49,7 @@ import * as integrationsEndpoints from './integrations';
49
49
  import * as updatesEndpoints from './updates';
50
50
  import * as intercomEndpoints from './intercom';
51
51
  import * as googleMapsEndpoints from './googleMaps';
52
+ import * as websiteBuilderEndpoints from './websiteBuilder';
52
53
  function bindMethods(instance, methods) {
53
54
  const boundMethods = {};
54
55
  for (const key in methods) {
@@ -129,6 +130,11 @@ const WashdayClient = function WashdayClient(apiToken, env = 'PROD', clientId, c
129
130
  getPosAppConfig: publicsEndpoints.getModule.getPosAppConfig,
130
131
  getHubAppConfig: publicsEndpoints.getModule.getHubAppConfig,
131
132
  });
133
+ this.websiteBuilder = bindMethods(this, {
134
+ getSettings: websiteBuilderEndpoints.getModule.getSettings,
135
+ updateSettings: websiteBuilderEndpoints.putModule.updateSettings,
136
+ getPublicBootstrap: websiteBuilderEndpoints.getModule.getPublicBootstrap,
137
+ });
132
138
  this.auth = bindMethods(this, {
133
139
  customerLoginToken: authEndpoints.postModule.customerLoginToken,
134
140
  googleLogin: authEndpoints.postModule.googleLogin,
@@ -0,0 +1,6 @@
1
+ import { WashdayClientInstance } from "../../interfaces/Api";
2
+ import { PublicWebsiteBootstrapResponse, WebsiteBuilderSettings } from "../../interfaces/WebsiteBuilder";
3
+ export declare const getSettings: (this: WashdayClientInstance) => Promise<WebsiteBuilderSettings>;
4
+ export declare const getPublicBootstrap: (this: WashdayClientInstance, params?: {
5
+ host?: string;
6
+ }) => Promise<PublicWebsiteBootstrapResponse>;
@@ -0,0 +1,41 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { unwrapWebsiteBuilderApiData } from "./response";
11
+ const GET_SET_WEBSITE_BUILDER = "api/website-builder/settings";
12
+ const GET_PUBLIC_WEBSITE_BUILDER_BOOTSTRAP = "/api/public/website-builder/bootstrap";
13
+ export const getSettings = function () {
14
+ return __awaiter(this, void 0, void 0, function* () {
15
+ try {
16
+ const config = {
17
+ headers: { Authorization: `Bearer ${this.apiToken}` },
18
+ };
19
+ const response = yield this.axiosInstance.get(GET_SET_WEBSITE_BUILDER, config);
20
+ return unwrapWebsiteBuilderApiData(response);
21
+ }
22
+ catch (error) {
23
+ console.error("Error fetching Website Builder settings:", error);
24
+ throw error;
25
+ }
26
+ });
27
+ };
28
+ export const getPublicBootstrap = function () {
29
+ return __awaiter(this, arguments, void 0, function* (params = {}) {
30
+ try {
31
+ const response = yield this.axiosInstance.get(GET_PUBLIC_WEBSITE_BUILDER_BOOTSTRAP, {
32
+ params,
33
+ });
34
+ return unwrapWebsiteBuilderApiData(response);
35
+ }
36
+ catch (error) {
37
+ console.error("Error fetching public Website Builder bootstrap:", error);
38
+ throw error;
39
+ }
40
+ });
41
+ };
@@ -0,0 +1,2 @@
1
+ export * as getModule from "./get";
2
+ export * as putModule from "./put";
@@ -0,0 +1,2 @@
1
+ export * as getModule from "./get";
2
+ export * as putModule from "./put";
@@ -0,0 +1,3 @@
1
+ import { WashdayClientInstance } from "../../interfaces/Api";
2
+ import { UpdateWebsiteBuilderSettingsPayload, WebsiteBuilderSettings } from "../../interfaces/WebsiteBuilder";
3
+ export declare const updateSettings: (this: WashdayClientInstance, payload: UpdateWebsiteBuilderSettingsPayload) => Promise<WebsiteBuilderSettings>;
@@ -0,0 +1,26 @@
1
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
2
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
3
+ return new (P || (P = Promise))(function (resolve, reject) {
4
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
5
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
6
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
7
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
8
+ });
9
+ };
10
+ import { unwrapWebsiteBuilderApiData } from "./response";
11
+ const GET_SET_WEBSITE_BUILDER = "api/website-builder/settings";
12
+ export const updateSettings = function (payload) {
13
+ return __awaiter(this, void 0, void 0, function* () {
14
+ try {
15
+ const config = {
16
+ headers: { Authorization: `Bearer ${this.apiToken}` },
17
+ };
18
+ const response = yield this.axiosInstance.put(GET_SET_WEBSITE_BUILDER, payload, config);
19
+ return unwrapWebsiteBuilderApiData(response);
20
+ }
21
+ catch (error) {
22
+ console.error("Error updating Website Builder settings:", error);
23
+ throw error;
24
+ }
25
+ });
26
+ };
@@ -0,0 +1 @@
1
+ export declare function unwrapWebsiteBuilderApiData<T>(response: any): T;
@@ -0,0 +1,6 @@
1
+ export function unwrapWebsiteBuilderApiData(response) {
2
+ if (!(response === null || response === void 0 ? void 0 : response.data) || !Object.prototype.hasOwnProperty.call(response.data, "data")) {
3
+ throw new Error("Website Builder API response missing data");
4
+ }
5
+ return response.data.data;
6
+ }
package/dist/index.d.ts CHANGED
@@ -11,6 +11,7 @@ export * from './interfaces/GoogleMaps';
11
11
  export * from './interfaces/Attendance';
12
12
  export * from './interfaces/Order';
13
13
  export * from './interfaces/Store';
14
+ export * from './interfaces/WebsiteBuilder';
14
15
  export * from './interfaces/Permission';
15
16
  export * from './interfaces/Route';
16
17
  export * from './enum';
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ export * from './interfaces/GoogleMaps';
11
11
  export * from './interfaces/Attendance';
12
12
  export * from './interfaces/Order';
13
13
  export * from './interfaces/Store';
14
+ export * from './interfaces/WebsiteBuilder';
14
15
  export * from './interfaces/Permission';
15
16
  export * from './interfaces/Route';
16
17
  export * from './enum';
@@ -47,6 +47,7 @@ import * as integrationsEndpoints from '../api/integrations';
47
47
  import * as updatesEndpoints from '../api/updates';
48
48
  import * as intercomEndpoints from '../api/intercom';
49
49
  import * as googleMapsEndpoints from '../api/googleMaps';
50
+ import * as websiteBuilderEndpoints from '../api/websiteBuilder';
50
51
  import { validateUserPin } from "../api/users/post";
51
52
  import { AxiosInstance } from "axios";
52
53
  export interface WashdayClientInstance {
@@ -135,6 +136,11 @@ export interface WashdayClientInstance {
135
136
  getPosAppConfig: typeof publicsEndpoints.getModule.getPosAppConfig;
136
137
  getHubAppConfig: typeof publicsEndpoints.getModule.getHubAppConfig;
137
138
  };
139
+ websiteBuilder: {
140
+ getSettings: typeof websiteBuilderEndpoints.getModule.getSettings;
141
+ updateSettings: typeof websiteBuilderEndpoints.putModule.updateSettings;
142
+ getPublicBootstrap: typeof websiteBuilderEndpoints.getModule.getPublicBootstrap;
143
+ };
138
144
  orders: {
139
145
  getList: typeof ordersEndpoints.getModule.getList;
140
146
  getOrdersHeaderSummary: typeof ordersEndpoints.getModule.getOrdersHeaderSummary;
@@ -0,0 +1,72 @@
1
+ export type LandingSectionType = "hero" | "how_it_works" | "services" | "store_info" | "reviews" | "final_cta";
2
+ export type ButtonRadiusPreset = "square" | "sm" | "md" | "lg" | "pill";
3
+ export type WebsiteBuilderTheme = {
4
+ primaryColor: string;
5
+ secondaryColor: string;
6
+ buttonBackgroundColor: string;
7
+ buttonRadiusPreset: ButtonRadiusPreset;
8
+ };
9
+ export type WebsiteBuilderSocialLinks = {
10
+ facebook?: string;
11
+ instagram?: string;
12
+ tiktok?: string;
13
+ whatsapp?: string;
14
+ x?: string;
15
+ linkedin?: string;
16
+ youtube?: string;
17
+ };
18
+ export type WebsiteBuilderPages = {
19
+ landing: boolean;
20
+ contact: boolean;
21
+ pricing: boolean;
22
+ privacy: boolean;
23
+ terms: boolean;
24
+ };
25
+ export type WebsiteBuilderLegal = {
26
+ privacyMarkdown?: string;
27
+ termsMarkdown?: string;
28
+ };
29
+ export type LandingSectionConfig = {
30
+ id: string;
31
+ type: LandingSectionType;
32
+ variant: string;
33
+ enabled: boolean;
34
+ order: number;
35
+ config: Record<string, unknown>;
36
+ };
37
+ export type WebsiteBuilderSettings = {
38
+ websiteEnabled: boolean;
39
+ maintenanceModeEnabled: boolean;
40
+ slug?: string;
41
+ websiteName?: string;
42
+ theme: WebsiteBuilderTheme;
43
+ socialLinks: WebsiteBuilderSocialLinks;
44
+ pages: WebsiteBuilderPages;
45
+ legal: WebsiteBuilderLegal;
46
+ landingSections: LandingSectionConfig[];
47
+ };
48
+ export type UpdateWebsiteBuilderSettingsPayload = Partial<Omit<WebsiteBuilderSettings, "theme" | "socialLinks" | "pages" | "legal" | "landingSections">> & {
49
+ theme?: Partial<WebsiteBuilderTheme>;
50
+ socialLinks?: Partial<Record<keyof WebsiteBuilderSocialLinks, string | null>>;
51
+ pages?: Partial<WebsiteBuilderPages>;
52
+ legal?: Partial<Record<keyof WebsiteBuilderLegal, string | null>>;
53
+ landingSections?: LandingSectionConfig[];
54
+ };
55
+ export type PublicWebsiteBootstrapResponse = {
56
+ company: {
57
+ name: string;
58
+ logoUrl?: string;
59
+ };
60
+ website: WebsiteBuilderSettings & {
61
+ mode: "live" | "maintenance";
62
+ };
63
+ stores: Array<{
64
+ id: string;
65
+ name: string;
66
+ phone?: string;
67
+ streetAddress?: string;
68
+ city?: string;
69
+ state?: string;
70
+ schedule?: unknown;
71
+ }>;
72
+ };
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "washday-sdk",
3
- "version": "1.6.87",
3
+ "version": "1.6.88",
4
4
  "description": "Washday utilities functions and API",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
package/src/api/index.ts CHANGED
@@ -51,6 +51,7 @@ import * as integrationsEndpoints from './integrations';
51
51
  import * as updatesEndpoints from './updates';
52
52
  import * as intercomEndpoints from './intercom';
53
53
  import * as googleMapsEndpoints from './googleMaps';
54
+ import * as websiteBuilderEndpoints from './websiteBuilder';
54
55
 
55
56
  type WashdayClientConstructor = {
56
57
  new(apiToken: string | null, env?: string, clientId?: string, clientSecret?: string): WashdayClientInstance
@@ -136,6 +137,11 @@ const WashdayClient: WashdayClientConstructor = function WashdayClient(this: Was
136
137
  getPosAppConfig: publicsEndpoints.getModule.getPosAppConfig,
137
138
  getHubAppConfig: publicsEndpoints.getModule.getHubAppConfig,
138
139
  });
140
+ this.websiteBuilder = bindMethods(this, {
141
+ getSettings: websiteBuilderEndpoints.getModule.getSettings,
142
+ updateSettings: websiteBuilderEndpoints.putModule.updateSettings,
143
+ getPublicBootstrap: websiteBuilderEndpoints.getModule.getPublicBootstrap,
144
+ });
139
145
  this.auth = bindMethods(this, {
140
146
  customerLoginToken: authEndpoints.postModule.customerLoginToken,
141
147
  googleLogin: authEndpoints.postModule.googleLogin,
@@ -0,0 +1,34 @@
1
+ import { WashdayClientInstance } from "../../interfaces/Api";
2
+ import { PublicWebsiteBootstrapResponse, WebsiteBuilderSettings } from "../../interfaces/WebsiteBuilder";
3
+ import { unwrapWebsiteBuilderApiData } from "./response";
4
+
5
+ const GET_SET_WEBSITE_BUILDER = "api/website-builder/settings";
6
+ const GET_PUBLIC_WEBSITE_BUILDER_BOOTSTRAP = "/api/public/website-builder/bootstrap";
7
+
8
+ export const getSettings = async function (this: WashdayClientInstance): Promise<WebsiteBuilderSettings> {
9
+ try {
10
+ const config = {
11
+ headers: { Authorization: `Bearer ${this.apiToken}` },
12
+ };
13
+ const response = await this.axiosInstance.get(GET_SET_WEBSITE_BUILDER, config);
14
+ return unwrapWebsiteBuilderApiData<WebsiteBuilderSettings>(response);
15
+ } catch (error) {
16
+ console.error("Error fetching Website Builder settings:", error);
17
+ throw error;
18
+ }
19
+ };
20
+
21
+ export const getPublicBootstrap = async function (
22
+ this: WashdayClientInstance,
23
+ params: { host?: string } = {},
24
+ ): Promise<PublicWebsiteBootstrapResponse> {
25
+ try {
26
+ const response = await this.axiosInstance.get(GET_PUBLIC_WEBSITE_BUILDER_BOOTSTRAP, {
27
+ params,
28
+ });
29
+ return unwrapWebsiteBuilderApiData<PublicWebsiteBootstrapResponse>(response);
30
+ } catch (error) {
31
+ console.error("Error fetching public Website Builder bootstrap:", error);
32
+ throw error;
33
+ }
34
+ };
@@ -0,0 +1,2 @@
1
+ export * as getModule from "./get";
2
+ export * as putModule from "./put";
@@ -0,0 +1,24 @@
1
+ import { WashdayClientInstance } from "../../interfaces/Api";
2
+ import {
3
+ UpdateWebsiteBuilderSettingsPayload,
4
+ WebsiteBuilderSettings,
5
+ } from "../../interfaces/WebsiteBuilder";
6
+ import { unwrapWebsiteBuilderApiData } from "./response";
7
+
8
+ const GET_SET_WEBSITE_BUILDER = "api/website-builder/settings";
9
+
10
+ export const updateSettings = async function (
11
+ this: WashdayClientInstance,
12
+ payload: UpdateWebsiteBuilderSettingsPayload,
13
+ ): Promise<WebsiteBuilderSettings> {
14
+ try {
15
+ const config = {
16
+ headers: { Authorization: `Bearer ${this.apiToken}` },
17
+ };
18
+ const response = await this.axiosInstance.put(GET_SET_WEBSITE_BUILDER, payload, config);
19
+ return unwrapWebsiteBuilderApiData<WebsiteBuilderSettings>(response);
20
+ } catch (error) {
21
+ console.error("Error updating Website Builder settings:", error);
22
+ throw error;
23
+ }
24
+ };
@@ -0,0 +1,7 @@
1
+ export function unwrapWebsiteBuilderApiData<T>(response: any): T {
2
+ if (!response?.data || !Object.prototype.hasOwnProperty.call(response.data, "data")) {
3
+ throw new Error("Website Builder API response missing data");
4
+ }
5
+
6
+ return response.data.data as T;
7
+ }
package/src/index.ts CHANGED
@@ -11,6 +11,7 @@ export * from './interfaces/GoogleMaps';
11
11
  export * from './interfaces/Attendance';
12
12
  export * from './interfaces/Order';
13
13
  export * from './interfaces/Store';
14
+ export * from './interfaces/WebsiteBuilder';
14
15
  export * from './interfaces/Permission';
15
16
  export * from './interfaces/Route';
16
17
  export * from './enum';
@@ -47,6 +47,7 @@ import * as integrationsEndpoints from '../api/integrations';
47
47
  import * as updatesEndpoints from '../api/updates';
48
48
  import * as intercomEndpoints from '../api/intercom';
49
49
  import * as googleMapsEndpoints from '../api/googleMaps';
50
+ import * as websiteBuilderEndpoints from '../api/websiteBuilder';
50
51
  import { validateUserPin } from "../api/users/post";
51
52
  import { AxiosInstance } from "axios";
52
53
 
@@ -138,6 +139,11 @@ export interface WashdayClientInstance {
138
139
  getPosAppConfig: typeof publicsEndpoints.getModule.getPosAppConfig,
139
140
  getHubAppConfig: typeof publicsEndpoints.getModule.getHubAppConfig,
140
141
  },
142
+ websiteBuilder: {
143
+ getSettings: typeof websiteBuilderEndpoints.getModule.getSettings,
144
+ updateSettings: typeof websiteBuilderEndpoints.putModule.updateSettings,
145
+ getPublicBootstrap: typeof websiteBuilderEndpoints.getModule.getPublicBootstrap,
146
+ },
141
147
  orders: {
142
148
  getList: typeof ordersEndpoints.getModule.getList;
143
149
  getOrdersHeaderSummary: typeof ordersEndpoints.getModule.getOrdersHeaderSummary;
@@ -0,0 +1,89 @@
1
+ export type LandingSectionType =
2
+ | "hero"
3
+ | "how_it_works"
4
+ | "services"
5
+ | "store_info"
6
+ | "reviews"
7
+ | "final_cta";
8
+
9
+ export type ButtonRadiusPreset = "square" | "sm" | "md" | "lg" | "pill";
10
+
11
+ export type WebsiteBuilderTheme = {
12
+ primaryColor: string;
13
+ secondaryColor: string;
14
+ buttonBackgroundColor: string;
15
+ buttonRadiusPreset: ButtonRadiusPreset;
16
+ };
17
+
18
+ export type WebsiteBuilderSocialLinks = {
19
+ facebook?: string;
20
+ instagram?: string;
21
+ tiktok?: string;
22
+ whatsapp?: string;
23
+ x?: string;
24
+ linkedin?: string;
25
+ youtube?: string;
26
+ };
27
+
28
+ export type WebsiteBuilderPages = {
29
+ landing: boolean;
30
+ contact: boolean;
31
+ pricing: boolean;
32
+ privacy: boolean;
33
+ terms: boolean;
34
+ };
35
+
36
+ export type WebsiteBuilderLegal = {
37
+ privacyMarkdown?: string;
38
+ termsMarkdown?: string;
39
+ };
40
+
41
+ export type LandingSectionConfig = {
42
+ id: string;
43
+ type: LandingSectionType;
44
+ variant: string;
45
+ enabled: boolean;
46
+ order: number;
47
+ config: Record<string, unknown>;
48
+ };
49
+
50
+ export type WebsiteBuilderSettings = {
51
+ websiteEnabled: boolean;
52
+ maintenanceModeEnabled: boolean;
53
+ slug?: string;
54
+ websiteName?: string;
55
+ theme: WebsiteBuilderTheme;
56
+ socialLinks: WebsiteBuilderSocialLinks;
57
+ pages: WebsiteBuilderPages;
58
+ legal: WebsiteBuilderLegal;
59
+ landingSections: LandingSectionConfig[];
60
+ };
61
+
62
+ export type UpdateWebsiteBuilderSettingsPayload = Partial<
63
+ Omit<WebsiteBuilderSettings, "theme" | "socialLinks" | "pages" | "legal" | "landingSections">
64
+ > & {
65
+ theme?: Partial<WebsiteBuilderTheme>;
66
+ socialLinks?: Partial<Record<keyof WebsiteBuilderSocialLinks, string | null>>;
67
+ pages?: Partial<WebsiteBuilderPages>;
68
+ legal?: Partial<Record<keyof WebsiteBuilderLegal, string | null>>;
69
+ landingSections?: LandingSectionConfig[];
70
+ };
71
+
72
+ export type PublicWebsiteBootstrapResponse = {
73
+ company: {
74
+ name: string;
75
+ logoUrl?: string;
76
+ };
77
+ website: WebsiteBuilderSettings & {
78
+ mode: "live" | "maintenance";
79
+ };
80
+ stores: Array<{
81
+ id: string;
82
+ name: string;
83
+ phone?: string;
84
+ streetAddress?: string;
85
+ city?: string;
86
+ state?: string;
87
+ schedule?: unknown;
88
+ }>;
89
+ };
@@ -0,0 +1,162 @@
1
+ import WashdayClient from "../src/api";
2
+ import { getSettings, getPublicBootstrap } from "../src/api/websiteBuilder/get";
3
+ import { updateSettings } from "../src/api/websiteBuilder/put";
4
+ import type {
5
+ PublicWebsiteBootstrapResponse,
6
+ UpdateWebsiteBuilderSettingsPayload,
7
+ WebsiteBuilderSettings,
8
+ } from "../src/interfaces/WebsiteBuilder";
9
+
10
+ describe("websiteBuilder SDK namespace", () => {
11
+ it("calls the authenticated settings endpoint", async () => {
12
+ const settings = createWebsiteBuilderSettings();
13
+ const get = jest.fn().mockResolvedValue({ data: { data: settings } });
14
+ const client = {
15
+ apiToken: "token-1",
16
+ axiosInstance: { get },
17
+ } as any;
18
+
19
+ const result = await getSettings.call(client);
20
+
21
+ expect(get).toHaveBeenCalledWith("api/website-builder/settings", {
22
+ headers: { Authorization: "Bearer token-1" },
23
+ });
24
+ expect(result).toEqual(settings);
25
+ });
26
+
27
+ it("calls the authenticated settings update endpoint", async () => {
28
+ const settings = createWebsiteBuilderSettings({ slug: "clean-wash" });
29
+ const put = jest.fn().mockResolvedValue({ data: { data: settings } });
30
+ const client = {
31
+ apiToken: "token-2",
32
+ axiosInstance: { put },
33
+ } as any;
34
+ const payload: UpdateWebsiteBuilderSettingsPayload = {
35
+ slug: "clean-wash",
36
+ theme: {
37
+ primaryColor: "#111111",
38
+ },
39
+ };
40
+
41
+ const result = await updateSettings.call(client, payload);
42
+
43
+ expect(put).toHaveBeenCalledWith("api/website-builder/settings", payload, {
44
+ headers: { Authorization: "Bearer token-2" },
45
+ });
46
+ expect(result).toEqual(settings);
47
+ });
48
+
49
+ it("calls the unauthenticated public bootstrap endpoint", async () => {
50
+ const bootstrap = createPublicBootstrap();
51
+ const get = jest.fn().mockResolvedValue({ data: { data: bootstrap } });
52
+ const client = {
53
+ apiToken: "token-3",
54
+ axiosInstance: { get },
55
+ } as any;
56
+
57
+ const result = await getPublicBootstrap.call(client, { host: "clean-wash.washdaypos.com" });
58
+
59
+ expect(get).toHaveBeenCalledWith("/api/public/website-builder/bootstrap", {
60
+ params: { host: "clean-wash.washdaypos.com" },
61
+ });
62
+ expect(result).toEqual(bootstrap);
63
+ });
64
+
65
+ it("binds the websiteBuilder namespace on WashdayClient", async () => {
66
+ const settings = createWebsiteBuilderSettings();
67
+ const client = new (WashdayClient as any)("token-4", "DEV");
68
+ client.axiosInstance.get = jest.fn().mockResolvedValue({ data: { data: settings } });
69
+
70
+ const result = await client.websiteBuilder.getSettings();
71
+
72
+ expect(client.axiosInstance.get).toHaveBeenCalledWith("api/website-builder/settings", {
73
+ headers: { Authorization: "Bearer token-4" },
74
+ });
75
+ expect(result).toEqual(settings);
76
+ });
77
+
78
+ it("throws a useful error when the backend response is missing wrapped data", async () => {
79
+ const consoleErrorSpy = jest.spyOn(console, "error").mockImplementation(() => undefined);
80
+ const get = jest.fn().mockResolvedValue({ data: { errors: [] } });
81
+ const client = {
82
+ apiToken: "token-5",
83
+ axiosInstance: { get },
84
+ } as any;
85
+
86
+ try {
87
+ await expect(getSettings.call(client)).rejects.toThrow(
88
+ "Website Builder API response missing data",
89
+ );
90
+ } finally {
91
+ consoleErrorSpy.mockRestore();
92
+ }
93
+ });
94
+
95
+ it("exports Website Builder response types", () => {
96
+ const settings: WebsiteBuilderSettings = createWebsiteBuilderSettings();
97
+ const bootstrap: PublicWebsiteBootstrapResponse = {
98
+ company: {
99
+ name: "Clean Wash",
100
+ },
101
+ website: {
102
+ ...settings,
103
+ mode: "live",
104
+ },
105
+ stores: [],
106
+ };
107
+
108
+ expect(bootstrap.website.slug).toBe("clean-wash");
109
+ });
110
+ });
111
+
112
+ function createWebsiteBuilderSettings(
113
+ overrides: Partial<WebsiteBuilderSettings> = {},
114
+ ): WebsiteBuilderSettings {
115
+ return {
116
+ websiteEnabled: true,
117
+ maintenanceModeEnabled: false,
118
+ slug: "clean-wash",
119
+ websiteName: "Clean Wash",
120
+ theme: {
121
+ primaryColor: "#0047AD",
122
+ secondaryColor: "#E6F0FF",
123
+ buttonBackgroundColor: "#0047AD",
124
+ buttonRadiusPreset: "md",
125
+ },
126
+ socialLinks: {},
127
+ pages: {
128
+ landing: true,
129
+ contact: true,
130
+ pricing: false,
131
+ privacy: false,
132
+ terms: false,
133
+ },
134
+ legal: {},
135
+ landingSections: [
136
+ {
137
+ id: "hero",
138
+ type: "hero",
139
+ variant: "centered",
140
+ enabled: true,
141
+ order: 0,
142
+ config: {},
143
+ },
144
+ ],
145
+ ...overrides,
146
+ };
147
+ }
148
+
149
+ function createPublicBootstrap(): PublicWebsiteBootstrapResponse {
150
+ const settings = createWebsiteBuilderSettings();
151
+
152
+ return {
153
+ company: {
154
+ name: "Clean Wash",
155
+ },
156
+ website: {
157
+ ...settings,
158
+ mode: "live",
159
+ },
160
+ stores: [],
161
+ };
162
+ }