@ikas/storefront-cmd 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.
@@ -0,0 +1,526 @@
1
+ import {
2
+ IkasThemeJson,
3
+ IkasThemeJsonComponent,
4
+ IkasThemeJsonComponentProp,
5
+ IkasThemeJsonComponentPropType,
6
+ IkasThemeJsonCustomData,
7
+ } from "@ikas/storefront-models";
8
+ import path from "path";
9
+ import { createFile, deleteDirContent } from "../../../utils/fs";
10
+ import _uniq from "lodash/uniq";
11
+
12
+ type File = {
13
+ content: string;
14
+ imports: string[];
15
+ internalCustomDatas: IkasThemeJsonCustomData[];
16
+ };
17
+
18
+ export class CustomDataTypesGenerator {
19
+ static async generate(themeJson: IkasThemeJson, workingDir?: string) {
20
+ await deleteDirContent(
21
+ path.join(
22
+ workingDir || process.cwd(),
23
+ "src",
24
+ "components",
25
+ "__generated__",
26
+ "types"
27
+ )
28
+ );
29
+ const file: File = {
30
+ content: "",
31
+ imports: [],
32
+ internalCustomDatas: [],
33
+ };
34
+
35
+ try {
36
+ themeJson.customData.forEach((customData) => {
37
+ CustomDataTypesGenerator.generateAllCustomDataTypes(
38
+ customData,
39
+ file,
40
+ themeJson
41
+ );
42
+ });
43
+
44
+ let lengthBefore = 0;
45
+ let lengthAfter = 0;
46
+
47
+ do {
48
+ lengthBefore = file.internalCustomDatas.length;
49
+ file.internalCustomDatas.forEach((customData) => {
50
+ CustomDataTypesGenerator.generateAllCustomDataTypes(
51
+ customData,
52
+ file,
53
+ themeJson
54
+ );
55
+ });
56
+ lengthAfter = file.internalCustomDatas.length;
57
+
58
+ if (lengthAfter !== lengthBefore) {
59
+ file.internalCustomDatas = file.internalCustomDatas.splice(
60
+ lengthBefore,
61
+ lengthAfter
62
+ );
63
+ }
64
+ } while (lengthBefore !== lengthAfter);
65
+
66
+ await PropTypeGenarator.generate(themeJson, file);
67
+
68
+ const generatedFolderPath = path.join(
69
+ workingDir || process.cwd(),
70
+ "src",
71
+ "components",
72
+ "__generated__"
73
+ );
74
+
75
+ file.imports = _uniq(file.imports);
76
+ let importStr = `import {\r\n`;
77
+ file.imports.forEach((i) => {
78
+ importStr += `\t${i},\r\n`;
79
+ });
80
+ importStr += `} from "@ikas/storefront"\r\n\r\n`;
81
+
82
+ const finalFile = importStr + file.content;
83
+
84
+ return await createFile(generatedFolderPath, "types.ts", finalFile);
85
+ } catch (error) {
86
+ console.log(error);
87
+ return false;
88
+ }
89
+ }
90
+
91
+ static generateAllCustomDataTypes(
92
+ customData: IkasThemeJsonCustomData,
93
+ file: File,
94
+ themeJson: IkasThemeJson
95
+ ) {
96
+ const isEnum = customData.type === IkasThemeJsonComponentPropType.ENUM;
97
+ const exportTypeStr = `export ${
98
+ isEnum ? "enum" : "type"
99
+ } ${CustomDataTypesGenerator.generateTypeName(customData)}${
100
+ isEnum ? "" : " = "
101
+ }{ \r\n`;
102
+
103
+ const closeExportTypeStr = `};\r\n\r\n`;
104
+
105
+ if (
106
+ (customData.type === IkasThemeJsonComponentPropType.DYNAMIC_LIST ||
107
+ customData.type === IkasThemeJsonComponentPropType.STATIC_LIST) &&
108
+ customData.nestedData
109
+ ) {
110
+ CustomDataTypesGenerator.generateAllCustomDataTypes(
111
+ customData.nestedData[0],
112
+ file,
113
+ themeJson
114
+ );
115
+ } else if (
116
+ customData.type === IkasThemeJsonComponentPropType.ENUM &&
117
+ !!customData.enumOptions
118
+ ) {
119
+ file.content += exportTypeStr;
120
+ customData.enumOptions.forEach((enumOption) => {
121
+ let leftValue = enumOption.value;
122
+
123
+ if (enumOption.value && !isNaN(parseInt(enumOption.value))) {
124
+ leftValue = "_" + enumOption.value;
125
+ }
126
+
127
+ file.content += `\t"${leftValue}" = "${enumOption?.value}",`;
128
+ file.content += `\r\n`;
129
+ });
130
+ file.content += closeExportTypeStr;
131
+ } else {
132
+ file.content += exportTypeStr;
133
+ if (!!customData.nestedData) {
134
+ customData.nestedData.forEach((nestedData) => {
135
+ CustomDataTypesGenerator.genenateCustomDataType(
136
+ nestedData,
137
+ file,
138
+ themeJson
139
+ );
140
+ file.content += `\r\n`;
141
+ });
142
+ }
143
+
144
+ file.content += closeExportTypeStr;
145
+ }
146
+ }
147
+
148
+ static genenateCustomDataType(
149
+ customData: IkasThemeJsonCustomData,
150
+ file: File,
151
+ themeJson: IkasThemeJson
152
+ ) {
153
+ const type = CustomDataTypesGenerator.getType(customData, file, themeJson);
154
+
155
+ if (customData.key && customData.key[0].match(/^\d/)) {
156
+ customData.key = "_" + customData.key;
157
+ }
158
+
159
+ file.content += `\t${customData.key}${
160
+ !customData.isRequired ? "?" : ""
161
+ }: ${type}${
162
+ [
163
+ IkasThemeJsonComponentPropType.DYNAMIC_LIST,
164
+ IkasThemeJsonComponentPropType.STATIC_LIST,
165
+ ].includes(customData.type)
166
+ ? "[]"
167
+ : ""
168
+ }${customData.type === IkasThemeJsonComponentPropType.ENUM ? "," : ";"}`;
169
+ }
170
+
171
+ static getType(
172
+ customData: IkasThemeJsonCustomData,
173
+ file: File,
174
+ themeJson: IkasThemeJson
175
+ ) {
176
+ let type = "";
177
+ switch (customData.type) {
178
+ case IkasThemeJsonComponentPropType.TEXT:
179
+ case IkasThemeJsonComponentPropType.RICH_TEXT:
180
+ case IkasThemeJsonComponentPropType.COLOR:
181
+ type = "string";
182
+ break;
183
+ case IkasThemeJsonComponentPropType.BOOLEAN:
184
+ type = "boolean";
185
+ break;
186
+ case IkasThemeJsonComponentPropType.IMAGE:
187
+ type = "IkasImage";
188
+ file.imports.push(type);
189
+ break;
190
+ case IkasThemeJsonComponentPropType.IMAGE_LIST:
191
+ type = "IkasImage[]";
192
+ file.imports.push("IkasImage");
193
+ break;
194
+ case IkasThemeJsonComponentPropType.LINK:
195
+ type = "IkasNavigationLink";
196
+ file.imports.push(type);
197
+ break;
198
+ case IkasThemeJsonComponentPropType.LIST_OF_LINK:
199
+ type = "IkasNavigationLink[]";
200
+ file.imports.push("IkasNavigationLink");
201
+ break;
202
+ case IkasThemeJsonComponentPropType.PRODUCT_DETAIL:
203
+ type = "IkasProduct";
204
+ file.imports.push(type);
205
+ break;
206
+ case IkasThemeJsonComponentPropType.PRODUCT_LIST:
207
+ type = "IkasProductList";
208
+ file.imports.push("IkasProductList");
209
+ break;
210
+ case IkasThemeJsonComponentPropType.PRODUCT_ATTRIBUTE:
211
+ type = "IkasProductAttribute";
212
+ file.imports.push(type);
213
+ break;
214
+ case IkasThemeJsonComponentPropType.PRODUCT_ATTRIBUTE_LIST:
215
+ type = "IkasProductAttribute[]";
216
+ file.imports.push("IkasProductAttribute");
217
+ break;
218
+
219
+ case IkasThemeJsonComponentPropType.BRAND:
220
+ type = "IkasBrand";
221
+ file.imports.push(type);
222
+ break;
223
+ case IkasThemeJsonComponentPropType.BRAND_LIST:
224
+ type = "IkasBrandList";
225
+ file.imports.push(type);
226
+ break;
227
+ case IkasThemeJsonComponentPropType.CATEGORY:
228
+ type = "IkasCategory";
229
+ file.imports.push(type);
230
+ break;
231
+ case IkasThemeJsonComponentPropType.CATEGORY_LIST:
232
+ type = "IkasCategoryList";
233
+ file.imports.push(type);
234
+ break;
235
+ case IkasThemeJsonComponentPropType.CUSTOM:
236
+ const cd = themeJson.customData.find(
237
+ (cd) => cd.id === customData.customDataId
238
+ );
239
+ if (cd) type = CustomDataTypesGenerator.generateTypeName(cd);
240
+ break;
241
+ case IkasThemeJsonComponentPropType.COMPONENT:
242
+ type = "IkasComponentRenderer";
243
+ file.imports.push(type);
244
+ break;
245
+ case IkasThemeJsonComponentPropType.COMPONENT_LIST:
246
+ type = "IkasComponentRenderer[]";
247
+ file.imports.push("IkasComponentRenderer");
248
+ break;
249
+ case IkasThemeJsonComponentPropType.BLOG:
250
+ type = "IkasBlog";
251
+ file.imports.push(type);
252
+ break;
253
+ case IkasThemeJsonComponentPropType.BLOG_LIST:
254
+ type = "IkasBlogList";
255
+ file.imports.push(type);
256
+ break;
257
+ case IkasThemeJsonComponentPropType.BLOG_CATEGORY:
258
+ type = "IkasBlogCategory";
259
+ file.imports.push(type);
260
+ break;
261
+ case IkasThemeJsonComponentPropType.BLOG_CATEGORY_LIST:
262
+ type = "IkasBlogCategoryList";
263
+ file.imports.push(type);
264
+ break;
265
+ case IkasThemeJsonComponentPropType.RAFFLE:
266
+ type = "IkasRaffle";
267
+ file.imports.push(type);
268
+ break;
269
+ case IkasThemeJsonComponentPropType.RAFFLE_LIST:
270
+ type = "IkasRaffleList";
271
+ file.imports.push(type);
272
+ break;
273
+ case IkasThemeJsonComponentPropType.SLIDER:
274
+ type = "IkasSlider";
275
+ file.imports.push(type);
276
+ break;
277
+
278
+ case IkasThemeJsonComponentPropType.ENUM:
279
+ type = CustomDataTypesGenerator.generateTypeName(customData);
280
+ if (!file.content.includes(`export enum ${type}`)) {
281
+ file.internalCustomDatas.push(customData);
282
+ }
283
+ break;
284
+ case IkasThemeJsonComponentPropType.OBJECT:
285
+ type = CustomDataTypesGenerator.generateTypeName(customData);
286
+ break;
287
+ case IkasThemeJsonComponentPropType.DYNAMIC_LIST:
288
+ case IkasThemeJsonComponentPropType.STATIC_LIST:
289
+ if (customData.nestedData) {
290
+ if (
291
+ customData.nestedData[0].type ===
292
+ IkasThemeJsonComponentPropType.OBJECT ||
293
+ customData.nestedData[0].type ===
294
+ IkasThemeJsonComponentPropType.ENUM
295
+ ) {
296
+ type = CustomDataTypesGenerator.generateTypeName(
297
+ customData.nestedData[0]
298
+ );
299
+ if (!file.content.includes(`export type ${type}`)) {
300
+ file.internalCustomDatas.push(customData.nestedData[0]);
301
+ }
302
+ } else {
303
+ type = CustomDataTypesGenerator.getType(
304
+ customData.nestedData[0],
305
+ file,
306
+ themeJson
307
+ );
308
+ }
309
+ }
310
+
311
+ break;
312
+ default:
313
+ break;
314
+ }
315
+ return type;
316
+ }
317
+
318
+ static generateTypeName(customData: IkasThemeJsonCustomData) {
319
+ if (customData.typescriptName) return customData.typescriptName;
320
+
321
+ let displayName = customData.name || "";
322
+ displayName = displayName.replace(/\s/g, ""); // removes whitespace
323
+ displayName = displayName.replace(/\W/g, ""); // removes non-alphabetic characters
324
+
325
+ if (displayName[0].match(/^\d/)) displayName = "_" + displayName; // if first char is a number add (_)
326
+ if (customData.type === IkasThemeJsonComponentPropType.ENUM)
327
+ displayName += "Enum";
328
+
329
+ return displayName;
330
+ }
331
+ }
332
+
333
+ export class PropTypeGenarator {
334
+ static async generate(themeJson: IkasThemeJson, file: File) {
335
+ const components = themeJson.components;
336
+ components.forEach((component) => {
337
+ if (component.props.length > 0 && component.id !== "checkout") {
338
+ file.content += `export type ${PropTypeGenarator.generatePropTypeName(
339
+ component
340
+ )}Props = {\n`;
341
+ component.props.forEach((prop) => {
342
+ file.content += `\t${prop.name}: ${PropTypeGenarator.getType(
343
+ prop,
344
+ themeJson,
345
+ file
346
+ )};\n`;
347
+ });
348
+
349
+ file.content += `};\r\n\r\n`;
350
+ }
351
+ });
352
+ }
353
+
354
+ static getType(
355
+ prop: IkasThemeJsonComponentProp,
356
+ themeJson: IkasThemeJson,
357
+ file: File
358
+ ) {
359
+ let type = "";
360
+ switch (prop.type) {
361
+ case IkasThemeJsonComponentPropType.TEXT:
362
+ case IkasThemeJsonComponentPropType.RICH_TEXT:
363
+ case IkasThemeJsonComponentPropType.COLOR:
364
+ type = "string";
365
+ break;
366
+ case IkasThemeJsonComponentPropType.BOOLEAN:
367
+ type = "boolean";
368
+ break;
369
+ case IkasThemeJsonComponentPropType.IMAGE:
370
+ type = "IkasImage";
371
+ file.imports.push(type);
372
+ break;
373
+ case IkasThemeJsonComponentPropType.IMAGE_LIST:
374
+ type = "IkasImage[]";
375
+ file.imports.push("IkasImage");
376
+ break;
377
+ case IkasThemeJsonComponentPropType.LINK:
378
+ type = "IkasNavigationLink";
379
+ file.imports.push(type);
380
+ break;
381
+ case IkasThemeJsonComponentPropType.LIST_OF_LINK:
382
+ type = "IkasNavigationLink[]";
383
+ file.imports.push("IkasNavigationLink");
384
+ break;
385
+ case IkasThemeJsonComponentPropType.PRODUCT_DETAIL:
386
+ type = "IkasProduct";
387
+ file.imports.push(type);
388
+ break;
389
+ case IkasThemeJsonComponentPropType.PRODUCT_LIST:
390
+ type = "IkasProductList";
391
+ file.imports.push("IkasProductList");
392
+ break;
393
+ case IkasThemeJsonComponentPropType.PRODUCT_ATTRIBUTE:
394
+ type = "IkasProductAttribute";
395
+ file.imports.push(type);
396
+ break;
397
+ case IkasThemeJsonComponentPropType.PRODUCT_ATTRIBUTE_LIST:
398
+ type = "IkasProductAttribute[]";
399
+ file.imports.push("IkasProductAttribute");
400
+ break;
401
+
402
+ case IkasThemeJsonComponentPropType.BRAND:
403
+ type = "IkasBrand";
404
+ file.imports.push(type);
405
+ break;
406
+ case IkasThemeJsonComponentPropType.BRAND_LIST:
407
+ type = "IkasBrandList";
408
+ file.imports.push(type);
409
+ break;
410
+ case IkasThemeJsonComponentPropType.CATEGORY:
411
+ type = "IkasCategory";
412
+ file.imports.push(type);
413
+ break;
414
+ case IkasThemeJsonComponentPropType.CATEGORY_LIST:
415
+ type = "IkasCategoryList";
416
+ file.imports.push(type);
417
+ break;
418
+ case IkasThemeJsonComponentPropType.CUSTOM:
419
+ const cd = themeJson.customData.find(
420
+ (cd) => cd.id === prop.customDataId
421
+ );
422
+
423
+ if (cd) {
424
+ type = CustomDataTypesGenerator.getType(cd, file, themeJson);
425
+ if (
426
+ cd.type === IkasThemeJsonComponentPropType.DYNAMIC_LIST ||
427
+ cd.type === IkasThemeJsonComponentPropType.STATIC_LIST
428
+ ) {
429
+ type += "[]";
430
+ }
431
+ }
432
+ break;
433
+ case IkasThemeJsonComponentPropType.COMPONENT:
434
+ type = "IkasComponentRenderer";
435
+ file.imports.push(type);
436
+ break;
437
+ case IkasThemeJsonComponentPropType.COMPONENT_LIST:
438
+ type = "IkasComponentRenderer[]";
439
+ file.imports.push("IkasComponentRenderer");
440
+ break;
441
+ case IkasThemeJsonComponentPropType.BLOG:
442
+ type = "IkasBlog";
443
+ file.imports.push(type);
444
+ break;
445
+ case IkasThemeJsonComponentPropType.BLOG_LIST:
446
+ type = "IkasBlogList";
447
+ file.imports.push(type);
448
+ break;
449
+ case IkasThemeJsonComponentPropType.BLOG_CATEGORY:
450
+ type = "IkasBlogCategory";
451
+ file.imports.push(type);
452
+ break;
453
+ case IkasThemeJsonComponentPropType.BLOG_CATEGORY_LIST:
454
+ type = "IkasBlogCategoryList";
455
+ file.imports.push(type);
456
+ break;
457
+ case IkasThemeJsonComponentPropType.RAFFLE:
458
+ type = "IkasRaffle";
459
+ file.imports.push(type);
460
+ break;
461
+ case IkasThemeJsonComponentPropType.RAFFLE_LIST:
462
+ type = "IkasRaffleList";
463
+ file.imports.push(type);
464
+ break;
465
+ case IkasThemeJsonComponentPropType.SLIDER:
466
+ type = "IkasSlider";
467
+ file.imports.push(type);
468
+ break;
469
+
470
+ // case IkasThemeJsonComponentPropType.ENUM:
471
+ // const enumCd = themeJson.customData.find(
472
+ // (cd) => cd.id === prop.customDataId
473
+ // );
474
+ // if (enumCd) type = CustomDataTypesGenerator.generateTypeName(enumCd);
475
+ // break;
476
+ // case IkasThemeJsonComponentPropType.DYNAMIC_LIST:
477
+ // case IkasThemeJsonComponentPropType.STATIC_LIST:
478
+ // const listCD = themeJson.customData.find(
479
+ // (cd) => cd.id === prop.customDataId
480
+ // );
481
+ // if (listCD?.nestedData) {
482
+ // if (
483
+ // listCD.nestedData[0].type === IkasThemeJsonComponentPropType.OBJECT ||
484
+ // listCD.nestedData[0].type === IkasThemeJsonComponentPropType.ENUM
485
+ // ) {
486
+ // type = CustomDataTypesGenerator.generateTypeName(
487
+ // listCD.nestedData[0]
488
+ // );
489
+ // if (!file.content.includes(`export type ${type}`)) {
490
+ // file.internalCustomDatas.push(listCD.nestedData[0]);
491
+ // }
492
+ // } else {
493
+ // type = CustomDataTypesGenerator.getType(
494
+ // listCD.nestedData[0],
495
+ // file,
496
+ // themeJson
497
+ // );
498
+ // }
499
+ // console.log("nesteddata custom type", type);
500
+ // }
501
+
502
+ // break;
503
+ default:
504
+ break;
505
+ }
506
+
507
+ return type;
508
+ }
509
+
510
+ static generatePropTypeName(component: IkasThemeJsonComponent) {
511
+ if (component.displayName === "") return;
512
+
513
+ const propName = component.dir || "";
514
+ const pieces = propName.split("-");
515
+ let _propName = "";
516
+
517
+ pieces.forEach(
518
+ (piece, index) =>
519
+ (_propName += piece.charAt(0).toUpperCase() + piece.slice(1))
520
+ );
521
+
522
+ if (_propName[0].match(/^\d/)) _propName = "_" + _propName;
523
+
524
+ return _propName;
525
+ }
526
+ }
@@ -0,0 +1,45 @@
1
+ import commandLineArgs from "command-line-args";
2
+ import { APIGenerator } from "./generators/api";
3
+ import { ConfigGenerator, ENV } from "./generators/config";
4
+ import { ThemeJsonGenerator } from "./generators/theme";
5
+ import { ComponentImportsGenerator } from "./generators/components";
6
+ import { PageGenerator } from "./generators/pages";
7
+ import { CustomDataTypesGenerator } from "./generators/types";
8
+
9
+ async function run() {
10
+ const optionDefinitions = [
11
+ { name: "generate", alias: "g", type: Boolean },
12
+ { name: "dev", alias: "d", type: Boolean },
13
+ ];
14
+
15
+ const options = commandLineArgs(optionDefinitions);
16
+
17
+ if (options.generate) {
18
+ const isDev = !!options.dev;
19
+ const isSuccess = await generate(isDev ? "dev" : "prod");
20
+
21
+ if (isSuccess) {
22
+ console.log("Project files generated successfully!");
23
+ } else {
24
+ console.log("Project files generate failed!");
25
+ }
26
+ }
27
+ }
28
+
29
+ async function generate(env: ENV) {
30
+ let themeJson = await ThemeJsonGenerator.getTheme();
31
+
32
+ if (!themeJson) await ThemeJsonGenerator.generateInitialThemeJsonFile();
33
+ themeJson = await ThemeJsonGenerator.getTheme();
34
+
35
+ return (
36
+ (await ThemeJsonGenerator.generate(themeJson)) &&
37
+ (await ComponentImportsGenerator.generate(themeJson)) &&
38
+ (await PageGenerator.generate()) &&
39
+ (await APIGenerator.generate()) &&
40
+ (await ConfigGenerator.generate(env)) &&
41
+ (await CustomDataTypesGenerator.generate(themeJson))
42
+ );
43
+ }
44
+
45
+ run();
@@ -0,0 +1,99 @@
1
+ import { IkasThemeJson, IkasThemeJsonPage } from "@ikas/storefront-models";
2
+ import _cloneDeep from "lodash/cloneDeep";
3
+ import {
4
+ ComponentImportsGenerator,
5
+ ConfigGenerator,
6
+ CustomDataTypesGenerator,
7
+ PageGenerator,
8
+ } from "../generators";
9
+
10
+ export function shouldDeploy(
11
+ oldThemeJson: IkasThemeJson,
12
+ newThemeJson: IkasThemeJson
13
+ ) {
14
+ if (
15
+ oldThemeJson.pages.some(
16
+ (page) => !newThemeJson.pages.find((p) => p.id === page.id)
17
+ ) ||
18
+ newThemeJson.pages.some(
19
+ (page) => !oldThemeJson.pages.find((p) => p.id === page.id)
20
+ )
21
+ )
22
+ return true;
23
+
24
+ return oldThemeJson.pages.some((page) => {
25
+ const comparedPage = newThemeJson.pages.find((p) => p.id === page.id);
26
+
27
+ const allOldPageComponents = page.components;
28
+ if (page.specifications?.length) {
29
+ page.specifications.forEach((specification) => {
30
+ allOldPageComponents.push(...specification.components);
31
+ });
32
+ }
33
+
34
+ const allNewPageComponents = comparedPage?.components || [];
35
+ if (comparedPage?.specifications?.length) {
36
+ comparedPage.specifications.forEach((specification) => {
37
+ allNewPageComponents.push(...specification.components);
38
+ });
39
+ }
40
+
41
+ const addedPageComponents = allOldPageComponents.filter(
42
+ (pageComponent) =>
43
+ !allNewPageComponents.find(
44
+ (compagedPageComponent) =>
45
+ pageComponent.componentId === compagedPageComponent.componentId
46
+ )
47
+ );
48
+
49
+ const deletedPageComponents = allNewPageComponents.filter(
50
+ (pageComponent) =>
51
+ !allOldPageComponents.find(
52
+ (compagedPageComponent) =>
53
+ pageComponent.componentId === compagedPageComponent.componentId
54
+ )
55
+ );
56
+
57
+ return !!addedPageComponents.length || !!deletedPageComponents.length;
58
+ });
59
+ }
60
+
61
+ export async function generate(
62
+ themeJsonList: IkasThemeJson[],
63
+ workingDir: string
64
+ ) {
65
+ const _themeJsonList = _cloneDeep(themeJsonList);
66
+ const themeJson: IkasThemeJson = {
67
+ components: [],
68
+ pages: [],
69
+ customData: [],
70
+ name: "",
71
+ settings: {} as any,
72
+ };
73
+
74
+ themeJson.components = _themeJsonList[0].components;
75
+ themeJson.customData = _themeJsonList[0].customData;
76
+
77
+ _themeJsonList.forEach((_themeJson) => {
78
+ _themeJson.pages.forEach((_page) => {
79
+ const existingPage = themeJson.pages.find((p) => p.type === _page.type);
80
+
81
+ const page: IkasThemeJsonPage = existingPage || _page;
82
+ page.components.push(..._page.components);
83
+
84
+ if (!page.specifications) page.specifications = [];
85
+ page.specifications.push(...(_page.specifications || []));
86
+
87
+ if (!existingPage) {
88
+ themeJson.pages.push(page);
89
+ }
90
+ });
91
+ });
92
+
93
+ return (
94
+ (await ComponentImportsGenerator.generate(themeJson, workingDir)) &&
95
+ (await PageGenerator.generate(workingDir)) &&
96
+ (await CustomDataTypesGenerator.generate(themeJson, workingDir)) &&
97
+ (await ConfigGenerator.generate("prod", workingDir))
98
+ );
99
+ }