@salesforce/storefront-next-dev 0.2.0-alpha.2 → 0.3.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.
- package/dist/cartridge-services/index.d.ts.map +1 -1
- package/dist/cartridge-services/index.js +171 -50
- package/dist/cartridge-services/index.js.map +1 -1
- package/dist/commands/create-bundle.js +12 -11
- package/dist/commands/create-instructions.js +7 -5
- package/dist/commands/create-storefront.js +18 -22
- package/dist/commands/deploy-cartridge.js +67 -26
- package/dist/commands/dev.js +6 -4
- package/dist/commands/extensions/create.js +2 -0
- package/dist/commands/extensions/install.js +3 -7
- package/dist/commands/extensions/list.js +2 -0
- package/dist/commands/extensions/remove.js +3 -7
- package/dist/commands/generate-cartridge.js +23 -2
- package/dist/commands/preview.js +15 -10
- package/dist/commands/push.js +25 -19
- package/dist/commands/validate-cartridge.js +51 -0
- package/dist/config.js +74 -47
- package/dist/configs/react-router.config.d.ts.map +1 -1
- package/dist/configs/react-router.config.js +36 -0
- package/dist/configs/react-router.config.js.map +1 -1
- package/dist/dependency-utils.js +14 -16
- package/dist/entry/server.d.ts.map +1 -1
- package/dist/entry/server.js +221 -11
- package/dist/entry/server.js.map +1 -1
- package/dist/generate-cartridge.js +106 -50
- package/dist/index.d.ts +127 -13
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1147 -167
- package/dist/index.js.map +1 -1
- package/dist/local-dev-setup.js +13 -13
- package/dist/logger/index.d.ts +20 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +69 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger.js +79 -33
- package/dist/logger2.js +1 -0
- package/dist/manage-extensions.js +7 -13
- package/dist/mrt/ssr.mjs +60 -72
- package/dist/mrt/ssr.mjs.map +1 -1
- package/dist/mrt/streamingHandler.mjs +66 -78
- package/dist/mrt/streamingHandler.mjs.map +1 -1
- package/dist/react-router/Scripts.d.ts +1 -1
- package/dist/react-router/Scripts.d.ts.map +1 -1
- package/dist/react-router/Scripts.js +38 -2
- package/dist/react-router/Scripts.js.map +1 -1
- package/dist/server.js +296 -16
- package/dist/utils.js +4 -4
- package/dist/validate-cartridge.js +45 -0
- package/package.json +22 -5
|
@@ -1,50 +1,91 @@
|
|
|
1
|
-
import { i as SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR,
|
|
1
|
+
import { i as SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR, t as CARTRIDGES_BASE_DIR } from "../config.js";
|
|
2
|
+
import { Flags } from "@oclif/core";
|
|
2
3
|
import path from "path";
|
|
3
4
|
import fs from "fs-extra";
|
|
4
|
-
import {
|
|
5
|
-
import { uploadCartridges } from "@salesforce/b2c-tooling-sdk/operations/code";
|
|
5
|
+
import { CartridgeCommand } from "@salesforce/b2c-tooling-sdk/cli";
|
|
6
|
+
import { deleteCartridges, getActiveCodeVersion, reloadCodeVersion, uploadCartridges } from "@salesforce/b2c-tooling-sdk/operations/code";
|
|
6
7
|
|
|
7
8
|
//#region src/commands/deploy-cartridge.ts
|
|
8
9
|
/**
|
|
9
|
-
* Deploy cartridge command - deploys
|
|
10
|
+
* Deploy cartridge command - deploys cartridges to a B2C instance.
|
|
10
11
|
*
|
|
11
|
-
*
|
|
12
|
-
* -
|
|
13
|
-
* -
|
|
14
|
-
* -
|
|
15
|
-
* -
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* - --
|
|
19
|
-
* - --
|
|
20
|
-
* - --instance/-i: Named instance from config (env: SFCC_INSTANCE)
|
|
12
|
+
* Extends CartridgeCommand which provides:
|
|
13
|
+
* - All B2C instance flags (--server, --code-version, --username, --password, etc.)
|
|
14
|
+
* - Cartridge filtering flags (-c/--cartridge, -x/--exclude-cartridge)
|
|
15
|
+
* - Cartridge discovery with plugin provider support
|
|
16
|
+
* - Config-driven cartridge filtering via dw.json `cartridges` option
|
|
17
|
+
*
|
|
18
|
+
* Additional flags:
|
|
19
|
+
* - --delete: Delete existing cartridges before upload
|
|
20
|
+
* - --reload/-r: Reload (re-activate) code version after deploy (requires OAuth)
|
|
21
21
|
*/
|
|
22
|
-
var Deploy = class Deploy extends
|
|
23
|
-
static description = "Deploy
|
|
22
|
+
var Deploy = class Deploy extends CartridgeCommand {
|
|
23
|
+
static description = "Deploy cartridges to B2C Commerce Cloud instance";
|
|
24
24
|
static examples = [
|
|
25
25
|
"<%= config.bin %> <%= command.id %>",
|
|
26
26
|
"<%= config.bin %> <%= command.id %> --project-directory ./my-project",
|
|
27
27
|
"<%= config.bin %> <%= command.id %> -s my-sandbox.dx.commercecloud.salesforce.com",
|
|
28
|
-
"<%= config.bin %> <%= command.id %> --code-version staging"
|
|
28
|
+
"<%= config.bin %> <%= command.id %> --code-version staging",
|
|
29
|
+
"<%= config.bin %> <%= command.id %> --delete",
|
|
30
|
+
"<%= config.bin %> <%= command.id %> --delete --reload",
|
|
31
|
+
"<%= config.bin %> <%= command.id %> -c app_storefrontnext_base",
|
|
32
|
+
"<%= config.bin %> <%= command.id %> -x test_cartridge"
|
|
29
33
|
];
|
|
30
|
-
static flags = {
|
|
34
|
+
static flags = {
|
|
35
|
+
...CartridgeCommand.baseFlags,
|
|
36
|
+
...CartridgeCommand.cartridgeFlags,
|
|
37
|
+
reload: Flags.boolean({
|
|
38
|
+
char: "r",
|
|
39
|
+
description: "Reload (re-activate) code version after deploy",
|
|
40
|
+
default: false
|
|
41
|
+
}),
|
|
42
|
+
delete: Flags.boolean({
|
|
43
|
+
description: "Delete existing cartridges before upload",
|
|
44
|
+
default: false
|
|
45
|
+
})
|
|
46
|
+
};
|
|
31
47
|
async run() {
|
|
32
48
|
const { flags } = await this.parse(Deploy);
|
|
33
49
|
const projectDirectory = flags["project-directory"] || process.cwd();
|
|
34
50
|
if (!fs.existsSync(projectDirectory)) this.error(`Project directory doesn't exist: ${projectDirectory}`);
|
|
51
|
+
const cartridgesDir = path.join(projectDirectory, CARTRIDGES_BASE_DIR);
|
|
35
52
|
const metadataDir = path.join(projectDirectory, CARTRIDGES_BASE_DIR, SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR);
|
|
36
53
|
if (!fs.existsSync(metadataDir)) this.error(`Metadata directory doesn't exist: ${metadataDir}. Run 'sfnext generate-cartridge' first.`);
|
|
37
54
|
this.requireServer();
|
|
38
|
-
this.requireCodeVersion();
|
|
39
55
|
this.requireWebDavCredentials();
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
}
|
|
45
|
-
|
|
56
|
+
let version = this.resolvedConfig.values.codeVersion;
|
|
57
|
+
if ((!version || flags.reload) && !this.hasOAuthCredentials()) {
|
|
58
|
+
const reason = version ? "The --reload flag requires OAuth credentials to reload the code version via OCAPI." : "No code version specified. OAuth credentials are required to auto-discover the active code version.";
|
|
59
|
+
this.error(`${reason}\n\nProvide --code-version to use basic auth only, or configure OAuth credentials (--client-id and --client-secret).`);
|
|
60
|
+
}
|
|
61
|
+
if (!version) {
|
|
62
|
+
this.warn("No code version specified, discovering active code version...");
|
|
63
|
+
let activeVersion;
|
|
64
|
+
try {
|
|
65
|
+
activeVersion = await getActiveCodeVersion(this.instance);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
this.error(`Failed to discover active code version: ${error instanceof Error ? error.message : String(error)}\n\nSpecify one explicitly with --code-version or in your dw.json config.`);
|
|
68
|
+
}
|
|
69
|
+
if (!activeVersion?.id) this.error("No active code version found. Specify one with --code-version or in your dw.json config.");
|
|
70
|
+
version = activeVersion.id;
|
|
71
|
+
this.instance.config.codeVersion = version;
|
|
72
|
+
}
|
|
73
|
+
const cartridges = await this.findCartridgesWithProviders(cartridgesDir);
|
|
74
|
+
if (cartridges.length === 0) this.error(`No cartridges found in ${cartridgesDir}`);
|
|
75
|
+
this.log(`Deploying to code version "${version}"...`);
|
|
76
|
+
for (const c of cartridges) this.log(` ${c.name} (${c.src})`);
|
|
77
|
+
if (flags.delete) {
|
|
78
|
+
this.log("Deleting existing cartridges...");
|
|
79
|
+
await deleteCartridges(this.instance, cartridges);
|
|
80
|
+
}
|
|
46
81
|
await uploadCartridges(this.instance, cartridges);
|
|
47
|
-
|
|
82
|
+
if (flags.reload) try {
|
|
83
|
+
await reloadCodeVersion(this.instance, version);
|
|
84
|
+
this.log("Code version reloaded.");
|
|
85
|
+
} catch (error) {
|
|
86
|
+
this.warn(`Could not reload code version: ${error instanceof Error ? error.message : String(error)}`);
|
|
87
|
+
}
|
|
88
|
+
this.log(`Deployed ${cartridges.length} cartridge(s) to version "${version}" successfully!`);
|
|
48
89
|
}
|
|
49
90
|
};
|
|
50
91
|
|
package/dist/commands/dev.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as printShutdownMessage, n as printServerConfig, r as printServerInfo } from "../logger.js";
|
|
2
|
+
import "../logger2.js";
|
|
2
3
|
import { c as loadEnvFile } from "../utils.js";
|
|
3
|
-
import { n as
|
|
4
|
+
import { i as loadProjectConfig, n as initBasePathEnv, r as getCommerceCloudApiUrl, t as createServer$2 } from "../server.js";
|
|
5
|
+
import "../config.js";
|
|
4
6
|
import { t as commonFlags } from "../flags.js";
|
|
5
7
|
import { Command, Flags } from "@oclif/core";
|
|
6
8
|
import path from "path";
|
|
@@ -48,6 +50,7 @@ async function dev(options = {}) {
|
|
|
48
50
|
const port = options.port || 5173;
|
|
49
51
|
process.env.NODE_ENV = process.env.NODE_ENV ?? "development";
|
|
50
52
|
loadEnvFile(projectDir);
|
|
53
|
+
await initBasePathEnv(projectDir);
|
|
51
54
|
process.env.EXTERNAL_DOMAIN_NAME = process.env.EXTERNAL_DOMAIN_NAME ?? `localhost:${port}`;
|
|
52
55
|
const config = await loadProjectConfig(projectDir);
|
|
53
56
|
const httpServer = createServer();
|
|
@@ -79,8 +82,7 @@ async function dev(options = {}) {
|
|
|
79
82
|
proxyHost: getCommerceCloudApiUrl(config.commerce.api.shortCode, config.commerce.api.proxyHost),
|
|
80
83
|
shortCode: config.commerce.api.shortCode,
|
|
81
84
|
organizationId: config.commerce.api.organizationId,
|
|
82
|
-
clientId: config.commerce.api.clientId
|
|
83
|
-
siteId: config.commerce.api.siteId
|
|
85
|
+
clientId: config.commerce.api.clientId
|
|
84
86
|
});
|
|
85
87
|
});
|
|
86
88
|
["SIGTERM", "SIGINT"].forEach((signal) => {
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import "../../logger.js";
|
|
2
|
+
import "../../logger2.js";
|
|
1
3
|
import "../../dependency-utils.js";
|
|
2
4
|
import { t as commonFlags } from "../../flags.js";
|
|
3
5
|
import { r as manageExtensions } from "../../manage-extensions.js";
|
|
@@ -21,11 +23,6 @@ var Install = class Install extends Command {
|
|
|
21
23
|
char: "s",
|
|
22
24
|
description: "Git URL of the source template project",
|
|
23
25
|
default: DEFAULT_TEMPLATE_GIT_URL
|
|
24
|
-
}),
|
|
25
|
-
verbose: Flags.boolean({
|
|
26
|
-
char: "v",
|
|
27
|
-
description: "Verbose mode",
|
|
28
|
-
default: false
|
|
29
26
|
})
|
|
30
27
|
};
|
|
31
28
|
async run() {
|
|
@@ -34,8 +31,7 @@ var Install = class Install extends Command {
|
|
|
34
31
|
projectDirectory: flags["project-directory"],
|
|
35
32
|
install: true,
|
|
36
33
|
extensions: flags.extension ? [flags.extension] : void 0,
|
|
37
|
-
sourceGitUrl: flags["source-git-url"]
|
|
38
|
-
verbose: flags.verbose
|
|
34
|
+
sourceGitUrl: flags["source-git-url"]
|
|
39
35
|
});
|
|
40
36
|
}
|
|
41
37
|
};
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import "../../logger.js";
|
|
2
|
+
import "../../logger2.js";
|
|
1
3
|
import "../../dependency-utils.js";
|
|
2
4
|
import { t as commonFlags } from "../../flags.js";
|
|
3
5
|
import { r as manageExtensions } from "../../manage-extensions.js";
|
|
@@ -15,11 +17,6 @@ var Remove = class Remove extends Command {
|
|
|
15
17
|
extensions: Flags.string({
|
|
16
18
|
char: "e",
|
|
17
19
|
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
20
|
})
|
|
24
21
|
};
|
|
25
22
|
async run() {
|
|
@@ -28,8 +25,7 @@ var Remove = class Remove extends Command {
|
|
|
28
25
|
await manageExtensions({
|
|
29
26
|
projectDirectory: flags["project-directory"],
|
|
30
27
|
uninstall: true,
|
|
31
|
-
extensions
|
|
32
|
-
verbose: flags.verbose
|
|
28
|
+
extensions
|
|
33
29
|
});
|
|
34
30
|
}
|
|
35
31
|
};
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
import
|
|
1
|
+
import "../logger.js";
|
|
2
|
+
import "../logger2.js";
|
|
2
3
|
import { i as SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR, t as CARTRIDGES_BASE_DIR } from "../config.js";
|
|
4
|
+
import { t as commonFlags } from "../flags.js";
|
|
3
5
|
import { t as generateMetadata } from "../generate-cartridge.js";
|
|
6
|
+
import { t as validateCartridgeMetadata } from "../validate-cartridge.js";
|
|
4
7
|
import { Command } from "@oclif/core";
|
|
5
8
|
import path from "path";
|
|
6
9
|
import fs from "fs-extra";
|
|
10
|
+
import chalk from "chalk";
|
|
7
11
|
|
|
8
12
|
//#region src/commands/generate-cartridge.ts
|
|
9
13
|
/**
|
|
@@ -27,7 +31,24 @@ var Generate = class Generate extends Command {
|
|
|
27
31
|
}
|
|
28
32
|
this.log("Generating Page Designer metadata...");
|
|
29
33
|
await generateMetadata(projectDirectory, metadataDir);
|
|
30
|
-
this.log("Page Designer metadata generated successfully
|
|
34
|
+
this.log("Page Designer metadata generated successfully!\n");
|
|
35
|
+
this.log("Validating generated metadata...\n");
|
|
36
|
+
const summary = await validateCartridgeMetadata(metadataDir);
|
|
37
|
+
for (const skipped of summary.skippedFiles) this.warn(`Skipping unrecognized file: ${skipped}`);
|
|
38
|
+
for (const result of summary.results) {
|
|
39
|
+
const relativePath = path.relative(metadataDir, result.filePath ?? "");
|
|
40
|
+
const typeInfo = result.schemaType ? ` (${result.schemaType})` : "";
|
|
41
|
+
if (result.valid) this.log(`${chalk.green("PASS")}: ${relativePath}${typeInfo}`);
|
|
42
|
+
else {
|
|
43
|
+
this.log(`${chalk.red("FAIL")}: ${relativePath}${typeInfo}`);
|
|
44
|
+
for (const error of result.errors) {
|
|
45
|
+
const location = error.path && error.path !== "/" ? ` at ${error.path}` : "";
|
|
46
|
+
this.log(` ${chalk.red("ERROR")}${location}: ${error.message}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
this.log(`\n${summary.validFiles}/${summary.totalFiles} file(s) valid, ${summary.totalErrors} error(s)`);
|
|
51
|
+
if (summary.totalErrors > 0) this.error("Generated metadata has validation errors", { exit: 1 });
|
|
31
52
|
}
|
|
32
53
|
};
|
|
33
54
|
|
package/dist/commands/preview.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { i as printShutdownMessage, n as printServerConfig, r as printServerInfo, t as logger } from "../logger.js";
|
|
2
|
+
import "../logger2.js";
|
|
2
3
|
import { c as loadEnvFile } from "../utils.js";
|
|
3
|
-
import { n as
|
|
4
|
+
import { i as loadProjectConfig, n as initBasePathEnv, r as getCommerceCloudApiUrl, t as createServer } from "../server.js";
|
|
5
|
+
import "../config.js";
|
|
4
6
|
import { t as commonFlags } from "../flags.js";
|
|
5
7
|
import { Command, Flags } from "@oclif/core";
|
|
6
8
|
import { execSync } from "child_process";
|
|
@@ -13,32 +15,36 @@ import { pathToFileURL } from "url";
|
|
|
13
15
|
* Start the preview server with production build
|
|
14
16
|
*/
|
|
15
17
|
async function preview(options = {}) {
|
|
18
|
+
process.setSourceMapsEnabled(true);
|
|
19
|
+
process.env.NODE_OPTIONS = [process.env.NODE_OPTIONS, "--enable-source-maps"].filter(Boolean).join(" ");
|
|
16
20
|
const startTime = Date.now();
|
|
17
21
|
const projectDir = path.resolve(options.projectDirectory || process.cwd());
|
|
18
22
|
const port = options.port || 3e3;
|
|
19
23
|
process.env.NODE_ENV = process.env.NODE_ENV ?? "production";
|
|
20
24
|
process.env.EXTERNAL_DOMAIN_NAME = process.env.EXTERNAL_DOMAIN_NAME ?? `localhost:${port}`;
|
|
21
25
|
loadEnvFile(projectDir);
|
|
26
|
+
await initBasePathEnv(projectDir);
|
|
22
27
|
const buildPath = path.join(projectDir, "build", "server", "index.js");
|
|
23
28
|
if (!fs.existsSync(buildPath)) {
|
|
24
|
-
warn("Production build not found. Building project...");
|
|
25
|
-
info("Running: pnpm build");
|
|
29
|
+
logger.warn("Production build not found. Building project...");
|
|
30
|
+
logger.info("Running: pnpm build");
|
|
26
31
|
try {
|
|
27
32
|
execSync("pnpm build", {
|
|
28
33
|
cwd: projectDir,
|
|
29
34
|
stdio: "inherit"
|
|
30
35
|
});
|
|
31
|
-
info("Build completed successfully");
|
|
36
|
+
logger.info("Build completed successfully");
|
|
32
37
|
} catch (err) {
|
|
33
|
-
|
|
38
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
39
|
+
logger.error(`Build failed: ${errorMsg}`);
|
|
34
40
|
process.exit(1);
|
|
35
41
|
}
|
|
36
42
|
if (!fs.existsSync(buildPath)) {
|
|
37
|
-
error(`Build still not found at ${buildPath} after running build command`);
|
|
43
|
+
logger.error(`Build still not found at ${buildPath} after running build command`);
|
|
38
44
|
process.exit(1);
|
|
39
45
|
}
|
|
40
46
|
}
|
|
41
|
-
info(`Loading production build from ${buildPath}`);
|
|
47
|
+
logger.info(`Loading production build from ${buildPath}`);
|
|
42
48
|
const build = (await import(pathToFileURL(buildPath).href)).default;
|
|
43
49
|
const config = await loadProjectConfig(projectDir);
|
|
44
50
|
const server = (await createServer({
|
|
@@ -59,8 +65,7 @@ async function preview(options = {}) {
|
|
|
59
65
|
proxyHost: getCommerceCloudApiUrl(config.commerce.api.shortCode),
|
|
60
66
|
shortCode: config.commerce.api.shortCode,
|
|
61
67
|
organizationId: config.commerce.api.organizationId,
|
|
62
|
-
clientId: config.commerce.api.clientId
|
|
63
|
-
siteId: config.commerce.api.siteId
|
|
68
|
+
clientId: config.commerce.api.clientId
|
|
64
69
|
});
|
|
65
70
|
});
|
|
66
71
|
["SIGTERM", "SIGINT"].forEach((signal) => {
|
package/dist/commands/push.js
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import "../logger.js";
|
|
2
|
+
import "../logger2.js";
|
|
2
3
|
import { n as getDefaultBuildDir, r as getDefaultMessage } from "../utils.js";
|
|
3
|
-
import { t as createBundle } from "../bundle.js";
|
|
4
4
|
import { a as buildMrtConfig, i as SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR, n as GENERATE_AND_DEPLOY_CARTRIDGE_ON_MRT_PUSH, r as SFNEXT_BASE_CARTRIDGE_NAME, t as CARTRIDGES_BASE_DIR } from "../config.js";
|
|
5
|
+
import { t as createBundle } from "../bundle.js";
|
|
5
6
|
import { t as generateMetadata } from "../generate-cartridge.js";
|
|
6
7
|
import { Flags } from "@oclif/core";
|
|
7
8
|
import path from "path";
|
|
8
9
|
import fs from "fs-extra";
|
|
9
10
|
import { MrtCommand } from "@salesforce/b2c-tooling-sdk/cli";
|
|
10
|
-
import { resolveConfig } from "@salesforce/b2c-tooling-sdk/config";
|
|
11
11
|
import { uploadCartridges } from "@salesforce/b2c-tooling-sdk/operations/code";
|
|
12
12
|
import { uploadBundle, waitForEnv } from "@salesforce/b2c-tooling-sdk/operations/mrt";
|
|
13
13
|
import { DEFAULT_MRT_ORIGIN, createMrtClient } from "@salesforce/b2c-tooling-sdk/clients";
|
|
@@ -17,10 +17,10 @@ import { DEFAULT_MRT_ORIGIN, createMrtClient } from "@salesforce/b2c-tooling-sdk
|
|
|
17
17
|
* MRT Push command - builds and pushes bundle to Managed Runtime.
|
|
18
18
|
*
|
|
19
19
|
* Inherits MRT flags from MrtCommand:
|
|
20
|
-
* - --api-key: MRT API key (env: SFCC_MRT_API_KEY)
|
|
21
|
-
* - --project/-p: MRT project slug (env: SFCC_MRT_PROJECT)
|
|
22
|
-
* - --environment/-e: MRT target environment (env: SFCC_MRT_ENVIRONMENT)
|
|
23
|
-
* - --cloud-origin: MRT cloud origin URL (env: SFCC_MRT_CLOUD_ORIGIN)
|
|
20
|
+
* - --api-key: MRT API key (env: MRT_API_KEY, fallback: SFCC_MRT_API_KEY)
|
|
21
|
+
* - --project/-p: MRT project slug (env: MRT_PROJECT, fallback: SFCC_MRT_PROJECT)
|
|
22
|
+
* - --environment/-e: MRT target environment (env: MRT_TARGET, fallback: SFCC_MRT_ENVIRONMENT)
|
|
23
|
+
* - --cloud-origin: MRT cloud origin URL (env: MRT_CLOUD_ORIGIN, fallback: SFCC_MRT_CLOUD_ORIGIN)
|
|
24
24
|
* - --credentials-file: Path to MRT credentials file (env: MRT_CREDENTIALS_FILE)
|
|
25
25
|
* - --config: Path to dw.json config file (env: SFCC_CONFIG)
|
|
26
26
|
* - --instance/-i: Named instance from config (env: SFCC_INSTANCE)
|
|
@@ -65,16 +65,16 @@ var Push = class Push extends MrtCommand {
|
|
|
65
65
|
if (flags["project-slug"]) this.warn("Flag --project-slug is deprecated. Use --project instead.");
|
|
66
66
|
if (flags.target) this.warn("Flag --target is deprecated. Use --environment instead.");
|
|
67
67
|
const target = flags.environment || flags.target || this.resolvedConfig.values.mrtEnvironment;
|
|
68
|
-
if (flags.wait && !target) this.error("You must provide a target environment when using --wait (via --environment flag,
|
|
68
|
+
if (flags.wait && !target) this.error("You must provide a target environment when using --wait (via --environment flag, MRT_TARGET env var, or dw.json)");
|
|
69
69
|
if (!fs.existsSync(projectDirectory)) this.error(`Project directory "${projectDirectory}" does not exist!`);
|
|
70
70
|
const projectSlug = flags.project || flags["project-slug"] || this.resolvedConfig.values.mrtProject;
|
|
71
|
-
if (!projectSlug || projectSlug.trim() === "") this.error("Project slug is required. Provide --project, set
|
|
71
|
+
if (!projectSlug || projectSlug.trim() === "") this.error("Project slug is required. Provide --project, set MRT_PROJECT env var, or configure mrtProject in dw.json");
|
|
72
72
|
const buildDirectory = flags["build-directory"] ?? getDefaultBuildDir(projectDirectory);
|
|
73
73
|
if (!fs.existsSync(buildDirectory)) this.error(`Build directory "${buildDirectory}" does not exist!`);
|
|
74
74
|
if (GENERATE_AND_DEPLOY_CARTRIDGE_ON_MRT_PUSH) await this.generateAndDeployCartridge(projectDirectory);
|
|
75
75
|
if (target) process.env.DEPLOY_TARGET = target;
|
|
76
76
|
this.requireMrtCredentials();
|
|
77
|
-
const config = buildMrtConfig(buildDirectory, projectDirectory);
|
|
77
|
+
const config = await buildMrtConfig(buildDirectory, projectDirectory);
|
|
78
78
|
const message = flags.message ?? getDefaultMessage(projectDirectory);
|
|
79
79
|
this.log(`Creating bundle for project: ${projectSlug}`);
|
|
80
80
|
if (target) this.log(`Target environment: ${target}`);
|
|
@@ -89,18 +89,25 @@ var Push = class Push extends MrtCommand {
|
|
|
89
89
|
});
|
|
90
90
|
const origin = this.resolvedConfig.values.mrtOrigin || DEFAULT_MRT_ORIGIN;
|
|
91
91
|
const client = createMrtClient({ origin }, this.getMrtAuth());
|
|
92
|
-
this.log(`
|
|
92
|
+
this.log(`Uploading bundle to ${origin}`);
|
|
93
93
|
const result = await uploadBundle(client, projectSlug, bundle, target);
|
|
94
|
+
this.log(`Bundle ${result.bundleId} uploaded`);
|
|
94
95
|
if (flags.wait && target) {
|
|
95
|
-
this.log(
|
|
96
|
+
this.log(`Waiting for deployment to ${target}...`);
|
|
97
|
+
let lastState = "";
|
|
96
98
|
await waitForEnv({
|
|
97
99
|
projectSlug,
|
|
98
100
|
slug: target,
|
|
99
|
-
origin
|
|
101
|
+
origin,
|
|
102
|
+
onPoll: (info) => {
|
|
103
|
+
if (info.state !== lastState) {
|
|
104
|
+
lastState = info.state;
|
|
105
|
+
this.log(` ${target}: ${info.state} (${info.elapsedSeconds}s)`);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
100
108
|
}, this.getMrtAuth());
|
|
101
|
-
this.log(
|
|
102
|
-
}
|
|
103
|
-
this.log(`Bundle ID: ${result.bundleId}`);
|
|
109
|
+
this.log(`Deployment complete — bundle ${result.bundleId} is live on ${target}`);
|
|
110
|
+
}
|
|
104
111
|
}
|
|
105
112
|
/**
|
|
106
113
|
* Generate and deploy cartridge metadata to B2C instance.
|
|
@@ -114,16 +121,15 @@ var Push = class Push extends MrtCommand {
|
|
|
114
121
|
await generateMetadata(projectDirectory, metadataDir);
|
|
115
122
|
this.log("Cartridge metadata generated successfully!");
|
|
116
123
|
this.log("Deploying cartridge to Commerce Cloud...");
|
|
117
|
-
|
|
118
|
-
if (!b2cConfig.hasB2CInstanceConfig()) {
|
|
124
|
+
if (!this.resolvedConfig.hasB2CInstanceConfig()) {
|
|
119
125
|
this.warn("B2C instance not configured, skipping cartridge deployment");
|
|
120
126
|
return;
|
|
121
127
|
}
|
|
122
|
-
if (!
|
|
128
|
+
if (!this.resolvedConfig.values.codeVersion) {
|
|
123
129
|
this.warn("Code version not configured, skipping cartridge deployment");
|
|
124
130
|
return;
|
|
125
131
|
}
|
|
126
|
-
await uploadCartridges(
|
|
132
|
+
await uploadCartridges(this.resolvedConfig.createB2CInstance(), [{
|
|
127
133
|
name: SFNEXT_BASE_CARTRIDGE_NAME,
|
|
128
134
|
src: path.join(projectDirectory, CARTRIDGES_BASE_DIR, SFNEXT_BASE_CARTRIDGE_NAME),
|
|
129
135
|
dest: SFNEXT_BASE_CARTRIDGE_NAME
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { i as SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR, t as CARTRIDGES_BASE_DIR } from "../config.js";
|
|
2
|
+
import { t as commonFlags } from "../flags.js";
|
|
3
|
+
import { t as validateCartridgeMetadata } from "../validate-cartridge.js";
|
|
4
|
+
import { Command } from "@oclif/core";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import fs from "fs-extra";
|
|
7
|
+
import chalk from "chalk";
|
|
8
|
+
|
|
9
|
+
//#region src/commands/validate-cartridge.ts
|
|
10
|
+
/**
|
|
11
|
+
* Validate cartridge metadata command.
|
|
12
|
+
*
|
|
13
|
+
* Validates all Page Designer metadata JSON files in the cartridge
|
|
14
|
+
* directory against their metadefinition schemas.
|
|
15
|
+
*/
|
|
16
|
+
var ValidateCartridge = class ValidateCartridge extends Command {
|
|
17
|
+
static description = "Validate Page Designer metadata JSON files against schemas";
|
|
18
|
+
static examples = ["<%= config.bin %> <%= command.id %>", "<%= config.bin %> <%= command.id %> -d ./my-project"];
|
|
19
|
+
static flags = { ...commonFlags };
|
|
20
|
+
async run() {
|
|
21
|
+
const { flags } = await this.parse(ValidateCartridge);
|
|
22
|
+
const projectDirectory = flags["project-directory"];
|
|
23
|
+
if (!fs.existsSync(projectDirectory)) this.error(`Project directory doesn't exist: ${projectDirectory}`);
|
|
24
|
+
const metadataDir = path.join(projectDirectory, CARTRIDGES_BASE_DIR, SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR);
|
|
25
|
+
if (!fs.existsSync(metadataDir)) this.error(`Metadata directory doesn't exist: ${metadataDir}\nRun "sfnext generate-cartridge" first to generate metadata files.`);
|
|
26
|
+
this.log("Validating Page Designer metadata...\n");
|
|
27
|
+
const summary = await validateCartridgeMetadata(metadataDir);
|
|
28
|
+
if (summary.totalFiles === 0) {
|
|
29
|
+
this.warn("No metadata files found to validate.");
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
for (const skipped of summary.skippedFiles) this.warn(`Skipping unrecognized file: ${skipped}`);
|
|
33
|
+
for (const result of summary.results) {
|
|
34
|
+
const relativePath = path.relative(metadataDir, result.filePath ?? "");
|
|
35
|
+
const typeInfo = result.schemaType ? ` (${result.schemaType})` : "";
|
|
36
|
+
if (result.valid) this.log(`${chalk.green("PASS")}: ${relativePath}${typeInfo}`);
|
|
37
|
+
else {
|
|
38
|
+
this.log(`${chalk.red("FAIL")}: ${relativePath}${typeInfo}`);
|
|
39
|
+
for (const error of result.errors) {
|
|
40
|
+
const location = error.path && error.path !== "/" ? ` at ${error.path}` : "";
|
|
41
|
+
this.log(` ${chalk.red("ERROR")}${location}: ${error.message}`);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
this.log(`\n${summary.validFiles}/${summary.totalFiles} file(s) valid, ${summary.totalErrors} error(s)`);
|
|
46
|
+
if (summary.totalErrors > 0) this.error("Validation failed", { exit: 1 });
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
//#endregion
|
|
51
|
+
export { ValidateCartridge as default };
|
package/dist/config.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { resolve } from "node:path";
|
|
3
|
+
|
|
1
4
|
//#region src/mrt/utils.ts
|
|
2
5
|
const MRT_BUNDLE_TYPE_SSR = "ssr";
|
|
3
6
|
const MRT_STREAMING_ENTRY_FILE = "streamingHandler";
|
|
@@ -29,59 +32,83 @@ const SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR = `${SFNEXT_BASE_CARTRIDGE_NAME}/cartridg
|
|
|
29
32
|
*/
|
|
30
33
|
const GENERATE_AND_DEPLOY_CARTRIDGE_ON_MRT_PUSH = false;
|
|
31
34
|
/**
|
|
32
|
-
*
|
|
35
|
+
* Merge override patterns with defaults while preserving required defaults.
|
|
36
|
+
*
|
|
37
|
+
* Overrides are prepended so they can add additional globs or exclusions, while
|
|
38
|
+
* defaults remain in the list to prevent breaking essential artifacts.
|
|
33
39
|
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
40
|
+
* @example
|
|
41
|
+
* const defaults = ['server/**', 'loader.js'];
|
|
42
|
+
* const overrides = ['custom/**', '!static/**'];
|
|
43
|
+
* mergePatterns(defaults, overrides);
|
|
44
|
+
* // => ['custom/**', '!static/**', 'server/**', 'loader.js']
|
|
45
|
+
*/
|
|
46
|
+
const mergePatterns = (defaults, overrides) => {
|
|
47
|
+
if (!overrides?.length) return defaults;
|
|
48
|
+
return Array.from(new Set([...overrides, ...defaults]));
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Load runtime config from config.server.ts for MRT bundle settings.
|
|
37
52
|
*
|
|
38
|
-
*
|
|
39
|
-
* @param projectDirectory - Path to the project root (reserved for future use)
|
|
40
|
-
* @returns MRT SSR configuration with glob patterns
|
|
53
|
+
* Keep in sync with @salesforce/storefront-next-runtime/src/config/load-config.ts.
|
|
41
54
|
*/
|
|
42
|
-
|
|
55
|
+
async function loadRuntimeConfig(projectDirectory) {
|
|
56
|
+
if (!projectDirectory) return;
|
|
57
|
+
const configPath = resolve(projectDirectory, "config.server.ts");
|
|
58
|
+
if (!existsSync(configPath)) return;
|
|
59
|
+
try {
|
|
60
|
+
const { createJiti } = await import("jiti");
|
|
61
|
+
const mod = await createJiti(import.meta.url, {
|
|
62
|
+
fsCache: false,
|
|
63
|
+
interopDefault: true
|
|
64
|
+
}).import(configPath);
|
|
65
|
+
return (mod.default ?? mod).runtime;
|
|
66
|
+
} catch (error) {
|
|
67
|
+
throw new Error(`[storefront-next-dev] Found config.server.ts at ${configPath} but failed to import it.`, { cause: error });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
const buildMrtConfig = async (_buildDirectory, projectDirectory) => {
|
|
43
71
|
const ssrEntryPoint = getMrtEntryFile("production");
|
|
72
|
+
const defaultSsrOnly = [
|
|
73
|
+
"server/**/*",
|
|
74
|
+
"package.json",
|
|
75
|
+
"loader.js",
|
|
76
|
+
`${ssrEntryPoint}.{js,mjs,cjs}`,
|
|
77
|
+
`${ssrEntryPoint}.{js,mjs,cjs}.map`,
|
|
78
|
+
"!static/**/*",
|
|
79
|
+
"sfnext-server-*.mjs",
|
|
80
|
+
"sfnext-server-*.mjs.map"
|
|
81
|
+
];
|
|
82
|
+
const defaultSsrShared = [
|
|
83
|
+
"client/**/*",
|
|
84
|
+
"static/**/*",
|
|
85
|
+
"**/*.css",
|
|
86
|
+
"**/*.png",
|
|
87
|
+
"**/*.jpg",
|
|
88
|
+
"**/*.jpeg",
|
|
89
|
+
"**/*.gif",
|
|
90
|
+
"**/*.svg",
|
|
91
|
+
"**/*.ico",
|
|
92
|
+
"**/*.woff",
|
|
93
|
+
"**/*.woff2",
|
|
94
|
+
"**/*.ttf",
|
|
95
|
+
"**/*.eot"
|
|
96
|
+
];
|
|
97
|
+
const defaultSsrParameters = { ssrFunctionNodeVersion: "24.x" };
|
|
98
|
+
const runtimeConfig = await loadRuntimeConfig(projectDirectory);
|
|
99
|
+
const ssrOnly = mergePatterns(defaultSsrOnly, runtimeConfig?.ssrOnly);
|
|
100
|
+
const ssrShared = mergePatterns(defaultSsrShared, runtimeConfig?.ssrShared);
|
|
101
|
+
const ssrParameters = {
|
|
102
|
+
...defaultSsrParameters,
|
|
103
|
+
...runtimeConfig?.ssrParameters ?? {}
|
|
104
|
+
};
|
|
105
|
+
if (!ssrParameters.envBasePath) delete ssrParameters.envBasePath;
|
|
44
106
|
return {
|
|
45
|
-
ssrOnly
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
`${ssrEntryPoint}.{js,mjs,cjs}`,
|
|
49
|
-
`${ssrEntryPoint}.{js,mjs,cjs}.map`,
|
|
50
|
-
"!static/**/*",
|
|
51
|
-
"sfnext-server-*.mjs",
|
|
52
|
-
"!**/*.stories.tsx",
|
|
53
|
-
"!**/*.stories.ts",
|
|
54
|
-
"!**/*-snapshot.tsx",
|
|
55
|
-
"!.storybook/**/*",
|
|
56
|
-
"!storybook-static/**/*",
|
|
57
|
-
"!**/__mocks__/**/*",
|
|
58
|
-
"!**/__snapshots__/**/*"
|
|
59
|
-
],
|
|
60
|
-
ssrShared: [
|
|
61
|
-
"client/**/*",
|
|
62
|
-
"static/**/*",
|
|
63
|
-
"**/*.css",
|
|
64
|
-
"**/*.png",
|
|
65
|
-
"**/*.jpg",
|
|
66
|
-
"**/*.jpeg",
|
|
67
|
-
"**/*.gif",
|
|
68
|
-
"**/*.svg",
|
|
69
|
-
"**/*.ico",
|
|
70
|
-
"**/*.woff",
|
|
71
|
-
"**/*.woff2",
|
|
72
|
-
"**/*.ttf",
|
|
73
|
-
"**/*.eot",
|
|
74
|
-
"!**/*.stories.tsx",
|
|
75
|
-
"!**/*.stories.ts",
|
|
76
|
-
"!**/*-snapshot.tsx",
|
|
77
|
-
"!.storybook/**/*",
|
|
78
|
-
"!storybook-static/**/*",
|
|
79
|
-
"!**/__mocks__/**/*",
|
|
80
|
-
"!**/__snapshots__/**/*"
|
|
81
|
-
],
|
|
82
|
-
ssrParameters: { ssrFunctionNodeVersion: "24.x" }
|
|
107
|
+
ssrOnly,
|
|
108
|
+
ssrShared,
|
|
109
|
+
ssrParameters
|
|
83
110
|
};
|
|
84
111
|
};
|
|
85
112
|
|
|
86
113
|
//#endregion
|
|
87
|
-
export { buildMrtConfig as a, SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR as i, GENERATE_AND_DEPLOY_CARTRIDGE_ON_MRT_PUSH as n, SFNEXT_BASE_CARTRIDGE_NAME as r, CARTRIDGES_BASE_DIR as t };
|
|
114
|
+
export { buildMrtConfig as a, SFNEXT_BASE_CARTRIDGE_OUTPUT_DIR as i, GENERATE_AND_DEPLOY_CARTRIDGE_ON_MRT_PUSH as n, loadRuntimeConfig as o, SFNEXT_BASE_CARTRIDGE_NAME as r, CARTRIDGES_BASE_DIR as t };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"react-router.config.d.ts","names":[],"sources":["../../src/configs/react-router.config.ts"],"sourcesContent":[],"mappings":";;;;;;;;;
|
|
1
|
+
{"version":3,"file":"react-router.config.d.ts","names":[],"sources":["../../src/configs/react-router.config.ts"],"sourcesContent":[],"mappings":";;;;;;;;;iBAuBgB,oBAAA,CAAA,GAAwB"}
|