@salesforce/storefront-next-dev 0.1.1 → 0.2.0-alpha.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 (50) hide show
  1. package/README.md +45 -36
  2. package/bin/run.js +12 -0
  3. package/dist/bundle.js +83 -0
  4. package/dist/cartridge-services/index.d.ts +2 -26
  5. package/dist/cartridge-services/index.d.ts.map +1 -1
  6. package/dist/cartridge-services/index.js +3 -336
  7. package/dist/cartridge-services/index.js.map +1 -1
  8. package/dist/commands/create-bundle.js +107 -0
  9. package/dist/commands/create-instructions.js +174 -0
  10. package/dist/commands/create-storefront.js +210 -0
  11. package/dist/commands/deploy-cartridge.js +52 -0
  12. package/dist/commands/dev.js +122 -0
  13. package/dist/commands/extensions/create.js +38 -0
  14. package/dist/commands/extensions/install.js +44 -0
  15. package/dist/commands/extensions/list.js +21 -0
  16. package/dist/commands/extensions/remove.js +38 -0
  17. package/dist/commands/generate-cartridge.js +35 -0
  18. package/dist/commands/prepare-local.js +30 -0
  19. package/dist/commands/preview.js +101 -0
  20. package/dist/commands/push.js +139 -0
  21. package/dist/config.js +87 -0
  22. package/dist/configs/react-router.config.js +3 -1
  23. package/dist/configs/react-router.config.js.map +1 -1
  24. package/dist/dependency-utils.js +314 -0
  25. package/dist/entry/client.d.ts +1 -0
  26. package/dist/entry/client.js +28 -0
  27. package/dist/entry/client.js.map +1 -0
  28. package/dist/entry/server.d.ts +15 -0
  29. package/dist/entry/server.d.ts.map +1 -0
  30. package/dist/entry/server.js +35 -0
  31. package/dist/entry/server.js.map +1 -0
  32. package/dist/flags.js +11 -0
  33. package/dist/generate-cartridge.js +620 -0
  34. package/dist/hooks/init.js +47 -0
  35. package/dist/index.d.ts +9 -29
  36. package/dist/index.d.ts.map +1 -1
  37. package/dist/index.js +413 -621
  38. package/dist/index.js.map +1 -1
  39. package/dist/local-dev-setup.js +176 -0
  40. package/dist/logger.js +105 -0
  41. package/dist/manage-extensions.js +329 -0
  42. package/dist/mrt/ssr.mjs +3 -3
  43. package/dist/mrt/ssr.mjs.map +1 -1
  44. package/dist/mrt/streamingHandler.mjs +4 -4
  45. package/dist/mrt/streamingHandler.mjs.map +1 -1
  46. package/dist/server.js +425 -0
  47. package/dist/utils.js +126 -0
  48. package/package.json +44 -9
  49. package/dist/cli.js +0 -3393
  50. /package/{LICENSE.txt → LICENSE} +0 -0
