shopify-accelerate-app 1.0.0

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 (47) hide show
  1. package/@types/metafields.ts +9 -0
  2. package/@types/sections.ts +1769 -0
  3. package/@types/settings.ts +3 -0
  4. package/@types/shopify.ts +1871 -0
  5. package/@types/types.d.ts +17 -0
  6. package/README.md +2 -0
  7. package/package.json +111 -0
  8. package/shopify-accelerate-app.ts +394 -0
  9. package/shopify.graphql +48866 -0
  10. package/src/esbuild/esbuild.ts +246 -0
  11. package/src/scaffold-theme/build-theme.ts +24 -0
  12. package/src/scaffold-theme/generate-asset-files.ts +48 -0
  13. package/src/scaffold-theme/generate-base-types.ts +23 -0
  14. package/src/scaffold-theme/generate-block-files.ts +194 -0
  15. package/src/scaffold-theme/generate-blocks-types.ts +242 -0
  16. package/src/scaffold-theme/generate-config-files.ts +34 -0
  17. package/src/scaffold-theme/generate-liquid-files.ts +995 -0
  18. package/src/scaffold-theme/generate-schema-locales.ts +195 -0
  19. package/src/scaffold-theme/generate-schema-variables.ts +380 -0
  20. package/src/scaffold-theme/generate-section-files.ts +303 -0
  21. package/src/scaffold-theme/generate-section-preset-files.ts +296 -0
  22. package/src/scaffold-theme/generate-section-types.ts +339 -0
  23. package/src/scaffold-theme/generate-setting-types.ts +123 -0
  24. package/src/scaffold-theme/generate-settings-file.ts +103 -0
  25. package/src/scaffold-theme/parse-files.ts +466 -0
  26. package/src/scaffold-theme/parse-locales.ts +98 -0
  27. package/src/shopify-cli/pull.ts +103 -0
  28. package/src/tailwind/postcss.config.js +8 -0
  29. package/src/tailwind/tailwind-watch.ts +133 -0
  30. package/src/tailwind/tailwind.config.js +261 -0
  31. package/src/telemetry/telemetry.ts +84 -0
  32. package/src/templates/.env.template +12 -0
  33. package/src/templates/shopify.theme.toml +9 -0
  34. package/src/utils/capitalize.ts +3 -0
  35. package/src/utils/delay.ts +3 -0
  36. package/src/utils/fs.ts +87 -0
  37. package/src/utils/is-object.ts +3 -0
  38. package/src/utils/json.ts +8 -0
  39. package/src/utils/to-camel-case.ts +6 -0
  40. package/src/utils/to-kebab-case.ts +6 -0
  41. package/src/utils/to-pascal-case.ts +12 -0
  42. package/src/utils/to-snake-case.ts +45 -0
  43. package/src/validate-cli-options.ts +281 -0
  44. package/src/watch-headless/watch-headless.ts +81 -0
  45. package/src/watch-theme/watch-theme.ts +84 -0
  46. package/tsconfig.json +82 -0
  47. package/tsconfig.tsbuildinfo +1 -0
