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,242 @@
1
+ import path from "path";
2
+ import { ShopifyBlock, ShopifySettingsInput } from "../../@types/shopify";
3
+ import { config } from "../../shopify-accelerate-app";
4
+ import { capitalize } from "../utils/capitalize";
5
+ import { writeCompareFile } from "../utils/fs";
6
+
7
+ export const generateBlocksTypes = () => {
8
+ const { folders, sources } = config;
9
+ const sections = sources.blockSchemas;
10
+
11
+ const blockTypesPath = path.join(folders.types, "blocks.ts");
12
+
13
+ const imports = getImports(sections);
14
+ let sectionUnionType = "export type ThemeBlocks =";
15
+ let typeContent = "";
16
+ for (const key in sections) {
17
+ const schema = sections[key] as ShopifyBlock;
18
+
19
+ typeContent += `${blockToTypes(schema, key)}\n`;
20
+ sectionUnionType += `\n | ${capitalize(key)}Block`;
21
+ }
22
+
23
+ if (!typeContent) return;
24
+
25
+ const finalContent = `${imports + typeContent + sectionUnionType};\n`;
26
+
27
+ writeCompareFile(blockTypesPath, finalContent);
28
+ };
29
+
30
+ export const getImports = (sections: { [T: string]: ShopifyBlock }) => {
31
+ const localTypes = [];
32
+
33
+ const analyseSetting = (setting) => {
34
+ if (setting.type === "richtext") {
35
+ if (localTypes.includes("_BlockTag")) return;
36
+ localTypes.push("_BlockTag");
37
+ }
38
+ if (setting.type === "article") {
39
+ if (localTypes.includes("_Article_liquid")) return;
40
+ localTypes.push("_Article_liquid");
41
+ }
42
+ if (setting.type === "blog") {
43
+ if (localTypes.includes("_Blog_liquid")) return;
44
+ localTypes.push("_Blog_liquid");
45
+ }
46
+ if (setting.type === "collection" && !setting.id.includes("__handle_only")) {
47
+ if (localTypes.includes("_Collection_liquid")) return;
48
+ localTypes.push("_Collection_liquid");
49
+ }
50
+ if (setting.type === "collection_list" && !setting.id.includes("__handle_only")) {
51
+ if (localTypes.includes("_Collection_liquid")) return;
52
+ localTypes.push("_Collection_liquid");
53
+ }
54
+ if (setting.type === "color") {
55
+ if (localTypes.includes("_Color_liquid")) return;
56
+ localTypes.push("_Color_liquid");
57
+ }
58
+ if (setting.type === "image_picker") {
59
+ if (localTypes.includes("_Image_liquid")) return;
60
+ localTypes.push("_Image_liquid");
61
+ }
62
+ if (setting.type === "font_picker") {
63
+ if (localTypes.includes("_Font_liquid")) return;
64
+ localTypes.push("_Font_liquid");
65
+ }
66
+ if (setting.type === "font_picker") {
67
+ if (localTypes.includes("_Font_options")) return;
68
+ localTypes.push("_Font_options");
69
+ }
70
+ if (setting.type === "link_list") {
71
+ if (localTypes.includes("_Linklist_liquid")) return;
72
+ localTypes.push("_Linklist_liquid");
73
+ }
74
+ if (setting.type === "page") {
75
+ if (localTypes.includes("_Page_liquid")) return;
76
+ localTypes.push("_Page_liquid");
77
+ }
78
+ if (setting.type === "product" && !setting.id.includes("__handle_only")) {
79
+ if (localTypes.includes("_Product_liquid")) return;
80
+ localTypes.push("_Product_liquid");
81
+ }
82
+ if (setting.type === "product_list" && !setting.id.includes("__handle_only")) {
83
+ if (localTypes.includes("_Product_liquid")) return;
84
+ localTypes.push("_Product_liquid");
85
+ }
86
+ if (setting.type === "video") {
87
+ if (localTypes.includes("_Video_liquid")) return;
88
+ localTypes.push("_Video_liquid");
89
+ }
90
+ };
91
+
92
+ for (const key in sections) {
93
+ const schema = sections[key];
94
+
95
+ schema.settings?.forEach(analyseSetting, localTypes);
96
+ schema.blocks?.forEach((block) => {
97
+ block?.settings?.forEach(analyseSetting, localTypes);
98
+ });
99
+ }
100
+
101
+ if (localTypes.length) {
102
+ return `import { ${localTypes.join(", ")} } from "./shopify";\n\n`;
103
+ }
104
+ return ``;
105
+ };
106
+
107
+ export const blockToTypes = (section, key) => {
108
+ const filename = section.folder;
109
+ const arr = [];
110
+ const settings: ShopifySettingsInput[] = section.settings
111
+ ?.filter((s) => s.type !== "header" && s.type !== "paragraph")
112
+ .sort((a, b) => (a.id > b.id ? 1 : a.id < b.id ? -1 : 0));
113
+
114
+ arr.push(`export type ${capitalize(key)}Block = {`);
115
+ if (section.blocks?.some((block) => block.type === "@theme")) {
116
+ arr.push(` blocks: ThemeBlocks[];`);
117
+ }
118
+ arr.push(` id${config.headless ? "?" : ""}: string;`);
119
+ if (settings?.length) {
120
+ arr.push(` settings: {`);
121
+ arr.push(
122
+ settings
123
+ .map(
124
+ (setting) =>
125
+ ` /** Input type: ${setting.type} */\n ` +
126
+ `${/[^\w_]/gi.test(setting.id) ? `"${setting.id}"` : `${setting.id}`}${getSettingsType(
127
+ setting
128
+ )};`
129
+ )
130
+ .sort((a, b) => {
131
+ const aX = a.split("\n")[1];
132
+ const bX = b.split("\n")[1];
133
+ if (aX.includes("?") && !bX.includes("?")) {
134
+ return 1;
135
+ } else if (!aX.includes("?") && bX.includes("?")) {
136
+ return -1;
137
+ } else if (aX > bX) {
138
+ return 1;
139
+ } else if (aX < bX) {
140
+ return -1;
141
+ } else {
142
+ return 0;
143
+ }
144
+ })
145
+ .join("\n")
146
+ );
147
+ arr.push(` };`);
148
+ }
149
+ arr.push(` type: "${filename}";`);
150
+ arr.push(`};`);
151
+
152
+ arr.push("");
153
+ return arr.join("\n");
154
+ };
155
+
156
+ export const getSettingsType = (setting: ShopifySettingsInput) => {
157
+ switch (setting.type) {
158
+ case "article":
159
+ return "?: _Article_liquid | string";
160
+ case "checkbox":
161
+ return ": boolean";
162
+ case "number":
163
+ return "?: number";
164
+ case "radio":
165
+ return `: ${setting.options.map(({ value }) => `"${value}"`).join(" | ")}`;
166
+ case "range":
167
+ return ": number";
168
+ case "select":
169
+ return `: ${setting.options.map(({ value }) => `"${value}"`).join(" | ")}`;
170
+ case "text":
171
+ return "?: string";
172
+ case "textarea":
173
+ return "?: string";
174
+ case "blog":
175
+ return "?: _Blog_liquid | string";
176
+ case "collection": {
177
+ if (setting.id.includes("__handle_only")) {
178
+ return "?: string";
179
+ }
180
+ return "?: _Collection_liquid";
181
+ }
182
+ case "collection_list": {
183
+ if (setting.id.includes("__handle_only")) {
184
+ return "?: string[]";
185
+ }
186
+ return "?: _Collection_liquid[]";
187
+ }
188
+ case "color":
189
+ return "?: _Color_liquid | string";
190
+ case "color_background":
191
+ return "?: string";
192
+ case "font_picker":
193
+ return ": _Font_liquid | _Font_options";
194
+ case "html":
195
+ return "?: string";
196
+ case "image_picker":
197
+ return "?: _Image_liquid | string";
198
+ case "link_list":
199
+ return "?: _Linklist_liquid";
200
+ case "liquid":
201
+ return "?: string";
202
+ case "page":
203
+ return "?: _Page_liquid | string";
204
+ case "product": {
205
+ if (setting.id.includes("__handle_only")) {
206
+ return "?: string";
207
+ }
208
+ return "?: _Product_liquid";
209
+ }
210
+ case "product_list": {
211
+ if (setting.id.includes("__handle_only")) {
212
+ return "?: string[]";
213
+ }
214
+ return "?: _Product_liquid[]";
215
+ }
216
+ case "color_scheme_group":
217
+ return `?: {\n [T:string]: {${setting.definition
218
+ .map((option) => {
219
+ if ("id" in option) {
220
+ return `\n ${option.id}: string;`;
221
+ }
222
+ return "";
223
+ })
224
+ .join("")}\n }\n }`;
225
+ case "richtext":
226
+ return "?: `<${_BlockTag}${string}</${_BlockTag}>`";
227
+ case "inline_richtext":
228
+ return "?: string";
229
+ case "url":
230
+ return "?: string";
231
+ case "video":
232
+ return "?: _Video_liquid";
233
+ case "video_url":
234
+ return "?: `${string}youtube${string}` | `${string}vimeo${string}`";
235
+ case "font":
236
+ return "?: string";
237
+ case "color_scheme":
238
+ return "?: string";
239
+ case "text_alignment":
240
+ return `: "left" | "center" | "right"`;
241
+ }
242
+ };
@@ -0,0 +1,34 @@
1
+ import fs from "fs";
2
+ import path from "path";
3
+ import { config, root_dir } from "../../shopify-accelerate-app";
4
+ import { writeOnlyNew } from "../utils/fs";
5
+
6
+ export const generateConfigFiles = () => {
7
+ const { theme_path, sources } = config;
8
+
9
+ sources.sectionGroups.forEach((file) => {
10
+ const fileName = file.split(/[\\/]/gi).at(-1);
11
+ const targetPath = path.join(process.cwd(), theme_path, "sections", fileName);
12
+ const rawContent = fs.readFileSync(file, { encoding: "utf-8" });
13
+ writeOnlyNew(targetPath, rawContent);
14
+ });
15
+
16
+ sources.configs.forEach((file) => {
17
+ const fileName = file.split(/[\\/]/gi).at(-1);
18
+ const targetPath = path.join(process.cwd(), theme_path, "config", fileName);
19
+ const rawContent = fs.readFileSync(file, { encoding: "utf-8" });
20
+ writeOnlyNew(targetPath, rawContent);
21
+ });
22
+ sources.templates.forEach((file) => {
23
+ const fileName = file.split(/[\\/]/gi).at(-1);
24
+ const targetPath = path.join(process.cwd(), theme_path, "templates", fileName);
25
+ const rawContent = fs.readFileSync(file, { encoding: "utf-8" });
26
+ writeOnlyNew(targetPath, rawContent);
27
+ });
28
+ sources.customerTemplates.forEach((file) => {
29
+ const fileName = file.split(/[\\/]/gi).at(-1);
30
+ const targetPath = path.join(process.cwd(), theme_path, "templates/customers", fileName);
31
+ const rawContent = fs.readFileSync(file, { encoding: "utf-8" });
32
+ writeOnlyNew(targetPath, rawContent);
33
+ });
34
+ };