@@ -0,0 +1,210 @@
1
+ import { c as warn, n as error } from "../logger.js";
2
+ import { t as generateEnvFile } from "../utils.js";
3
+ import { a as trimExtensions, i as validateNoCycles, n as resolveDependenciesForMultiple } from "../dependency-utils.js";
4
+ import { t as prepareForLocalDev } from "../local-dev-setup.js";
5
+ import { Command, Flags } from "@oclif/core";
6
+ import { execFileSync, execSync } from "child_process";
7
+ import path from "path";
8
+ import fs from "fs-extra";
9
+ import dotenv from "dotenv";
10
+ import prompts from "prompts";
11
+
12
+ //#region src/create-storefront.ts
13
+ const DEFAULT_STOREFRONT = "sfcc-storefront";
14
+ const STOREFRONT_NEXT_GITHUB_URL = "https://github.com/SalesforceCommerceCloud/storefront-next-template";
15
+ const createStorefront = async (options = {}) => {
16
+ try {
17
+ execSync("git --version", { stdio: "ignore" });
18
+ } catch (e) {
19
+ error(`❌ git isn't installed or found in your PATH. Install git before running this command: ${String(e)}`);
20
+ process.exit(1);
21
+ }
22
+ let storefront = options.name;
23
+ if (!storefront) storefront = (await prompts({
24
+ type: "text",
25
+ name: "storefront",
26
+ message: "🏪 What would you like to name your storefront?\n",
27
+ initial: DEFAULT_STOREFRONT
28
+ })).storefront;
29
+ if (!storefront) {
30
+ error("Storefront name is required.");
31
+ process.exit(1);
32
+ }
33
+ console.log("\n");
34
+ let template = options.template;
35
+ if (!template) {
36
+ template = (await prompts({
37
+ type: "select",
38
+ name: "template",
39
+ message: "📄 Which template would you like to use for your storefront?\n",
40
+ choices: [{
41
+ title: "Salesforce B2C Commerce Retail Storefront",
42
+ value: STOREFRONT_NEXT_GITHUB_URL
43
+ }, {
44
+ title: "A different template (I will provide the Github URL)",
45
+ value: "custom"
46
+ }]
47
+ })).template;
48
+ console.log("\n");
49
+ if (template === "custom") {
50
+ const { githubUrl } = await prompts({
51
+ type: "text",
52
+ name: "githubUrl",
53
+ message: "🌐 What is the Github URL for your template?\n"
54
+ });
55
+ if (!githubUrl) {
56
+ error("Github URL is required.");
57
+ process.exit(1);
58
+ }
59
+ template = githubUrl;
60
+ }
61
+ }
62
+ if (!template) {
63
+ error("Template is required.");
64
+ process.exit(1);
65
+ }
66
+ if (options.templateBranch !== void 0 && options.templateBranch.trim() === "") {
67
+ error("--template-branch cannot be empty.");
68
+ process.exit(1);
69
+ }
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");
79
+ if (fs.existsSync(gitDir)) fs.rmSync(gitDir, {
80
+ recursive: true,
81
+ force: true
82
+ });
83
+ if (template.startsWith("file://") || options.localPackagesDir) {
84
+ const templatePath = template.replace("file://", "");
85
+ const sourcePackagesDir = options.localPackagesDir || path.dirname(templatePath);
86
+ await prepareForLocalDev({
87
+ projectDirectory: storefront,
88
+ sourcePackagesDir
89
+ });
90
+ }
91
+ 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");
94
+ const extensionConfig = JSON.parse(extensionConfigText);
95
+ if (extensionConfig.extensions) {
96
+ try {
97
+ validateNoCycles(extensionConfig);
98
+ } catch (e) {
99
+ error(`Extension configuration error: ${e.message}`);
100
+ process.exit(1);
101
+ }
102
+ const { selectedExtensions } = await prompts({
103
+ type: "multiselect",
104
+ name: "selectedExtensions",
105
+ message: "🔌 Which extension would you like to enable? (Use arrow keys to select, space to toggle, and enter to confirm.)\n",
106
+ choices: Object.keys(extensionConfig.extensions).map((extension) => ({
107
+ title: `${extensionConfig.extensions[extension].name} - ${extensionConfig.extensions[extension].description}`,
108
+ value: extension,
109
+ selected: extensionConfig.extensions[extension].defaultOn ?? true
110
+ })),
111
+ instructions: false
112
+ });
113
+ const resolvedExtensions = resolveDependenciesForMultiple(selectedExtensions, extensionConfig);
114
+ const selectedSet = new Set(selectedExtensions);
115
+ const autoAdded = resolvedExtensions.filter((ext) => !selectedSet.has(ext));
116
+ if (autoAdded.length > 0) for (const addedExt of autoAdded) {
117
+ const dependentExts = selectedExtensions.filter((selected) => {
118
+ return (extensionConfig.extensions[selected]?.dependencies || []).includes(addedExt) || resolvedExtensions.indexOf(addedExt) < resolvedExtensions.indexOf(selected);
119
+ });
120
+ if (dependentExts.length > 0) {
121
+ const addedName = extensionConfig.extensions[addedExt]?.name || addedExt;
122
+ warn(`${dependentExts.map((ext) => extensionConfig.extensions[ext]?.name || ext).join(", ")} requires ${addedName}. ${addedName} has been automatically added.`);
123
+ }
124
+ }
125
+ const enabledExtensions = Object.fromEntries(resolvedExtensions.map((ext) => [ext, true]));
126
+ trimExtensions(storefront, enabledExtensions, { extensions: extensionConfig.extensions }, options?.verbose || false);
127
+ }
128
+ }
129
+ const configMeta = JSON.parse(fs.readFileSync(path.join(storefront, "src", "config", "config-meta.json"), "utf8"));
130
+ const envDefaultPath = path.join(storefront, ".env.default");
131
+ let envDefaultValues = {};
132
+ if (fs.existsSync(envDefaultPath)) envDefaultValues = dotenv.parse(fs.readFileSync(envDefaultPath, "utf8"));
133
+ console.log("\n⚙️ We will now configure your storefront before it will be ready to run.\n");
134
+ const configOverrides = {};
135
+ for (const config of configMeta.configs) {
136
+ const answer = await prompts({
137
+ type: "text",
138
+ name: config.key,
139
+ message: `What is the value for ${config.name}? (default: ${envDefaultValues[config.key]})\n`,
140
+ initial: envDefaultValues[config.key] ?? ""
141
+ });
142
+ configOverrides[config.key] = answer[config.key];
143
+ }
144
+ generateEnvFile(storefront, configOverrides);
145
+ const BANNER = `
146
+ ╔══════════════════════════════════════════════════════════════════╗
147
+ ║ CONGRATULATIONS ║
148
+ ╚══════════════════════════════════════════════════════════════════╝
149
+
150
+ 🎉 Congratulations! Your storefront is ready to use! 🎉
151
+ What's next:
152
+ - Navigate to the storefront directory: cd ${storefront}
153
+ - Install dependencies: pnpm install
154
+ - Build the storefront: pnpm run build
155
+ - Run the development server: pnpm run dev
156
+ `;
157
+ console.log(BANNER);
158
+ };
159
+
160
+ //#endregion
161
+ //#region src/commands/create-storefront.ts
162
+ /**
163
+ * Create storefront command - creates a new storefront project from template.
164
+ */
165
+ var CreateStorefront = class CreateStorefront extends Command {
166
+ static description = "Create a storefront project";
167
+ static examples = [
168
+ "<%= config.bin %> <%= command.id %>",
169
+ "<%= config.bin %> <%= command.id %> -v",
170
+ "<%= config.bin %> <%= command.id %> -n my-storefront -t https://github.com/org/template -b release-0.2.x",
171
+ "<%= config.bin %> <%= command.id %> -n my-storefront -t /path/to/local/template",
172
+ "<%= config.bin %> <%= command.id %> -l /path/to/monorepo/packages"
173
+ ];
174
+ static flags = {
175
+ verbose: Flags.boolean({
176
+ char: "v",
177
+ description: "Verbose mode",
178
+ default: false
179
+ }),
180
+ name: Flags.string({
181
+ char: "n",
182
+ description: "Storefront project name"
183
+ }),
184
+ template: Flags.string({
185
+ char: "t",
186
+ description: "Template repository to use for the storefront (GitHub URL or local path)"
187
+ }),
188
+ "template-branch": Flags.string({
189
+ char: "b",
190
+ description: "Branch or tag to clone from the template repository"
191
+ }),
192
+ "local-packages-dir": Flags.string({
193
+ char: "l",
194
+ description: "Local monorepo packages directory for file:// templates (pre-fills dependency paths)"
195
+ })
196
+ };
197
+ async run() {
198
+ const { flags } = await this.parse(CreateStorefront);
199
+ await createStorefront({
200
+ verbose: flags.verbose,
201
+ name: flags.name,
202
+ template: flags.template,
203
+ templateBranch: flags["template-branch"],
204
+ localPackagesDir: flags["local-packages-dir"]
205
+ });
206
+ }
207
+ };
208
+
209
+ //#endregion
210
+ export { CreateStorefront as default };
@@ -0,0 +1,52 @@
1
+ import { i as SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR, r as SFNEXT_BASE_CARTRIDGE_NAME, t as CARTRIDGES_BASE_DIR } from "../config.js";
2
+ import path from "path";
3
+ import fs from "fs-extra";
4
+ import { InstanceCommand } from "@salesforce/b2c-tooling-sdk/cli";
5
+ import { uploadCartridges } from "@salesforce/b2c-tooling-sdk/operations/code";
6
+
7
+ //#region src/commands/deploy-cartridge.ts
8
+ /**
9
+ * Deploy cartridge command - deploys the Page Designer metadata cartridge to a B2C instance.
10
+ *
11
+ * Inherits all B2C instance flags from InstanceCommand:
12
+ * - --server/-s: B2C instance hostname (env: SFCC_SERVER)
13
+ * - --code-version/-v: Code version (env: SFCC_CODE_VERSION)
14
+ * - --username/-u: Basic auth username (env: SFCC_USERNAME)
15
+ * - --password/-p: Basic auth password (env: SFCC_PASSWORD)
16
+ * - --client-id: OAuth client ID (env: SFCC_CLIENT_ID)
17
+ * - --client-secret: OAuth client secret (env: SFCC_CLIENT_SECRET)
18
+ * - --webdav-server: Separate WebDAV hostname (env: SFCC_WEBDAV_SERVER)
19
+ * - --config: Path to dw.json config file (env: SFCC_CONFIG)
20
+ * - --instance/-i: Named instance from config (env: SFCC_INSTANCE)
21
+ */
22
+ var Deploy = class Deploy extends InstanceCommand {
23
+ static description = "Deploy cartridge to B2C Commerce Cloud instance";
24
+ static examples = [
25
+ "<%= config.bin %> <%= command.id %>",
26
+ "<%= config.bin %> <%= command.id %> --project-directory ./my-project",
27
+ "<%= config.bin %> <%= command.id %> -s my-sandbox.dx.commercecloud.salesforce.com",
28
+ "<%= config.bin %> <%= command.id %> --code-version staging"
29
+ ];
30
+ static flags = { ...InstanceCommand.baseFlags };
31
+ async run() {
32
+ const { flags } = await this.parse(Deploy);
33
+ const projectDirectory = flags["project-directory"] || process.cwd();
34
+ if (!fs.existsSync(projectDirectory)) this.error(`Project directory doesn't exist: ${projectDirectory}`);
35
+ const metadataDir = path.join(projectDirectory, CARTRIDGES_BASE_DIR, SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR);
36
+ if (!fs.existsSync(metadataDir)) this.error(`Metadata directory doesn't exist: ${metadataDir}. Run 'sfnext generate-cartridge' first.`);
37
+ this.requireServer();
38
+ this.requireCodeVersion();
39
+ this.requireWebDavCredentials();
40
+ const cartridges = [{
41
+ name: SFNEXT_BASE_CARTRIDGE_NAME,
42
+ src: path.join(projectDirectory, CARTRIDGES_BASE_DIR, SFNEXT_BASE_CARTRIDGE_NAME),
43
+ dest: SFNEXT_BASE_CARTRIDGE_NAME
44
+ }];
45
+ this.log(`Deploying cartridge "${SFNEXT_BASE_CARTRIDGE_NAME}" to code version "${this.resolvedConfig.values.codeVersion}"...`);
46
+ await uploadCartridges(this.instance, cartridges);
47
+ this.log(`Code deployed to version "${this.resolvedConfig.values.codeVersion}" successfully!`);
48
+ }
49
+ };
50
+
51
+ //#endregion
52
+ export { Deploy as default };
@@ -0,0 +1,122 @@
1
+ import { a as printServerInfo, i as printServerConfig, o as printShutdownMessage } from "../logger.js";
2
+ import { c as loadEnvFile } from "../utils.js";
3
+ import { n as getCommerceCloudApiUrl, r as loadProjectConfig, t as createServer$2 } from "../server.js";
4
+ import { t as commonFlags } from "../flags.js";
5
+ import { Command, Flags } from "@oclif/core";
6
+ import path from "path";
7
+ import { createServer } from "node:http";
8
+ import { createServer as createServer$1 } from "vite";
9
+
10
+ //#region src/plugins/workspace.ts
11
+ /**
12
+ * Returns workspace-specific HMR configuration when running behind a workspace proxy.
13
+ *
14
+ * In workspace environments the OAuth2 proxy for the dev server's port is already
15
+ * authenticated, so routing HMR WebSocket through the same HTTP server means it
16
+ * shares the same proxy port and OAuth2 session. A separate port (e.g. port-8000)
17
+ * would require its own OAuth2 login and return a 302 redirect that WebSocket
18
+ * clients cannot follow.
19
+ *
20
+ * This is exported separately from the plugin because it requires the `httpServer`
21
+ * reference created in `dev.ts`.
22
+ *
23
+ * @param httpServer - The Node HTTP server to attach the HMR WebSocket to.
24
+ *
25
+ * Environment variables:
26
+ * - `EXTERNAL_DOMAIN_NAME` — The external hostname for the workspace proxy.
27
+ * When it does not start with "localhost", workspace proxy mode is assumed.
28
+ */
29
+ function getWorkspaceHmrConfig(httpServer) {
30
+ const externalDomain = process.env.EXTERNAL_DOMAIN_NAME;
31
+ if (!externalDomain || externalDomain.startsWith("localhost")) return void 0;
32
+ return {
33
+ protocol: "wss",
34
+ host: externalDomain,
35
+ clientPort: 443,
36
+ server: httpServer
37
+ };
38
+ }
39
+
40
+ //#endregion
41
+ //#region src/lib/dev.ts
42
+ /**
43
+ * Start the development server with Vite in middleware mode
44
+ */
45
+ async function dev(options = {}) {
46
+ const startTime = Date.now();
47
+ const projectDir = path.resolve(options.projectDirectory || process.cwd());
48
+ const port = options.port || 5173;
49
+ process.env.NODE_ENV = process.env.NODE_ENV ?? "development";
50
+ loadEnvFile(projectDir);
51
+ process.env.EXTERNAL_DOMAIN_NAME = process.env.EXTERNAL_DOMAIN_NAME ?? `localhost:${port}`;
52
+ const config = await loadProjectConfig(projectDir);
53
+ const httpServer = createServer();
54
+ const hmr = getWorkspaceHmrConfig(httpServer);
55
+ const vite = await createServer$1({
56
+ root: projectDir,
57
+ server: {
58
+ middlewareMode: true,
59
+ ...hmr && { hmr }
60
+ }
61
+ });
62
+ const app = await createServer$2({
63
+ mode: "development",
64
+ projectDirectory: projectDir,
65
+ config,
66
+ port,
67
+ vite
68
+ });
69
+ httpServer.on("request", app);
70
+ httpServer.listen(port, () => {
71
+ printServerInfo("development", port, startTime, projectDir);
72
+ printServerConfig({
73
+ mode: "development",
74
+ port,
75
+ enableProxy: true,
76
+ enableStaticServing: false,
77
+ enableCompression: false,
78
+ proxyPath: config.commerce.api.proxy,
79
+ proxyHost: getCommerceCloudApiUrl(config.commerce.api.shortCode, config.commerce.api.proxyHost),
80
+ shortCode: config.commerce.api.shortCode,
81
+ organizationId: config.commerce.api.organizationId,
82
+ clientId: config.commerce.api.clientId,
83
+ siteId: config.commerce.api.siteId
84
+ });
85
+ });
86
+ ["SIGTERM", "SIGINT"].forEach((signal) => {
87
+ process.once(signal, () => {
88
+ printShutdownMessage();
89
+ httpServer.close(() => {
90
+ vite.close();
91
+ process.exit(0);
92
+ });
93
+ });
94
+ });
95
+ }
96
+
97
+ //#endregion
98
+ //#region src/commands/dev.ts
99
+ /**
100
+ * Dev server command - starts the Vite development server with SSR.
101
+ */
102
+ var Dev = class Dev extends Command {
103
+ static description = "Start Vite development server with SSR";
104
+ static examples = ["<%= config.bin %> <%= command.id %>", "<%= config.bin %> <%= command.id %> -d ./my-project -p 3000"];
105
+ static flags = {
106
+ ...commonFlags,
107
+ port: Flags.integer({
108
+ char: "p",
109
+ description: "Port number (default: 5173)"
110
+ })
111
+ };
112
+ async run() {
113
+ const { flags } = await this.parse(Dev);
114
+ await dev({
115
+ projectDirectory: flags["project-directory"],
116
+ port: flags.port
117
+ });
118
+ }
119
+ };
120
+
121
+ //#endregion
122
+ export { Dev as default };
@@ -0,0 +1,38 @@
1
+ import "../../dependency-utils.js";
2
+ import { t as createExtension } from "../../manage-extensions.js";
3
+ import { Command, Flags } from "@oclif/core";
4
+
5
+ //#region src/commands/extensions/create.ts
6
+ /**
7
+ * Create extension command - creates a new extension scaffold in a storefront project.
8
+ */
9
+ var Create = class Create extends Command {
10
+ static description = "Create a new extension scaffold in a storefront project";
11
+ static examples = ["<%= config.bin %> <%= command.id %> -n \"My Extension\"", "<%= config.bin %> <%= command.id %> -p ./my-project -n \"Store Locator\" -d \"Adds store locator functionality\""];
12
+ static flags = {
13
+ "project-directory": Flags.string({
14
+ char: "p",
15
+ description: "Target project directory",
16
+ default: process.cwd()
17
+ }),
18
+ name: Flags.string({
19
+ char: "n",
20
+ description: "Name of the extension to create (e.g., \"My Extension\")"
21
+ }),
22
+ description: Flags.string({
23
+ char: "d",
24
+ description: "Description of the extension"
25
+ })
26
+ };
27
+ async run() {
28
+ const { flags } = await this.parse(Create);
29
+ await createExtension({
30
+ projectDirectory: flags["project-directory"],
31
+ name: flags.name ?? "",
32
+ description: flags.description ?? ""
33
+ });
34
+ }
35
+ };
36
+
37
+ //#endregion
38
+ export { Create as default };
@@ -0,0 +1,44 @@
1
+ import "../../dependency-utils.js";
2
+ import { t as commonFlags } from "../../flags.js";
3
+ import { r as manageExtensions } from "../../manage-extensions.js";
4
+ import { Command, Flags } from "@oclif/core";
5
+
6
+ //#region src/commands/extensions/install.ts
7
+ const DEFAULT_TEMPLATE_GIT_URL = process.env.DEFAULT_TEMPLATE_GIT_URL || "https://github.com/SalesforceCommerceCloud/storefront-next-template.git";
8
+ /**
9
+ * Install extension command - installs an extension into a storefront project.
10
+ */
11
+ var Install = class Install extends Command {
12
+ static description = "Install an extension into a storefront project";
13
+ static examples = ["<%= config.bin %> <%= command.id %> -e SFDC_EXT_STORE_LOCATOR", "<%= config.bin %> <%= command.id %> -d ./my-project -e SFDC_EXT_THEME_SWITCHER"];
14
+ static flags = {
15
+ ...commonFlags,
16
+ extension: Flags.string({
17
+ char: "e",
18
+ description: "Extension marker value (e.g. SFDC_EXT_STORE_LOCATOR)"
19
+ }),
20
+ "source-git-url": Flags.string({
21
+ char: "s",
22
+ description: "Git URL of the source template project",
23
+ default: DEFAULT_TEMPLATE_GIT_URL
24
+ }),
25
+ verbose: Flags.boolean({
26
+ char: "v",
27
+ description: "Verbose mode",
28
+ default: false
29
+ })
30
+ };
31
+ async run() {
32
+ const { flags } = await this.parse(Install);
33
+ await manageExtensions({
34
+ projectDirectory: flags["project-directory"],
35
+ install: true,
36
+ extensions: flags.extension ? [flags.extension] : void 0,
37
+ sourceGitUrl: flags["source-git-url"],
38
+ verbose: flags.verbose
39
+ });
40
+ }
41
+ };
42
+
43
+ //#endregion
44
+ export { Install as default };
@@ -0,0 +1,21 @@
1
+ import "../../dependency-utils.js";
2
+ import { t as commonFlags } from "../../flags.js";
3
+ import { n as listExtensions } from "../../manage-extensions.js";
4
+ import { Command } from "@oclif/core";
5
+
6
+ //#region src/commands/extensions/list.ts
7
+ /**
8
+ * List extensions command - lists all installed extensions in a storefront project.
9
+ */
10
+ var List = class List extends Command {
11
+ static description = "List all installed extensions in a storefront project";
12
+ static examples = ["<%= config.bin %> <%= command.id %>", "<%= config.bin %> <%= command.id %> -d ./my-project"];
13
+ static flags = { ...commonFlags };
14
+ async run() {
15
+ const { flags } = await this.parse(List);
16
+ listExtensions({ projectDirectory: flags["project-directory"] });
17
+ }
18
+ };
19
+
20
+ //#endregion
21
+ export { List as default };
@@ -0,0 +1,38 @@
1
+ import "../../dependency-utils.js";
2
+ import { t as commonFlags } from "../../flags.js";
3
+ import { r as manageExtensions } from "../../manage-extensions.js";
4
+ import { Command, Flags } from "@oclif/core";
5
+
6
+ //#region src/commands/extensions/remove.ts
7
+ /**
8
+ * Remove extension command - removes one or more extensions from a storefront project.
9
+ */
10
+ var Remove = class Remove extends Command {
11
+ static description = "Remove one or more installed extensions from a storefront project";
12
+ static examples = ["<%= config.bin %> <%= command.id %> -e SFDC_EXT_STORE_LOCATOR", "<%= config.bin %> <%= command.id %> -e SFDC_EXT_STORE_LOCATOR,SFDC_EXT_THEME_SWITCHER"];
13
+ static flags = {
14
+ ...commonFlags,
15
+ extensions: Flags.string({
16
+ char: "e",
17
+ description: "Comma-separated list of extension marker values (e.g. SFDC_EXT_STORE_LOCATOR,SFDC_EXT_THEME_SWITCHER)"
18
+ }),
19
+ verbose: Flags.boolean({
20
+ char: "v",
21
+ description: "Verbose mode",
22
+ default: false
23
+ })
24
+ };
25
+ async run() {
26
+ const { flags } = await this.parse(Remove);
27
+ const extensions = flags.extensions ? flags.extensions.split(",").map((e) => e.trim()) : void 0;
28
+ await manageExtensions({
29
+ projectDirectory: flags["project-directory"],
30
+ uninstall: true,
31
+ extensions,
32
+ verbose: flags.verbose
33
+ });
34
+ }
35
+ };
36
+
37
+ //#endregion
38
+ export { Remove as default };
@@ -0,0 +1,35 @@
1
+ import { t as commonFlags } from "../flags.js";
2
+ import { i as SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR, t as CARTRIDGES_BASE_DIR } from "../config.js";
3
+ import { t as generateMetadata } from "../generate-cartridge.js";
4
+ import { Command } from "@oclif/core";
5
+ import path from "path";
6
+ import fs from "fs-extra";
7
+
8
+ //#region src/commands/generate-cartridge.ts
9
+ /**
10
+ * Generate cartridge metadata command.
11
+ *
12
+ * Scans the project for decorated components and generates Page Designer
13
+ * metadata files in the cartridge directory.
14
+ */
15
+ var Generate = class Generate extends Command {
16
+ static description = "Generate Page Designer component metadata from decorated components";
17
+ static examples = ["<%= config.bin %> <%= command.id %>", "<%= config.bin %> <%= command.id %> -d ./my-project"];
18
+ static flags = { ...commonFlags };
19
+ async run() {
20
+ const { flags } = await this.parse(Generate);
21
+ const projectDirectory = flags["project-directory"];
22
+ if (!fs.existsSync(projectDirectory)) this.error(`Project directory doesn't exist: ${projectDirectory}`);
23
+ const metadataDir = path.join(projectDirectory, CARTRIDGES_BASE_DIR, SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR);
24
+ if (!fs.existsSync(metadataDir)) {
25
+ this.log(`Creating metadata directory: ${metadataDir}`);
26
+ fs.mkdirSync(metadataDir, { recursive: true });
27
+ }
28
+ this.log("Generating Page Designer metadata...");
29
+ await generateMetadata(projectDirectory, metadataDir);
30
+ this.log("Page Designer metadata generated successfully!");
31
+ }
32
+ };
33
+
34
+ //#endregion
35
+ export { Generate as default };
@@ -0,0 +1,30 @@
1
+ import "../logger.js";
2
+ import { t as prepareForLocalDev } from "../local-dev-setup.js";
3
+ import { t as commonFlags } from "../flags.js";
4
+ import { Command, Flags } from "@oclif/core";
5
+
6
+ //#region src/commands/prepare-local.ts
7
+ /**
8
+ * Prepare local command - prepares a storefront project for local development with file-linked packages.
9
+ */
10
+ var PrepareLocal = class PrepareLocal extends Command {
11
+ static description = "Prepare a storefront project for local development with file-linked packages. Converts workspace:* dependencies to file: references and patches vite.config.ts.";
12
+ static examples = ["<%= config.bin %> <%= command.id %> -d ./my-storefront", "<%= config.bin %> <%= command.id %> -d . -s /path/to/monorepo/packages"];
13
+ static flags = {
14
+ ...commonFlags,
15
+ "source-packages-dir": Flags.string({
16
+ char: "s",
17
+ description: "Source monorepo packages directory (for default path suggestions)"
18
+ })
19
+ };
20
+ async run() {
21
+ const { flags } = await this.parse(PrepareLocal);
22
+ await prepareForLocalDev({
23
+ projectDirectory: flags["project-directory"],
24
+ sourcePackagesDir: flags["source-packages-dir"]
25
+ });
26
+ }
27
+ };
28
+
29
+ //#endregion
30
+ export { PrepareLocal as default };