@salesforce/storefront-next-dev 0.2.0-alpha.1 → 0.2.0-alpha.2

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.
@@ -12,6 +12,7 @@ import prompts from "prompts";
12
12
  //#region src/create-storefront.ts
13
13
  const DEFAULT_STOREFRONT = "sfcc-storefront";
14
14
  const STOREFRONT_NEXT_GITHUB_URL = "https://github.com/SalesforceCommerceCloud/storefront-next-template";
15
+ const isLocalPath = (template) => template.startsWith("file://") || template.startsWith("/") || template.startsWith("./") || template.startsWith("../");
15
16
  const createStorefront = async (options = {}) => {
16
17
  try {
17
18
  execSync("git --version", { stdio: "ignore" });
@@ -31,6 +32,7 @@ const createStorefront = async (options = {}) => {
31
32
  process.exit(1);
32
33
  }
33
34
  console.log("\n");
35
+ const outputPath = options.outputDir ? path.join(options.outputDir, storefront) : storefront;
34
36
  let template = options.template;
35
37
  if (!template) {
36
38
  template = (await prompts({
@@ -67,30 +69,47 @@ const createStorefront = async (options = {}) => {
67
69
  error("--template-branch cannot be empty.");
68
70
  process.exit(1);
69
71
  }
70
- const cloneArgs = [
71
- "clone",
72
- "--depth",
73
- "1"
74
- ];
75
- if (options.templateBranch) cloneArgs.push("--branch", options.templateBranch);
76
- cloneArgs.push(template, storefront);
77
- execFileSync("git", cloneArgs);
78
- const gitDir = path.join(storefront, ".git");
72
+ if (isLocalPath(template)) {
73
+ const resolvedPath = path.resolve(template.replace("file://", ""));
74
+ if (fs.existsSync(path.join(resolvedPath, ".git"))) {
75
+ const cloneArgs = [
76
+ "clone",
77
+ "--depth",
78
+ "1"
79
+ ];
80
+ if (options.templateBranch) cloneArgs.push("--branch", options.templateBranch);
81
+ cloneArgs.push(resolvedPath, outputPath);
82
+ execFileSync("git", cloneArgs);
83
+ } else fs.copySync(resolvedPath, outputPath, { filter: (src) => {
84
+ const rel = path.relative(resolvedPath, src);
85
+ return rel !== "node_modules" && !rel.startsWith(`node_modules${path.sep}`) && rel !== ".git" && !rel.startsWith(`.git${path.sep}`);
86
+ } });
87
+ } else {
88
+ const cloneArgs = [
89
+ "clone",
90
+ "--depth",
91
+ "1"
92
+ ];
93
+ if (options.templateBranch) cloneArgs.push("--branch", options.templateBranch);
94
+ cloneArgs.push(template, outputPath);
95
+ execFileSync("git", cloneArgs);
96
+ }
97
+ const gitDir = path.join(outputPath, ".git");
79
98
  if (fs.existsSync(gitDir)) fs.rmSync(gitDir, {
80
99
  recursive: true,
81
100
  force: true
82
101
  });
83
- if (template.startsWith("file://") || options.localPackagesDir) {
102
+ if (isLocalPath(template) || options.localPackagesDir) {
84
103
  const templatePath = template.replace("file://", "");
85
- const sourcePackagesDir = options.localPackagesDir || path.dirname(templatePath);
86
104
  await prepareForLocalDev({
87
- projectDirectory: storefront,
88
- sourcePackagesDir
105
+ projectDirectory: outputPath,
106
+ sourcePackagesDir: options.localPackagesDir || path.dirname(templatePath),
107
+ defaults: options.defaults
89
108
  });
90
109
  }
91
110
  console.log("\n");
92
- if (fs.existsSync(path.join(storefront, "src", "extensions", "config.json"))) {
93
- const extensionConfigText = fs.readFileSync(path.join(storefront, "src", "extensions", "config.json"), "utf8");
111
+ if (fs.existsSync(path.join(outputPath, "src", "extensions", "config.json"))) {
112
+ const extensionConfigText = fs.readFileSync(path.join(outputPath, "src", "extensions", "config.json"), "utf8");
94
113
  const extensionConfig = JSON.parse(extensionConfigText);
95
114
  if (extensionConfig.extensions) {
96
115
  try {
@@ -99,7 +118,9 @@ const createStorefront = async (options = {}) => {
99
118
  error(`Extension configuration error: ${e.message}`);
100
119
  process.exit(1);
101
120
  }
102
- const { selectedExtensions } = await prompts({
121
+ let selectedExtensions;
122
+ if (options.defaults) selectedExtensions = Object.keys(extensionConfig.extensions).filter((ext) => extensionConfig.extensions[ext].defaultOn ?? true);
123
+ else ({selectedExtensions} = await prompts({
103
124
  type: "multiselect",
104
125
  name: "selectedExtensions",
105
126
  message: "šŸ”Œ Which extension would you like to enable? (Use arrow keys to select, space to toggle, and enter to confirm.)\n",
@@ -109,7 +130,7 @@ const createStorefront = async (options = {}) => {
109
130
  selected: extensionConfig.extensions[extension].defaultOn ?? true
110
131
  })),
111
132
  instructions: false
112
- });
133
+ }));
113
134
  const resolvedExtensions = resolveDependenciesForMultiple(selectedExtensions, extensionConfig);
114
135
  const selectedSet = new Set(selectedExtensions);
115
136
  const autoAdded = resolvedExtensions.filter((ext) => !selectedSet.has(ext));
@@ -122,17 +143,17 @@ const createStorefront = async (options = {}) => {
122
143
  warn(`${dependentExts.map((ext) => extensionConfig.extensions[ext]?.name || ext).join(", ")} requires ${addedName}. ${addedName} has been automatically added.`);
123
144
  }
124
145
  }
125
- const enabledExtensions = Object.fromEntries(resolvedExtensions.map((ext) => [ext, true]));
126
- trimExtensions(storefront, enabledExtensions, { extensions: extensionConfig.extensions }, options?.verbose || false);
146
+ trimExtensions(outputPath, Object.fromEntries(resolvedExtensions.map((ext) => [ext, true])), { extensions: extensionConfig.extensions }, options?.verbose || false);
127
147
  }
128
148
  }
129
- const configMeta = JSON.parse(fs.readFileSync(path.join(storefront, "src", "config", "config-meta.json"), "utf8"));
130
- const envDefaultPath = path.join(storefront, ".env.default");
149
+ const configMeta = JSON.parse(fs.readFileSync(path.join(outputPath, "src", "config", "config-meta.json"), "utf8"));
150
+ const envDefaultPath = path.join(outputPath, ".env.default");
131
151
  let envDefaultValues = {};
132
152
  if (fs.existsSync(envDefaultPath)) envDefaultValues = dotenv.parse(fs.readFileSync(envDefaultPath, "utf8"));
133
153
  console.log("\nāš™ļø We will now configure your storefront before it will be ready to run.\n");
134
154
  const configOverrides = {};
135
- for (const config of configMeta.configs) {
155
+ for (const config of configMeta.configs) if (options.defaults) configOverrides[config.key] = envDefaultValues[config.key] ?? "";
156
+ else {
136
157
  const answer = await prompts({
137
158
  type: "text",
138
159
  name: config.key,
@@ -141,7 +162,7 @@ const createStorefront = async (options = {}) => {
141
162
  });
142
163
  configOverrides[config.key] = answer[config.key];
143
164
  }
144
- generateEnvFile(storefront, configOverrides);
165
+ generateEnvFile(outputPath, configOverrides);
145
166
  const BANNER = `
146
167
  ╔══════════════════════════════════════════════════════════════════╗
147
168
  ā•‘ CONGRATULATIONS ā•‘
@@ -149,8 +170,8 @@ const createStorefront = async (options = {}) => {
149
170
 
150
171
  šŸŽ‰ Congratulations! Your storefront is ready to use! šŸŽ‰
151
172
  What's next:
152
- - Navigate to the storefront directory: cd ${storefront}
153
- - Install dependencies: pnpm install
173
+ - Navigate to the storefront directory: cd ${outputPath}
174
+ - Install dependencies: ${options.localPackagesDir ? "pnpm install --ignore-workspace" : "pnpm install"}
154
175
  - Build the storefront: pnpm run build
155
176
  - Run the development server: pnpm run dev
156
177
  `;
@@ -192,6 +213,15 @@ var CreateStorefront = class CreateStorefront extends Command {
192
213
  "local-packages-dir": Flags.string({
193
214
  char: "l",
194
215
  description: "Local monorepo packages directory for file:// templates (pre-fills dependency paths)"
216
+ }),
217
+ defaults: Flags.boolean({
218
+ char: "d",
219
+ description: "Accept all defaults without prompting (for CI/automation)",
220
+ default: false
221
+ }),
222
+ "output-dir": Flags.string({
223
+ char: "o",
224
+ description: "Directory where the storefront project will be created"
195
225
  })
196
226
  };
197
227
  async run() {
@@ -201,7 +231,9 @@ var CreateStorefront = class CreateStorefront extends Command {
201
231
  name: flags.name,
202
232
  template: flags.template,
203
233
  templateBranch: flags["template-branch"],
204
- localPackagesDir: flags["local-packages-dir"]
234
+ localPackagesDir: flags["local-packages-dir"],
235
+ defaults: flags.defaults,
236
+ outputDir: flags["output-dir"]
205
237
  });
206
238
  }
207
239
  };
@@ -9,7 +9,7 @@ import prompts from "prompts";
9
9
  * Prompts user for local package paths and replaces workspace:* dependencies with file: references.
10
10
  */
11
11
  async function prepareForLocalDev(options) {
12
- const { projectDirectory, sourcePackagesDir } = options;
12
+ const { projectDirectory, sourcePackagesDir, defaults } = options;
13
13
  const packageJsonPath = path.join(projectDirectory, "package.json");
14
14
  if (!fs.existsSync(packageJsonPath)) throw new Error(`package.json not found in ${projectDirectory}`);
15
15
  const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
@@ -35,15 +35,18 @@ async function prepareForLocalDev(options) {
35
35
  console.log("");
36
36
  const defaultPaths = {};
37
37
  if (sourcePackagesDir) {
38
- defaultPaths["@salesforce/storefront-next-dev"] = path.join(sourcePackagesDir, "storefront-next-dev");
39
- defaultPaths["@salesforce/storefront-next-runtime"] = path.join(sourcePackagesDir, "storefront-next-runtime");
38
+ defaultPaths["@salesforce/storefront-next-dev"] = path.resolve(sourcePackagesDir, "storefront-next-dev");
39
+ defaultPaths["@salesforce/storefront-next-runtime"] = path.resolve(sourcePackagesDir, "storefront-next-runtime");
40
40
  }
41
41
  const resolvedPaths = {};
42
42
  for (const { pkg } of workspaceDeps) {
43
43
  if (resolvedPaths[pkg]) continue;
44
44
  const defaultPath = defaultPaths[pkg] || "";
45
45
  const defaultExists = defaultPath && fs.existsSync(defaultPath);
46
- const { localPath } = await prompts({
46
+ let localPath;
47
+ if (defaults && defaultExists) localPath = defaultPath;
48
+ else if (defaults) warn(`Skipping ${pkg} - default path not found: ${defaultPath}`);
49
+ else ({localPath} = await prompts({
47
50
  type: "text",
48
51
  name: "localPath",
49
52
  message: `šŸ“¦ Path to ${pkg}:`,
@@ -54,7 +57,7 @@ async function prepareForLocalDev(options) {
54
57
  if (!fs.existsSync(path.join(value, "package.json"))) return `No package.json found in: ${value}`;
55
58
  return true;
56
59
  }
57
- });
60
+ }));
58
61
  if (!localPath) {
59
62
  warn(`Skipping ${pkg} - no path provided`);
60
63
  continue;
package/dist/logger.js CHANGED
@@ -3,7 +3,7 @@ import chalk from "chalk";
3
3
  import { createRequire } from "module";
4
4
 
5
5
  //#region package.json
6
- var version = "0.2.0-alpha.1";
6
+ var version = "0.2.0-alpha.2";
7
7
 
8
8
  //#endregion
9
9
  //#region src/utils/logger.ts