@@ -0,0 +1,466 @@
1
+ import chalk from "chalk";
2
+ import importFresh from "import-fresh";
3
+ import path from "path";
4
+ import { ShopifyBlock, ShopifySection, ShopifySettings } from "../../@types/shopify";
5
+ import { config } from "../../shopify-accelerate-app";
6
+ import { getAllFiles } from "../utils/fs";
7
+
8
+ export const getSources = () => {
9
+ const { folders, disabled_theme_blocks } = config;
10
+
11
+ const sourceFiles = [
12
+ ...getAllFiles(folders.sections),
13
+ ...getAllFiles(folders.presets),
14
+ ...getAllFiles(folders.snippets),
15
+ ...getAllFiles(folders.config),
16
+ ...getAllFiles(folders.templates),
17
+ ...getAllFiles(folders.assets),
18
+ ...getAllFiles(folders.layout),
19
+ ...getAllFiles(folders.utils),
20
+ ...getAllFiles(folders.types),
21
+ ...getAllFiles(folders.blocks),
22
+ ];
23
+
24
+ const typeScriptSchema = [];
25
+
26
+ const snippets = [];
27
+ const layouts = [];
28
+ const sectionsLiquid = [];
29
+ const sectionsSchemaFiles = [];
30
+ const sectionPresetSchemaFiles = [];
31
+ const sectionsJs = [];
32
+ const settingsFiles = [];
33
+ const blocksLiquid = [];
34
+ const blocksSchemaFiles = [];
35
+ const blocksJs = [];
36
+ const giftCards = [];
37
+ const sectionGroups = [];
38
+ const configs = [];
39
+ const templates = [];
40
+ const customerTemplates = [];
41
+ const assets = [];
42
+
43
+ sourceFiles.forEach((filePath) => {
44
+ if (isTypeScriptSchema(filePath)) {
45
+ typeScriptSchema.push(filePath);
46
+ }
47
+ if (isSnippet(filePath)) {
48
+ snippets.push(filePath);
49
+ }
50
+ if (isLayout(filePath)) {
51
+ layouts.push(filePath);
52
+ }
53
+ if (isSectionLiquid(filePath)) {
54
+ sectionsLiquid.push(filePath);
55
+ }
56
+ if (isSectionSchema(filePath)) {
57
+ sectionsSchemaFiles.push(filePath);
58
+ }
59
+ if (isSectionPresetSchema(filePath)) {
60
+ sectionPresetSchemaFiles.push(filePath);
61
+ }
62
+ if (isSectionTs(filePath)) {
63
+ sectionsJs.push(filePath);
64
+ }
65
+ if (isBlockLiquid(filePath)) {
66
+ blocksLiquid.push(filePath);
67
+ if (disabled_theme_blocks) {
68
+ snippets.push(filePath);
69
+ }
70
+ }
71
+ if (isBlockSchema(filePath)) {
72
+ blocksSchemaFiles.push(filePath);
73
+ }
74
+ if (isBlockTs(filePath)) {
75
+ blocksJs.push(filePath);
76
+ }
77
+ if (isGiftCard(filePath)) {
78
+ giftCards.push(filePath);
79
+ }
80
+ if (isSectionGroup(filePath)) {
81
+ sectionGroups.push(filePath);
82
+ }
83
+ if (isConfig(filePath)) {
84
+ configs.push(filePath);
85
+ }
86
+ if (isTemplate(filePath)) {
87
+ templates.push(filePath);
88
+ }
89
+ if (isCustomerTemplate(filePath)) {
90
+ customerTemplates.push(filePath);
91
+ }
92
+ if (isAsset(filePath)) {
93
+ assets.push(filePath);
94
+ }
95
+ if (isSettingsSchema(filePath)) {
96
+ settingsFiles.push(filePath);
97
+ }
98
+ });
99
+
100
+ config.sources.snippets = snippets;
101
+ config.sources.layouts = layouts;
102
+ config.sources.sectionsLiquid = sectionsLiquid;
103
+ config.sources.sectionsSchemaFiles = sectionsSchemaFiles;
104
+ config.sources.sectionPresetSchemaFiles = sectionPresetSchemaFiles;
105
+ config.sources.sectionsJs = sectionsJs;
106
+ config.sources.blocksLiquid = blocksLiquid;
107
+ config.sources.blocksSchemaFiles = blocksSchemaFiles;
108
+ config.sources.blocksJs = blocksJs;
109
+ config.sources.assets = assets;
110
+ config.sources.giftCards = giftCards;
111
+ config.sources.configs = configs;
112
+ config.sources.sectionGroups = sectionGroups;
113
+ config.sources.templates = templates;
114
+ config.sources.customerTemplates = customerTemplates;
115
+ config.sources.settingsFile = settingsFiles?.[0];
116
+ config.sources.settingsSchema = settingsFiles?.[0]
117
+ ? (importFresh(settingsFiles[0]) as { settingsSchema: ShopifySettings })?.settingsSchema
118
+ : [];
119
+
120
+ config.sources.sectionSchemas = sectionsSchemaFiles.reduce(
121
+ (acc, file) => {
122
+ try {
123
+ const data = importFresh(file);
124
+ return {
125
+ ...acc,
126
+ ...Object.entries(data).reduce((acc2, [key, val]) => {
127
+ // @ts-ignore
128
+ acc2[key] = { ...val, folder: file.split(/[\\/]/gi).at(-2), path: file };
129
+ return acc2;
130
+ }, {}),
131
+ };
132
+ } catch (err) {
133
+ console.log(chalk.redBright(err.message));
134
+ return acc;
135
+ }
136
+ },
137
+ {} as { [T: string]: ShopifySection }
138
+ );
139
+ config.sources.sectionPresetSchemas = sectionPresetSchemaFiles.reduce(
140
+ (acc, file) => {
141
+ try {
142
+ let data = importFresh(file);
143
+ if (data["default"]) {
144
+ data = data["default"];
145
+ }
146
+
147
+ return {
148
+ ...acc,
149
+ ...Object.entries(data).reduce((acc2, [key, val]) => {
150
+ // @ts-ignore
151
+ acc2[key] = { ...val, folder: file.split(/[\\/]/gi).at(-2), path: file };
152
+ return acc2;
153
+ }, {}),
154
+ };
155
+ } catch (err) {
156
+ console.log(chalk.redBright(err.message));
157
+ return acc;
158
+ }
159
+ },
160
+ {} as { [T: string]: ShopifySection }
161
+ );
162
+
163
+ config.sources.blockSchemas = blocksSchemaFiles.reduce(
164
+ (acc, file) => {
165
+ try {
166
+ const data = importFresh(file);
167
+
168
+ return {
169
+ ...acc,
170
+ ...Object.entries(data).reduce((acc2, [key, val]) => {
171
+ // @ts-ignore
172
+ acc2[key] = { ...val, folder: file.split(/[\\/]/gi).at(-2), path: file };
173
+ return acc2;
174
+ }, {}),
175
+ };
176
+ } catch (err) {
177
+ console.log(chalk.redBright(err.message));
178
+ return acc;
179
+ }
180
+ },
181
+ {} as { [T: string]: ShopifyBlock }
182
+ );
183
+ };
184
+
185
+ export const getSchemaSources = () => {
186
+ const { folders, disabled_theme_blocks } = config;
187
+
188
+ const sourceFiles = [
189
+ ...getAllFiles(folders.layout),
190
+ ...getAllFiles(folders.snippets),
191
+ ...getAllFiles(folders.presets),
192
+ ...getAllFiles(folders.blocks),
193
+ ...getAllFiles(folders.sections),
194
+ ...getAllFiles(folders.config),
195
+ ];
196
+
197
+ const typeScriptSchema = [];
198
+
199
+ const snippets = [];
200
+ const layouts = [];
201
+ const sectionsLiquid = [];
202
+ const sectionsSchemaFiles = [];
203
+ const sectionPresetSchemaFiles = [];
204
+ const settingsFiles = [];
205
+ const blocksLiquid = [];
206
+ const blocksSchemaFiles = [];
207
+ const giftCards = [];
208
+ const assets = [];
209
+
210
+ sourceFiles.forEach((filePath) => {
211
+ if (isTypeScriptSchema(filePath)) {
212
+ typeScriptSchema.push(filePath);
213
+ }
214
+ if (isSnippet(filePath)) {
215
+ snippets.push(filePath);
216
+ }
217
+
218
+ if (isLayout(filePath)) {
219
+ layouts.push(filePath);
220
+ }
221
+ if (isSectionLiquid(filePath)) {
222
+ sectionsLiquid.push(filePath);
223
+ }
224
+ if (isSectionSchema(filePath)) {
225
+ sectionsSchemaFiles.push(filePath);
226
+ }
227
+ if (isSectionPresetSchema(filePath)) {
228
+ sectionPresetSchemaFiles.push(filePath);
229
+ }
230
+ if (isBlockLiquid(filePath)) {
231
+ blocksLiquid.push(filePath);
232
+ if (disabled_theme_blocks) {
233
+ snippets.push(filePath);
234
+ }
235
+ }
236
+ if (isBlockSchema(filePath)) {
237
+ blocksSchemaFiles.push(filePath);
238
+ }
239
+ if (isAsset(filePath)) {
240
+ assets.push(filePath);
241
+ }
242
+ if (isSettingsSchema(filePath)) {
243
+ settingsFiles.push(filePath);
244
+ }
245
+ });
246
+
247
+ Object.keys(require.cache)?.forEach((file) => {
248
+ if (/[\\/]@utils[\\/]settings[\\/][^\\/]*\.ts$/gi.test(file)) {
249
+ importFresh(file);
250
+ }
251
+ });
252
+
253
+ config.sources.snippets = snippets;
254
+ config.sources.layouts = layouts;
255
+ config.sources.sectionsLiquid = sectionsLiquid;
256
+ config.sources.sectionsSchemaFiles = sectionsSchemaFiles;
257
+ config.sources.sectionPresetSchemaFiles = sectionPresetSchemaFiles;
258
+ config.sources.blocksLiquid = blocksLiquid;
259
+ config.sources.giftCards = giftCards;
260
+ config.sources.settingsFile = settingsFiles[0];
261
+ config.sources.settingsSchema = settingsFiles?.[0]
262
+ ? (importFresh(settingsFiles[0]) as { settingsSchema: ShopifySettings })?.settingsSchema
263
+ : [];
264
+ config.sources.sectionSchemas = sectionsSchemaFiles.reduce(
265
+ (acc, file) => {
266
+ try {
267
+ const data = importFresh(file);
268
+
269
+ return {
270
+ ...acc,
271
+ ...Object.entries(data).reduce((acc2, [key, val]) => {
272
+ // @ts-ignore
273
+ acc2[key] = { ...val, folder: file.split(/[\\/]/gi).at(-2), path: file };
274
+ return acc2;
275
+ }, {}),
276
+ };
277
+ } catch (err) {
278
+ console.log(chalk.redBright(err.message));
279
+ return acc;
280
+ }
281
+ },
282
+ {} as { [T: string]: ShopifySection }
283
+ );
284
+ config.sources.sectionPresetSchemas = sectionPresetSchemaFiles.reduce(
285
+ (acc, file) => {
286
+ try {
287
+ let data = importFresh(file);
288
+ if (data["default"]) {
289
+ data = data["default"];
290
+ }
291
+ return {
292
+ ...acc,
293
+ ...Object.entries(data).reduce((acc2, [key, val]) => {
294
+ // @ts-ignore
295
+ acc2[key] = { ...val, folder: file.split(/[\\/]/gi).at(-2), path: file };
296
+ return acc2;
297
+ }, {}),
298
+ };
299
+ } catch (err) {
300
+ console.log(chalk.redBright(err.message));
301
+ return acc;
302
+ }
303
+ },
304
+ {} as { [T: string]: ShopifySection }
305
+ );
306
+ config.sources.blockSchemas = blocksSchemaFiles.reduce(
307
+ (acc, file) => {
308
+ try {
309
+ const data = importFresh(file);
310
+
311
+ return {
312
+ ...acc,
313
+ ...Object.entries(data).reduce((acc2, [key, val]) => {
314
+ // @ts-ignore
315
+ acc2[key] = { ...val, folder: file.split(/[\\/]/gi).at(-2), path: file };
316
+ return acc2;
317
+ }, {}),
318
+ };
319
+ } catch (err) {
320
+ console.log(chalk.redBright(err.message));
321
+ return acc;
322
+ }
323
+ },
324
+ {} as { [T: string]: ShopifyBlock }
325
+ );
326
+ };
327
+
328
+ export const getTargets = () => {
329
+ if (config.headless) {
330
+ return;
331
+ }
332
+ const { theme_path } = config;
333
+
334
+ const targetFiles = [
335
+ ...getAllFiles(path.join(theme_path, "assets")),
336
+ ...getAllFiles(path.join(theme_path, "sections")),
337
+ ...getAllFiles(path.join(theme_path, "config")),
338
+ ...getAllFiles(path.join(theme_path, "templates")),
339
+ ];
340
+
341
+ const assets = [];
342
+ const sections = [];
343
+ const settings = [];
344
+ const dynamicJs = [];
345
+ const giftCards = [];
346
+ const sectionGroups = [];
347
+ const configs = [];
348
+ const templates = [];
349
+ const customerTemplates = [];
350
+
351
+ targetFiles.forEach((file) => {
352
+ if (isTargetDynamicJs(file)) {
353
+ dynamicJs.push(file);
354
+ }
355
+ if (!isTargetDynamicJs(file) && /[\\/]assets[\\/][^\\/]*$/gi.test(file)) {
356
+ assets.push(file);
357
+ }
358
+ if (/[\\/]sections[\\/][^\\/]*\.liquid$/gi.test(file)) {
359
+ sections.push(file);
360
+ }
361
+ if (isGiftCard(file)) {
362
+ giftCards.push(file);
363
+ }
364
+ if (/[\\/]sections[\\/][\\/]*\.json$/gi.test(file)) {
365
+ sectionGroups.push(file);
366
+ }
367
+ if (isConfig(file)) {
368
+ configs.push(file);
369
+ }
370
+ if (isTemplate(file)) {
371
+ templates.push(file);
372
+ }
373
+ if (isCustomerTemplate(file)) {
374
+ customerTemplates.push(file);
375
+ }
376
+ if (isSettingsSchema(file)) {
377
+ settings.push(file);
378
+ }
379
+ });
380
+
381
+ config.targets.blocks = getAllFiles(path.join(theme_path, "blocks"));
382
+ config.targets.layout = getAllFiles(path.join(theme_path, "layout"));
383
+ config.targets.locales = getAllFiles(path.join(theme_path, "locales"));
384
+ config.targets.snippets = getAllFiles(path.join(theme_path, "snippets"));
385
+ config.targets.assets = assets;
386
+ config.targets.dynamicJs = dynamicJs;
387
+ config.targets.sections = sections;
388
+ config.targets.settings = settings[0];
389
+ config.targets.giftCards = giftCards;
390
+ config.targets.sectionGroups = sectionGroups;
391
+ config.targets.configs = configs;
392
+ config.targets.templates = templates;
393
+ config.targets.customerTemplates = customerTemplates;
394
+ };
395
+
396
+ export const isTypeScriptSchema = (name: string) =>
397
+ /[\\/]sections[\\/][^\\/]*[\\/]schema.ts$/gi.test(name) ||
398
+ /[\\/]presets[\\/][^\\/]*.ts$/gi.test(name) ||
399
+ /[\\/]blocks[\\/][^\\/]*[\\/]schema.ts$/gi.test(name) ||
400
+ /[\\/]config[\\/]settings_schema\.ts$/gi.test(name) ||
401
+ /[\\/]@utils[\\/]settings[\\/][^\\/]*\.ts$/gi.test(name);
402
+
403
+ export const isSectionLiquid = (name: string) =>
404
+ /[\\/]sections[\\/][^\\/]*[\\/][^.]*\.liquid$/gi.test(name);
405
+
406
+ export const isSectionSchema = (name: string) =>
407
+ /[\\/]sections([\\/])[^\\/]*([\\/])schema\.ts$/gi.test(name);
408
+
409
+ export const isSectionPresetSchema = (name: string) =>
410
+ /[\\/]presets([\\/])[^\\/]*\.ts$/gi.test(name);
411
+
412
+ export const isSectionTs = (name: string) =>
413
+ !isSectionSchema(name) && /[\\/]sections([\\/])[^\\/]*([\\/])[^\\/]*\.ts$/gi.test(name);
414
+
415
+ export const isSettingsSchema = (name: string) =>
416
+ /[\\/]config[\\/]settings_schema\.ts$/gi.test(name) ||
417
+ path.join(name) === path.join(config.folders.config, "settings_schema.ts");
418
+
419
+ export const isAsset = (name: string) =>
420
+ /[\\/]assets[\\/][^\\/]*$/gi.test(name) ||
421
+ /[\\/]snippets[\\/][^\\/]*.js$/gi.test(name) ||
422
+ /[\\/]blocks[\\/][^\\/]*.js$/gi.test(name) ||
423
+ /[\\/]sections[\\/][^\\/]*.js$/gi.test(name);
424
+
425
+ export const isSnippet = (name: string) => {
426
+ return (
427
+ /[\\/]sections[\\/][^\\/]*[\\/][^.]*\.[^.]*\.liquid$/gi.test(name) ||
428
+ /[\\/]blocks[\\/][^\\/]*[\\/][^.]*\.[^.]*\.liquid$/gi.test(name) ||
429
+ /[\\/]snippets[\\/][^\\/]*\.liquid$/gi.test(name)
430
+ );
431
+ };
432
+
433
+ export const isBlockLiquid = (name: string) =>
434
+ /[\\/]blocks[\\/][^\\/]*[\\/][^.]*\.liquid$/gi.test(name);
435
+
436
+ export const isBlockSchema = (name: string) =>
437
+ /[\\/]blocks([\\/])[^\\/]*([\\/])schema.ts$/gi.test(name);
438
+
439
+ export const isBlockTs = (name: string) =>
440
+ !isBlockSchema(name) && /[\\/]blocks([\\/])[^\\/]*([\\/])[^\\/]*?\.ts$/gi.test(name);
441
+
442
+ export const isLayout = (name: string) => {
443
+ return /(?<![\\/](blocks|sections|snippets))[\\/]layout[\\/][^\\/]*\.liquid$/gi.test(name);
444
+ };
445
+
446
+ export const isSectionGroup = (name: string) =>
447
+ /[\\/]templates[\\/]section-groups[\\/][^\\/]*\.json$/gi.test(name);
448
+
449
+ export const isConfig = (name: string) => /[\\/]config[\\/][^\\/]*\.json$/gi.test(name);
450
+
451
+ export const isTemplate = (name: string) => /[\\/]templates[\\/][^\\/]*\.json$/gi.test(name);
452
+
453
+ export const isCustomerTemplate = (name: string) =>
454
+ /[\\/]templates[\\/]customers[\\/][^\\/]*\.json$/gi.test(name);
455
+
456
+ export const isGiftCard = (name: string) => /[\\/]templates[\\/]gift_card\.liquid$/gi.test(name);
457
+
458
+ export const isTargetDynamicJs = (name: string) =>
459
+ /[\\/]assets[\\/](__section--|__block--)[^\\/]*$/gi.test(name);
460
+
461
+ export const isLiquid = (name: string) =>
462
+ isSectionLiquid(name) ||
463
+ isBlockLiquid(name) ||
464
+ isSnippet(name) ||
465
+ isLayout(name) ||
466
+ isGiftCard(name);
@@ -0,0 +1,98 @@
1
+ import { ShopifyHeader, ShopifyParagraph, ShopifySection, ShopifySettings, ShopifySettingsInput } from "../../@types/shopify";
2
+ import { config } from "../../shopify-accelerate-app";
3
+ import { toLocaleFriendlySnakeCase } from "../utils/to-snake-case";
4
+
5
+ export function parseLocales() {
6
+ const { sources } = config;
7
+ const sections = sources.sectionSchemas;
8
+ const blocks = sources.blockSchemas;
9
+ const settings = sources.settingsSchema;
10
+ const entries: { [T: string]: string[] } = {};
11
+
12
+ const mapSettings = (settings: (ShopifySettingsInput | ShopifyHeader | ShopifyParagraph)[]) => {
13
+ settings?.forEach((setting) => {
14
+ if (setting.type === "paragraph" || setting.type === "header") {
15
+ if (setting.content.split(" ").length > 4) {
16
+ return;
17
+ }
18
+ const [key, value] = [toLocaleFriendlySnakeCase(setting.content), setting.content];
19
+ if (entries[key]) {
20
+ entries[key].push(value);
21
+ } else {
22
+ entries[key] = [value];
23
+ }
24
+ return;
25
+ }
26
+
27
+ if (setting?.id) {
28
+ if (setting.type === "color_scheme_group") {
29
+ return;
30
+ }
31
+ if (setting.type === "select" || setting.type === "radio") {
32
+ setting.options.forEach((option, index) => {
33
+ const [key, value] = [toLocaleFriendlySnakeCase(option.label), option.label];
34
+ if (entries[key]) {
35
+ entries[key].push(value);
36
+ } else {
37
+ entries[key] = [value];
38
+ }
39
+ });
40
+ }
41
+ if (setting.label) {
42
+ const [key, value] = [toLocaleFriendlySnakeCase(setting.label), setting.label];
43
+ if (entries[key]) {
44
+ entries[key].push(value);
45
+ } else {
46
+ entries[key] = [value];
47
+ }
48
+ }
49
+
50
+ if (setting.info) {
51
+ if (setting.info.split(" ").length <= 4) {
52
+ const [key, value] = [toLocaleFriendlySnakeCase(setting.info), setting.info];
53
+ if (entries[key]) {
54
+ entries[key].push(value);
55
+ } else {
56
+ entries[key] = [value];
57
+ }
58
+ }
59
+ }
60
+ if ("placeholder" in setting && typeof setting.placeholder === "string") {
61
+ const [key, value] = [
62
+ toLocaleFriendlySnakeCase(setting.placeholder),
63
+ setting.placeholder,
64
+ ];
65
+ if (entries[key]) {
66
+ entries[key].push(value);
67
+ } else {
68
+ entries[key] = [value];
69
+ }
70
+ }
71
+ }
72
+ });
73
+ };
74
+
75
+ Object.values(sections).forEach((section) => {
76
+ const blocks =
77
+ section.blocks?.filter((block) => block.type !== "@app" && block.type !== "@theme") ?? [];
78
+ mapSettings(section.settings);
79
+ blocks.forEach((block) => mapSettings(block.settings));
80
+ });
81
+
82
+ Object.values(blocks).forEach((section) => {
83
+ const blocks =
84
+ section.blocks?.filter((block) => block.type !== "@app" && block.type !== "@theme") ?? [];
85
+ mapSettings(section.settings);
86
+ blocks.forEach((block) => mapSettings(block.settings));
87
+ });
88
+
89
+ settings.forEach((settingsSection) => {
90
+ if (!("settings" in settingsSection)) return;
91
+ mapSettings(settingsSection.settings);
92
+ });
93
+ /* fs.writeFileSync(path.join(process.cwd(), "/test.json"), JSON.stringify(entries, null, 2), {
94
+ encoding: "utf-8",
95
+ });*/
96
+
97
+ config.sources.locale_duplicates = entries;
98
+ }
@@ -0,0 +1,103 @@
1
+ import chalk from "chalk";
2
+ import { exec } from "child_process";
3
+ import fs from "fs";
4
+ import path from "path";
5
+ import { config } from "../../shopify-accelerate-app";
6
+ import { buildTheme } from "../scaffold-theme/build-theme";
7
+ import { generateConfigFiles } from "../scaffold-theme/generate-config-files";
8
+ import { validateCliOptions } from "../validate-cli-options";
9
+
10
+ export const shopifyCliPull = async () => {
11
+ const { store, theme_id, environment, theme_path } = config;
12
+ const cleanThemePath = theme_path?.replace(/^\.\//gi, "")?.replace(/\\/gi, "/");
13
+ let second_attempt = false;
14
+
15
+ await new Promise((resolve, reject) => {
16
+ const interval = setInterval(() => {
17
+ console.log(
18
+ `[${chalk.gray(new Date().toLocaleTimeString())}]: ${chalk.yellowBright(
19
+ `Downloading Theme Files from https://admin.shopify.com/store/${store}/themes/${theme_id}`
20
+ )}`
21
+ );
22
+ }, 1000);
23
+ exec(
24
+ `shopify theme pull --environment ${environment} && cd ${cleanThemePath} && git init && git add . && git commit -m init`,
25
+ async (error, stdout, stderr) => {
26
+ const vcsPath = path.join(process.cwd(), ".idea/vcs.xml");
27
+ const workspace = path.join(process.cwd(), ".idea/workspace.xml");
28
+ if (fs.existsSync(workspace)) {
29
+ if (fs.existsSync(vcsPath)) {
30
+ const vcsContent = fs.readFileSync(vcsPath, { encoding: "utf-8" });
31
+ if (
32
+ !vcsContent.includes(
33
+ `<mapping directory="$PROJECT_DIR$/${cleanThemePath}" vcs="Git" />`
34
+ )
35
+ ) {
36
+ const newVcsContent = vcsContent.replace(
37
+ "</component>",
38
+ ` <mapping directory="$PROJECT_DIR$/${cleanThemePath}" vcs="Git" />\n </component>`
39
+ );
40
+ fs.writeFileSync(vcsPath, newVcsContent);
41
+ }
42
+ } else {
43
+ fs.writeFileSync(
44
+ vcsPath,
45
+ `<?xml version="1.0" encoding="UTF-8"?>
46
+ <project version="4">
47
+ <component name="VcsDirectoryMappings">
48
+ <mapping directory="" vcs="Git" />
49
+ <mapping directory="$PROJECT_DIR$/${cleanThemePath}" vcs="Git" />
50
+ </component>
51
+ </project>`
52
+ );
53
+ }
54
+ }
55
+ if (
56
+ stderr &&
57
+ stderr.includes(`doesn't exist`) &&
58
+ stderr.includes(`Theme`) &&
59
+ !second_attempt
60
+ ) {
61
+ clearInterval(interval);
62
+ second_attempt = true;
63
+ console.log(stderr);
64
+ console.log(
65
+ `[${chalk.gray(new Date().toLocaleTimeString())}]: ${chalk.redBright(
66
+ `Error - Theme not Found`
67
+ )}`
68
+ );
69
+ await validateCliOptions({
70
+ store,
71
+ environment,
72
+ reset_theme_id: true,
73
+ });
74
+ buildTheme();
75
+ generateConfigFiles();
76
+ await shopifyCliPull();
77
+
78
+ resolve(true);
79
+ return;
80
+ }
81
+ if (stderr && stderr.includes(`doesn't exist`) && stderr.includes(`Theme`)) {
82
+ console.log(stderr);
83
+ console.log(
84
+ `[${chalk.gray(new Date().toLocaleTimeString())}]: ${chalk.redBright(
85
+ `Error - Could not initialize the Theme`
86
+ )}`
87
+ );
88
+
89
+ clearInterval(interval);
90
+ resolve(true);
91
+ }
92
+ console.log(
93
+ `[${chalk.gray(new Date().toLocaleTimeString())}]: ${chalk.greenBright(
94
+ `Theme Files & Git Initialized`
95
+ )}`
96
+ );
97
+
98
+ clearInterval(interval);
99
+ resolve(true);
100
+ }
101
+ );
102
+ });
103
+ };
@@ -0,0 +1,8 @@
1
+ module.exports = {
2
+ plugins: {
3
+ "postcss-import": {},
4
+ "tailwindcss/nesting": {},
5
+ tailwindcss: {},
6
+ autoprefixer: {},
7
+ },
8
+ };