@ikas/storefront-next 4.0.0-alpha.10
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/package.json +59 -0
- package/src/api/getComponentDirs.ts +39 -0
- package/src/api/getTheme.ts +22 -0
- package/src/api/index.ts +14 -0
- package/src/api/middleware.ts +24 -0
- package/src/api/updateTheme.ts +33 -0
- package/src/api/uploadTheme.ts +307 -0
- package/src/index.ts +4 -0
- package/src/pages/404.tsx +18 -0
- package/src/pages/[slug]/index.tsx +18 -0
- package/src/pages/account/addresses.tsx +10 -0
- package/src/pages/account/favorite-products.tsx +10 -0
- package/src/pages/account/forgot-password.tsx +10 -0
- package/src/pages/account/index.tsx +10 -0
- package/src/pages/account/login.tsx +10 -0
- package/src/pages/account/orders/[id].tsx +10 -0
- package/src/pages/account/orders/index.tsx +10 -0
- package/src/pages/account/raffles.tsx +10 -0
- package/src/pages/account/recover-password.tsx +10 -0
- package/src/pages/account/register.tsx +10 -0
- package/src/pages/blog/[slug].tsx +17 -0
- package/src/pages/blog/index.tsx +10 -0
- package/src/pages/cart.tsx +10 -0
- package/src/pages/checkout.tsx +10 -0
- package/src/pages/editor.tsx +11 -0
- package/src/pages/home.tsx +10 -0
- package/src/pages/index.ts +22 -0
- package/src/pages/pages/[slug].tsx +72 -0
- package/src/pages/raffle/[slug].tsx +17 -0
- package/src/pages/raffle/index.tsx +10 -0
- package/src/pages/search.tsx +10 -0
- package/src/provider/page-data-next.ts +618 -0
- package/src/utils/fs.ts +93 -0
- package/src/utils/google-fonts.ts +52 -0
- package/src/utils/i18n.ts +80 -0
|
@@ -0,0 +1,618 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import getConfig from "next/config.js";
|
|
3
|
+
import { GetServerSidePropsContext, GetStaticPropsContext } from "next";
|
|
4
|
+
import { ParsedUrlQuery } from "querystring";
|
|
5
|
+
import {
|
|
6
|
+
IkasCustomerReviewSettings,
|
|
7
|
+
IkasMerchantSettings,
|
|
8
|
+
IkasProductBackInStockSettings,
|
|
9
|
+
IkasSalesChannel,
|
|
10
|
+
IkasStorefront,
|
|
11
|
+
IkasStorefrontRouting,
|
|
12
|
+
IkasStorefrontThemeLocalization,
|
|
13
|
+
IkasThemeJson,
|
|
14
|
+
IkasThemeJsonFavicon,
|
|
15
|
+
IkasThemeJsonPageType,
|
|
16
|
+
IkasThemeJsonSettings,
|
|
17
|
+
IkasThemeJsonStockPreference,
|
|
18
|
+
} from "@ikas/storefront-models";
|
|
19
|
+
import { IkasPageDataProvider } from "@ikas/storefront-providers";
|
|
20
|
+
import { IkasStorefrontConfig } from "@ikas/storefront-config";
|
|
21
|
+
import {
|
|
22
|
+
listCheckoutSettings,
|
|
23
|
+
listMerchantSettings,
|
|
24
|
+
IkasAPIClientConfig,
|
|
25
|
+
getStorefrontSettings,
|
|
26
|
+
IkasStorefrontSettings,
|
|
27
|
+
} from "@ikas/storefront-api";
|
|
28
|
+
import { getGoogleFontHref } from "../utils/google-fonts";
|
|
29
|
+
import { I18NFileReader } from "../utils/i18n";
|
|
30
|
+
import { createFile, deleteDirContent } from "../utils/fs";
|
|
31
|
+
|
|
32
|
+
export class IkasNextPageDataProvider {
|
|
33
|
+
static startTime = Date.now();
|
|
34
|
+
|
|
35
|
+
static readLocalTheme(): Promise<IkasThemeJson> {
|
|
36
|
+
return new Promise((resolve, reject) => {
|
|
37
|
+
const themeJSONPath = "./src/theme.json";
|
|
38
|
+
|
|
39
|
+
fs.readFile(
|
|
40
|
+
themeJSONPath,
|
|
41
|
+
{
|
|
42
|
+
flag: "a+",
|
|
43
|
+
},
|
|
44
|
+
function (err, file) {
|
|
45
|
+
if (err) {
|
|
46
|
+
return reject(err);
|
|
47
|
+
}
|
|
48
|
+
const result = file.length ? JSON.parse(file.toString()) : {};
|
|
49
|
+
resolve(result);
|
|
50
|
+
}
|
|
51
|
+
);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
static readSettingsFile(): Promise<SettingsData | null> {
|
|
56
|
+
return new Promise((resolve) => {
|
|
57
|
+
const { serverRuntimeConfig } = getConfig();
|
|
58
|
+
const settingsPath = serverRuntimeConfig.SETTINGS;
|
|
59
|
+
|
|
60
|
+
fs.readFile(
|
|
61
|
+
settingsPath,
|
|
62
|
+
{
|
|
63
|
+
flag: "a+",
|
|
64
|
+
},
|
|
65
|
+
function (err, file) {
|
|
66
|
+
if (err) {
|
|
67
|
+
console.error("SETTINGS FILE READ ERROR!!!");
|
|
68
|
+
console.error(err);
|
|
69
|
+
return resolve(null);
|
|
70
|
+
}
|
|
71
|
+
const result = file.length ? JSON.parse(file.toString()) : {};
|
|
72
|
+
resolve(result);
|
|
73
|
+
}
|
|
74
|
+
);
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
static async cacheLocalSettingsFile(settings: IkasStorefrontSettings) {
|
|
79
|
+
const cacheFileFolderPath = ".ikas";
|
|
80
|
+
await deleteDirContent(cacheFileFolderPath);
|
|
81
|
+
|
|
82
|
+
const cacheFileName = `settings-${this.startTime}.json`;
|
|
83
|
+
await createFile(
|
|
84
|
+
cacheFileFolderPath,
|
|
85
|
+
cacheFileName,
|
|
86
|
+
JSON.stringify(settings, null, 2)
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
static readLocalSettingsFile() {
|
|
91
|
+
try {
|
|
92
|
+
const fileContent = fs.readFileSync(
|
|
93
|
+
`.ikas/settings-${this.startTime}.json`
|
|
94
|
+
);
|
|
95
|
+
|
|
96
|
+
if (fileContent && fileContent.length)
|
|
97
|
+
return JSON.parse(fileContent.toString());
|
|
98
|
+
} catch {}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
static setAPIClientConfig() {
|
|
102
|
+
IkasAPIClientConfig.URL = IkasStorefrontConfig.getApiUrl() || "";
|
|
103
|
+
IkasAPIClientConfig.HEADERS = {
|
|
104
|
+
"x-api-key": IkasStorefrontConfig.getApiKey() || "",
|
|
105
|
+
"x-sfid": IkasStorefrontConfig.getStorefrontId() || "",
|
|
106
|
+
"x-sfrid": IkasStorefrontConfig.getStorefrontRoutingId() || "",
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
if (IkasStorefrontConfig.getCustomerToken()) {
|
|
110
|
+
IkasAPIClientConfig.TOKEN = IkasStorefrontConfig.getCustomerToken() || "";
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
static async getLocalSettings(locale: string): Promise<SettingsData | null> {
|
|
115
|
+
let settings: IkasStorefrontSettings =
|
|
116
|
+
await IkasNextPageDataProvider.readLocalSettingsFile();
|
|
117
|
+
|
|
118
|
+
if (!settings) {
|
|
119
|
+
const settingsResponse = await getStorefrontSettings();
|
|
120
|
+
|
|
121
|
+
if (!settingsResponse.isSuccess || !settingsResponse.data) {
|
|
122
|
+
console.error("Storefront settings fetch failed!");
|
|
123
|
+
console.error(settingsResponse);
|
|
124
|
+
return null;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
settings = settingsResponse.data;
|
|
128
|
+
await this.cacheLocalSettingsFile(settings);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
const storefront = settings.storefront;
|
|
132
|
+
const salesChannel = settings.salesChannel;
|
|
133
|
+
const storefrontJSScripts = []; // Not using the settings one on purpose, no need to run scripts on localhost
|
|
134
|
+
const productBackInStockSettings: IkasProductBackInStockSettings | null =
|
|
135
|
+
settings.productBackInStockSettings
|
|
136
|
+
? {
|
|
137
|
+
customerLoginRequired:
|
|
138
|
+
settings.productBackInStockSettings.customerLoginRequired,
|
|
139
|
+
}
|
|
140
|
+
: null;
|
|
141
|
+
const customerReviewSettings: IkasCustomerReviewSettings | null =
|
|
142
|
+
settings.customerReviewSettings
|
|
143
|
+
? {
|
|
144
|
+
customerLoginRequired:
|
|
145
|
+
settings.customerReviewSettings.customerLoginRequired || false,
|
|
146
|
+
customerPurchaseRequired:
|
|
147
|
+
settings.customerReviewSettings.customerPurchaseRequired || false,
|
|
148
|
+
}
|
|
149
|
+
: null;
|
|
150
|
+
|
|
151
|
+
const localTheme = await IkasNextPageDataProvider.readLocalTheme();
|
|
152
|
+
const colorScript = IkasNextPageDataProvider.createColorScript(
|
|
153
|
+
localTheme.settings
|
|
154
|
+
);
|
|
155
|
+
const fontScript = IkasNextPageDataProvider.createFontScript(
|
|
156
|
+
localTheme.settings
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
if (colorScript) storefrontJSScripts.push(colorScript);
|
|
160
|
+
if (fontScript) storefrontJSScripts.push(fontScript);
|
|
161
|
+
|
|
162
|
+
return {
|
|
163
|
+
storefront: storefront,
|
|
164
|
+
themeLocalization: {
|
|
165
|
+
id: "",
|
|
166
|
+
locale: "en",
|
|
167
|
+
privacyPolicy: null,
|
|
168
|
+
returnPolicy: null,
|
|
169
|
+
storefrontId: storefront.id,
|
|
170
|
+
storefrontThemeId: "",
|
|
171
|
+
termsOfService: null,
|
|
172
|
+
themeJson: localTheme,
|
|
173
|
+
},
|
|
174
|
+
salesChannel,
|
|
175
|
+
routing: storefront.routings.length
|
|
176
|
+
? storefront.routings.find(
|
|
177
|
+
(r) => r.locale === locale || r.id === locale
|
|
178
|
+
) || storefront.routings[0]
|
|
179
|
+
: {
|
|
180
|
+
countryCodes: [],
|
|
181
|
+
domain: "",
|
|
182
|
+
dynamicCurrencySettings: {
|
|
183
|
+
roundingFormat: null,
|
|
184
|
+
targetCurrencyCode: "",
|
|
185
|
+
},
|
|
186
|
+
id: "",
|
|
187
|
+
locale: "en",
|
|
188
|
+
path: null,
|
|
189
|
+
priceListId: null,
|
|
190
|
+
},
|
|
191
|
+
favicon: localTheme.settings.favicon,
|
|
192
|
+
stockPreference: localTheme.settings.stockPreference,
|
|
193
|
+
storefrontJSScripts,
|
|
194
|
+
domain: "localhost:3333",
|
|
195
|
+
productBackInStockSettings,
|
|
196
|
+
customerReviewSettings,
|
|
197
|
+
merchantSettings: settings.merchantSettings,
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
static async getProdSettings(locale: string): Promise<SettingsData | null> {
|
|
202
|
+
return new Promise(async (resolve) => {
|
|
203
|
+
const settings = await IkasNextPageDataProvider.readSettingsFile();
|
|
204
|
+
if (!settings || !settings.localizationMap) return resolve(null);
|
|
205
|
+
|
|
206
|
+
const storefront = settings.storefront;
|
|
207
|
+
const salesChannel = settings.salesChannel;
|
|
208
|
+
const localizationMap = settings.localizationMap;
|
|
209
|
+
const storefrontJSScripts = settings.storefrontJSScripts || [];
|
|
210
|
+
const domain = settings.domain;
|
|
211
|
+
const productBackInStockSettings: IkasProductBackInStockSettings | null =
|
|
212
|
+
settings.productBackInStockSettings
|
|
213
|
+
? {
|
|
214
|
+
customerLoginRequired:
|
|
215
|
+
settings.productBackInStockSettings.customerLoginRequired,
|
|
216
|
+
}
|
|
217
|
+
: null;
|
|
218
|
+
const customerReviewSettings: IkasCustomerReviewSettings | null =
|
|
219
|
+
settings.customerReviewSettings
|
|
220
|
+
? {
|
|
221
|
+
customerLoginRequired:
|
|
222
|
+
settings.customerReviewSettings.customerLoginRequired || false,
|
|
223
|
+
customerPurchaseRequired:
|
|
224
|
+
settings.customerReviewSettings.customerPurchaseRequired ||
|
|
225
|
+
false,
|
|
226
|
+
}
|
|
227
|
+
: null;
|
|
228
|
+
|
|
229
|
+
let merchantSettings = settings.merchantSettings;
|
|
230
|
+
if (!merchantSettings) {
|
|
231
|
+
const response = await listMerchantSettings({});
|
|
232
|
+
if (response.isSuccess && response.data) {
|
|
233
|
+
merchantSettings = response.data;
|
|
234
|
+
} else {
|
|
235
|
+
console.error("MERCHANT SETTINGS FETCH FAILED!");
|
|
236
|
+
return resolve(null);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
const themeLocalizationPath = localizationMap[locale];
|
|
241
|
+
const routing = storefront.routings.find(
|
|
242
|
+
(r) => r.id === locale || r.path === locale
|
|
243
|
+
);
|
|
244
|
+
|
|
245
|
+
if (!themeLocalizationPath || !routing) {
|
|
246
|
+
console.error("THEME LOCALIZATION PATH OR ROUTING MISSING!!!");
|
|
247
|
+
return resolve(null);
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
fs.readFile(
|
|
251
|
+
themeLocalizationPath,
|
|
252
|
+
{
|
|
253
|
+
flag: "a+",
|
|
254
|
+
},
|
|
255
|
+
function (err, file) {
|
|
256
|
+
if (err) {
|
|
257
|
+
console.error("THEME LOCALIZATION FILE READ ERROR!!!");
|
|
258
|
+
console.error(err);
|
|
259
|
+
return resolve(null);
|
|
260
|
+
}
|
|
261
|
+
const result = file.length ? JSON.parse(file.toString()) : {};
|
|
262
|
+
const themeLocalization = result as IkasStorefrontThemeLocalization;
|
|
263
|
+
const favicon = themeLocalization.themeJson.settings.favicon;
|
|
264
|
+
const stockPreference =
|
|
265
|
+
themeLocalization.themeJson.settings.stockPreference;
|
|
266
|
+
|
|
267
|
+
if (themeLocalization.themeJson.settings) {
|
|
268
|
+
const colorScript = IkasNextPageDataProvider.createColorScript(
|
|
269
|
+
themeLocalization.themeJson.settings
|
|
270
|
+
);
|
|
271
|
+
const fontScript = IkasNextPageDataProvider.createFontScript(
|
|
272
|
+
themeLocalization.themeJson.settings
|
|
273
|
+
);
|
|
274
|
+
|
|
275
|
+
if (colorScript) storefrontJSScripts.push(colorScript);
|
|
276
|
+
if (fontScript) storefrontJSScripts.push(fontScript);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
resolve({
|
|
280
|
+
storefront,
|
|
281
|
+
themeLocalization,
|
|
282
|
+
salesChannel,
|
|
283
|
+
routing,
|
|
284
|
+
favicon,
|
|
285
|
+
stockPreference,
|
|
286
|
+
storefrontJSScripts,
|
|
287
|
+
domain,
|
|
288
|
+
productBackInStockSettings,
|
|
289
|
+
customerReviewSettings,
|
|
290
|
+
merchantSettings,
|
|
291
|
+
});
|
|
292
|
+
}
|
|
293
|
+
);
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
static async getSettings(locale: string): Promise<SettingsData | null> {
|
|
298
|
+
const isLocal = process.env.NEXT_PUBLIC_ENV === "local";
|
|
299
|
+
|
|
300
|
+
if (isLocal) {
|
|
301
|
+
return await this.getLocalSettings(locale);
|
|
302
|
+
} else {
|
|
303
|
+
return await this.getProdSettings(locale);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
static async setStorefrontConfig(settings: SettingsData) {
|
|
308
|
+
const {
|
|
309
|
+
storefront,
|
|
310
|
+
salesChannel,
|
|
311
|
+
routing,
|
|
312
|
+
favicon,
|
|
313
|
+
stockPreference,
|
|
314
|
+
storefrontJSScripts,
|
|
315
|
+
domain,
|
|
316
|
+
productBackInStockSettings,
|
|
317
|
+
customerReviewSettings,
|
|
318
|
+
merchantSettings,
|
|
319
|
+
} = settings;
|
|
320
|
+
|
|
321
|
+
IkasStorefrontConfig.init({
|
|
322
|
+
apiUrl: process.env.NEXT_PUBLIC_GQL_URL,
|
|
323
|
+
adminApiUrl: process.env.NEXT_PUBLIC_UPLOAD_GQL_URL,
|
|
324
|
+
cdnUrl: process.env.NEXT_PUBLIC_IMG_BASE_URL,
|
|
325
|
+
storefrontId: storefront.id,
|
|
326
|
+
storefrontRoutingId: routing.id,
|
|
327
|
+
storefrontThemeId: storefront.mainStorefrontThemeId!,
|
|
328
|
+
salesChannelId: storefront.salesChannelId!,
|
|
329
|
+
priceListId: routing.priceListId || undefined,
|
|
330
|
+
stockLocationIds: salesChannel.stockLocations?.map((sl) => sl.id),
|
|
331
|
+
routings: storefront.routings,
|
|
332
|
+
paymentGateways: salesChannel.paymentGateways || [],
|
|
333
|
+
gtmId: storefront.gtmId || undefined,
|
|
334
|
+
fbpId: storefront.fbpId || undefined,
|
|
335
|
+
analytics4Id: storefront.analytics4Id || undefined,
|
|
336
|
+
universalAnalyticsId: storefront.universalAnalyticsId || undefined,
|
|
337
|
+
tiktokPixelId: storefront.tiktokPixelId || undefined,
|
|
338
|
+
favicon: favicon || null,
|
|
339
|
+
pickUpStockLocationIds: storefront.pickUpStockLocationIds
|
|
340
|
+
? storefront.pickUpStockLocationIds.length
|
|
341
|
+
? storefront.pickUpStockLocationIds
|
|
342
|
+
: null
|
|
343
|
+
: null,
|
|
344
|
+
stockPreference: stockPreference || null,
|
|
345
|
+
storefrontJSScripts: storefrontJSScripts || [],
|
|
346
|
+
domain: domain,
|
|
347
|
+
productBackInStockSettings: productBackInStockSettings,
|
|
348
|
+
customerReviewSettings: customerReviewSettings,
|
|
349
|
+
merchantSettings,
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
static async setTranslations(
|
|
354
|
+
settings: SettingsData,
|
|
355
|
+
componentIds: string[],
|
|
356
|
+
pageType?: IkasThemeJsonPageType,
|
|
357
|
+
isEditor?: boolean
|
|
358
|
+
) {
|
|
359
|
+
const { serverRuntimeConfig } = getConfig();
|
|
360
|
+
const routing = settings.routing;
|
|
361
|
+
const isLocal = process.env.NEXT_PUBLIC_ENV === "local";
|
|
362
|
+
|
|
363
|
+
const components = settings.themeLocalization.themeJson.components.filter(
|
|
364
|
+
(c) => isEditor || componentIds.includes(c.id)
|
|
365
|
+
);
|
|
366
|
+
const namespaces = ["common", ...components.map((c) => c.dir)];
|
|
367
|
+
|
|
368
|
+
if (pageType === IkasThemeJsonPageType.CHECKOUT || isEditor) {
|
|
369
|
+
namespaces.push("checkout-page");
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const nextI18nConf = serverRuntimeConfig.nextI18nConf;
|
|
373
|
+
const currentLocale = routing.locale;
|
|
374
|
+
|
|
375
|
+
const i18nReader = new I18NFileReader(
|
|
376
|
+
currentLocale,
|
|
377
|
+
namespaces,
|
|
378
|
+
isLocal ? undefined : nextI18nConf.localePath
|
|
379
|
+
);
|
|
380
|
+
|
|
381
|
+
const translations = await i18nReader.read();
|
|
382
|
+
IkasStorefrontConfig.init({
|
|
383
|
+
translations,
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
static async getExtraProps(
|
|
388
|
+
settings: SettingsData,
|
|
389
|
+
provider: IkasPageDataProvider,
|
|
390
|
+
pageType?: IkasThemeJsonPageType
|
|
391
|
+
) {
|
|
392
|
+
const extraProps: Record<string, any> = {};
|
|
393
|
+
const themeLocalization = settings.themeLocalization;
|
|
394
|
+
|
|
395
|
+
if (pageType === IkasThemeJsonPageType.CHECKOUT) {
|
|
396
|
+
const checkoutComponent = provider.page?.components[0];
|
|
397
|
+
|
|
398
|
+
if (checkoutComponent) {
|
|
399
|
+
const checkoutSettings = await listCheckoutSettings({});
|
|
400
|
+
const customizationProps: IkasCheckoutCustomizationProps = {
|
|
401
|
+
showTax: checkoutComponent.propValues["showTax"] ?? true,
|
|
402
|
+
buttonBgColor: checkoutComponent.propValues["buttonBgColor"],
|
|
403
|
+
buttonTextColor: checkoutComponent.propValues["buttonTextColor"],
|
|
404
|
+
buttonDisabledBgColor:
|
|
405
|
+
checkoutComponent.propValues["buttonDisabledBgColor"],
|
|
406
|
+
buttonDisabledTextColor:
|
|
407
|
+
checkoutComponent.propValues["buttonDisabledTextColor"],
|
|
408
|
+
|
|
409
|
+
primaryTextColor: checkoutComponent.propValues["primaryTextColor"],
|
|
410
|
+
secondaryTextColor:
|
|
411
|
+
checkoutComponent.propValues["secondaryTextColor"],
|
|
412
|
+
|
|
413
|
+
primaryBgColor: checkoutComponent.propValues["primaryBgColor"],
|
|
414
|
+
secondaryBgColor: checkoutComponent.propValues["secondaryBgColor"],
|
|
415
|
+
borderColor: checkoutComponent.propValues["borderColor"],
|
|
416
|
+
cardBgColor: checkoutComponent.propValues["cardBgColor"],
|
|
417
|
+
|
|
418
|
+
errorColor: checkoutComponent.propValues["errorColor"],
|
|
419
|
+
errorLightColor: checkoutComponent.propValues["errorLightColor"],
|
|
420
|
+
warningColor: checkoutComponent.propValues["warningColor"],
|
|
421
|
+
warningLightColor: checkoutComponent.propValues["warningLightColor"],
|
|
422
|
+
successColor: checkoutComponent.propValues["successColor"],
|
|
423
|
+
successLightColor: checkoutComponent.propValues["successLightColor"],
|
|
424
|
+
};
|
|
425
|
+
|
|
426
|
+
extraProps.customizationProps = customizationProps;
|
|
427
|
+
extraProps.returnPolicy = themeLocalization.returnPolicy;
|
|
428
|
+
extraProps.privacyPolicy = themeLocalization.privacyPolicy;
|
|
429
|
+
extraProps.termsOfService = themeLocalization.termsOfService;
|
|
430
|
+
extraProps.checkoutSettings = checkoutSettings?.data?.length
|
|
431
|
+
? checkoutSettings.data[0]
|
|
432
|
+
: null;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
return extraProps;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
static async getPageData(
|
|
440
|
+
context:
|
|
441
|
+
| GetStaticPropsContext<ParsedUrlQuery>
|
|
442
|
+
| GetServerSidePropsContext<ParsedUrlQuery>,
|
|
443
|
+
isServer: boolean,
|
|
444
|
+
pageType?: IkasThemeJsonPageType,
|
|
445
|
+
possiblePageTypes?: IkasThemeJsonPageType[],
|
|
446
|
+
isEditor?: boolean
|
|
447
|
+
) {
|
|
448
|
+
const isLocal = process.env.NEXT_PUBLIC_ENV === "local";
|
|
449
|
+
const isProdEditor = !isLocal && isEditor;
|
|
450
|
+
|
|
451
|
+
IkasNextPageDataProvider.setAPIClientConfig();
|
|
452
|
+
|
|
453
|
+
IkasStorefrontConfig.init({
|
|
454
|
+
apiUrl: process.env.NEXT_PUBLIC_GQL_URL,
|
|
455
|
+
adminApiUrl: process.env.NEXT_PUBLIC_UPLOAD_GQL_URL,
|
|
456
|
+
cdnUrl: process.env.NEXT_PUBLIC_IMG_BASE_URL,
|
|
457
|
+
});
|
|
458
|
+
|
|
459
|
+
// Local editor - prod deploy - local build
|
|
460
|
+
if (!isProdEditor) {
|
|
461
|
+
const locale = context.locale;
|
|
462
|
+
|
|
463
|
+
if (!locale) {
|
|
464
|
+
return {
|
|
465
|
+
props: {},
|
|
466
|
+
notFound: true,
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
const settings = await IkasNextPageDataProvider.getSettings(locale);
|
|
471
|
+
|
|
472
|
+
if (
|
|
473
|
+
!settings ||
|
|
474
|
+
!settings.storefront.mainStorefrontThemeId ||
|
|
475
|
+
!settings.storefront.salesChannelId
|
|
476
|
+
) {
|
|
477
|
+
return {
|
|
478
|
+
props: {},
|
|
479
|
+
notFound: true,
|
|
480
|
+
};
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
await this.setStorefrontConfig(settings);
|
|
484
|
+
|
|
485
|
+
const themeLocalization = settings.themeLocalization;
|
|
486
|
+
const provider = new IkasPageDataProvider(
|
|
487
|
+
themeLocalization.themeJson,
|
|
488
|
+
context.params,
|
|
489
|
+
pageType
|
|
490
|
+
);
|
|
491
|
+
provider.possiblePageTypes =
|
|
492
|
+
possiblePageTypes || (pageType ? [pageType] : []);
|
|
493
|
+
|
|
494
|
+
if (!isEditor) {
|
|
495
|
+
await provider.getPageData();
|
|
496
|
+
if (!provider.page) {
|
|
497
|
+
return {
|
|
498
|
+
props: {},
|
|
499
|
+
notFound: true,
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
const componentIds = isEditor
|
|
505
|
+
? provider.theme.components.map((c) => c.id)
|
|
506
|
+
: provider.page?.components.map((pc) => pc.componentId) || [];
|
|
507
|
+
await this.setTranslations(settings, componentIds, pageType, isEditor);
|
|
508
|
+
|
|
509
|
+
const extraProps = await this.getExtraProps(settings, provider, pageType);
|
|
510
|
+
|
|
511
|
+
if (isServer)
|
|
512
|
+
return {
|
|
513
|
+
props: {
|
|
514
|
+
...provider.nextPageData.props,
|
|
515
|
+
...extraProps,
|
|
516
|
+
},
|
|
517
|
+
};
|
|
518
|
+
else {
|
|
519
|
+
return {
|
|
520
|
+
props: {
|
|
521
|
+
...provider.nextPageData.props,
|
|
522
|
+
...extraProps,
|
|
523
|
+
},
|
|
524
|
+
revalidate: 60,
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
} else {
|
|
528
|
+
return {
|
|
529
|
+
props: {},
|
|
530
|
+
};
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
static async getStaticProps(
|
|
535
|
+
context: GetStaticPropsContext<ParsedUrlQuery>,
|
|
536
|
+
pageType?: IkasThemeJsonPageType,
|
|
537
|
+
possiblePageTypes?: IkasThemeJsonPageType[],
|
|
538
|
+
isEditor?: boolean
|
|
539
|
+
) {
|
|
540
|
+
return await IkasNextPageDataProvider.getPageData(
|
|
541
|
+
context,
|
|
542
|
+
false,
|
|
543
|
+
pageType,
|
|
544
|
+
possiblePageTypes,
|
|
545
|
+
isEditor
|
|
546
|
+
);
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
static async getServerSideProps(
|
|
550
|
+
context: GetServerSidePropsContext<ParsedUrlQuery>,
|
|
551
|
+
pageType?: IkasThemeJsonPageType
|
|
552
|
+
) {
|
|
553
|
+
return await IkasNextPageDataProvider.getPageData(context, true, pageType);
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
static createColorScript(settings: IkasThemeJsonSettings) {
|
|
557
|
+
if (!settings.colors) return;
|
|
558
|
+
|
|
559
|
+
return `<script>${settings.colors
|
|
560
|
+
.map(
|
|
561
|
+
(sc) =>
|
|
562
|
+
`document.documentElement.style.setProperty("${sc.key}","${sc.color}");`
|
|
563
|
+
)
|
|
564
|
+
.join("\r\n")}</script>
|
|
565
|
+
`;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
static createFontScript(settings: IkasThemeJsonSettings) {
|
|
569
|
+
const fontHref = getGoogleFontHref(settings.fontFamily);
|
|
570
|
+
|
|
571
|
+
if (fontHref) {
|
|
572
|
+
return `<link id="ikas-font" rel="stylesheet" href="${fontHref}">
|
|
573
|
+
<style>
|
|
574
|
+
body {
|
|
575
|
+
font-family: '${settings.fontFamily.name}', -apple-system, system-ui, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif !important;
|
|
576
|
+
}
|
|
577
|
+
</style>`;
|
|
578
|
+
}
|
|
579
|
+
}
|
|
580
|
+
}
|
|
581
|
+
|
|
582
|
+
export type SettingsData = {
|
|
583
|
+
storefront: IkasStorefront;
|
|
584
|
+
themeLocalization: IkasStorefrontThemeLocalization;
|
|
585
|
+
salesChannel: IkasSalesChannel;
|
|
586
|
+
routing: IkasStorefrontRouting;
|
|
587
|
+
localizationMap?: Record<string, any>;
|
|
588
|
+
favicon: IkasThemeJsonFavicon;
|
|
589
|
+
stockPreference: IkasThemeJsonStockPreference;
|
|
590
|
+
storefrontJSScripts: string[];
|
|
591
|
+
domain: string;
|
|
592
|
+
productBackInStockSettings: IkasProductBackInStockSettings | null;
|
|
593
|
+
customerReviewSettings: IkasCustomerReviewSettings | null;
|
|
594
|
+
merchantSettings: IkasMerchantSettings;
|
|
595
|
+
};
|
|
596
|
+
|
|
597
|
+
export type IkasCheckoutCustomizationProps = {
|
|
598
|
+
showTax?: boolean;
|
|
599
|
+
buttonBgColor?: string;
|
|
600
|
+
buttonTextColor?: string;
|
|
601
|
+
buttonDisabledBgColor?: string;
|
|
602
|
+
buttonDisabledTextColor?: string;
|
|
603
|
+
|
|
604
|
+
primaryTextColor?: string;
|
|
605
|
+
secondaryTextColor?: string;
|
|
606
|
+
|
|
607
|
+
primaryBgColor?: string;
|
|
608
|
+
secondaryBgColor?: string;
|
|
609
|
+
borderColor?: string;
|
|
610
|
+
cardBgColor?: string;
|
|
611
|
+
|
|
612
|
+
errorColor?: string;
|
|
613
|
+
errorLightColor?: string;
|
|
614
|
+
warningColor?: string;
|
|
615
|
+
warningLightColor?: string;
|
|
616
|
+
successColor?: string;
|
|
617
|
+
successLightColor?: string;
|
|
618
|
+
};
|
package/src/utils/fs.ts
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Divides the given filePath string into directory part and fileName part
|
|
6
|
+
* @param path Path for the file
|
|
7
|
+
*/
|
|
8
|
+
export function getFilePathParts(path: string) {
|
|
9
|
+
const componentFilePathParts = path.split("/");
|
|
10
|
+
|
|
11
|
+
if (componentFilePathParts.length > 1) {
|
|
12
|
+
const dirParts = componentFilePathParts.slice(
|
|
13
|
+
0,
|
|
14
|
+
componentFilePathParts.length - 1
|
|
15
|
+
);
|
|
16
|
+
const filePart = componentFilePathParts[componentFilePathParts.length - 1];
|
|
17
|
+
|
|
18
|
+
return {
|
|
19
|
+
dirParts,
|
|
20
|
+
filePart,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
return {
|
|
25
|
+
filePart: path,
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Deletes the contents of the given directory, exluding the ignoreFiles
|
|
31
|
+
* @param dirPath Path for the directory
|
|
32
|
+
* @param ignoreFiles List of files to keep in directory. Does not accept recursive paths, only first level files
|
|
33
|
+
*
|
|
34
|
+
* @returns true for successfull operation, false otherwise
|
|
35
|
+
*/
|
|
36
|
+
export async function deleteDirContent(
|
|
37
|
+
dirPath: string,
|
|
38
|
+
ignoreFiles?: string[]
|
|
39
|
+
) {
|
|
40
|
+
try {
|
|
41
|
+
// const fs = await import("fs-extra");
|
|
42
|
+
const files = fs.readdirSync(dirPath);
|
|
43
|
+
|
|
44
|
+
files.forEach((file) => {
|
|
45
|
+
if (!ignoreFiles?.includes(file)) {
|
|
46
|
+
fs.unlinkSync(path.join(dirPath, file));
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
return true;
|
|
51
|
+
} catch (err) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Creates the given file and directories for the filePath
|
|
58
|
+
* @param basePath Base directory path for the file
|
|
59
|
+
* @param fileSubPath Filename or the sub directory path for the file to write
|
|
60
|
+
* @param fileStr File contents
|
|
61
|
+
*
|
|
62
|
+
* @returns true for successfull operation, false otherwise
|
|
63
|
+
*/
|
|
64
|
+
export async function createFile(
|
|
65
|
+
basePath: string,
|
|
66
|
+
fileSubPath: string,
|
|
67
|
+
fileStr: string
|
|
68
|
+
) {
|
|
69
|
+
try {
|
|
70
|
+
// const fs = await import("fs-extra");
|
|
71
|
+
let generatedFolderPath = basePath;
|
|
72
|
+
|
|
73
|
+
const pageFilePathParts = getFilePathParts(fileSubPath);
|
|
74
|
+
if (pageFilePathParts.dirParts?.length) {
|
|
75
|
+
generatedFolderPath = path.join(
|
|
76
|
+
generatedFolderPath,
|
|
77
|
+
...pageFilePathParts.dirParts
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!fs.existsSync(generatedFolderPath)) {
|
|
82
|
+
fs.mkdirSync(generatedFolderPath, { recursive: true });
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const filePath = path.join(generatedFolderPath, pageFilePathParts.filePart);
|
|
86
|
+
fs.writeFileSync(filePath, fileStr);
|
|
87
|
+
|
|
88
|
+
return true;
|
|
89
|
+
} catch (err) {
|
|
90
|
+
console.error(err);
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|