@salesforce/b2c-dx-mcp 0.0.1 → 0.3.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.
Files changed (48) hide show
  1. package/README.md +422 -29
  2. package/bin/run.cmd +3 -0
  3. package/bin/run.js +27 -0
  4. package/content/auth.md +62 -0
  5. package/content/components.md +123 -0
  6. package/content/config.md +180 -0
  7. package/content/data-fetching.md +323 -0
  8. package/content/extensions.md +80 -0
  9. package/content/i18n.md +121 -0
  10. package/content/page-designer.md +86 -0
  11. package/content/performance.md +80 -0
  12. package/content/pitfalls.md +141 -0
  13. package/content/quick-reference.md +226 -0
  14. package/content/state-management.md +75 -0
  15. package/content/styling.md +51 -0
  16. package/content/testing.md +232 -0
  17. package/dist/commands/mcp.d.ts +110 -0
  18. package/dist/commands/mcp.js +333 -0
  19. package/dist/registry.d.ts +37 -0
  20. package/dist/registry.js +212 -0
  21. package/dist/server.d.ts +46 -0
  22. package/dist/server.js +98 -0
  23. package/dist/services.d.ts +168 -0
  24. package/dist/services.js +191 -0
  25. package/dist/tools/adapter.d.ts +201 -0
  26. package/dist/tools/adapter.js +220 -0
  27. package/dist/tools/cartridges/index.d.ts +20 -0
  28. package/dist/tools/cartridges/index.js +101 -0
  29. package/dist/tools/index.d.ts +17 -0
  30. package/dist/tools/index.js +25 -0
  31. package/dist/tools/mrt/index.d.ts +20 -0
  32. package/dist/tools/mrt/index.js +101 -0
  33. package/dist/tools/pwav3/index.d.ts +13 -0
  34. package/dist/tools/pwav3/index.js +78 -0
  35. package/dist/tools/scapi/index.d.ts +9 -0
  36. package/dist/tools/scapi/index.js +68 -0
  37. package/dist/tools/storefrontnext/developer-guidelines.d.ts +9 -0
  38. package/dist/tools/storefrontnext/developer-guidelines.js +140 -0
  39. package/dist/tools/storefrontnext/index.d.ts +13 -0
  40. package/dist/tools/storefrontnext/index.js +83 -0
  41. package/dist/utils/constants.d.ts +16 -0
  42. package/dist/utils/constants.js +18 -0
  43. package/dist/utils/index.d.ts +7 -0
  44. package/dist/utils/index.js +16 -0
  45. package/dist/utils/types.d.ts +45 -0
  46. package/dist/utils/types.js +7 -0
  47. package/oclif.manifest.json +377 -0
  48. package/package.json +123 -7
@@ -0,0 +1,37 @@
1
+ import type { McpTool, Toolset, StartupFlags } from './utils/index.js';
2
+ import type { B2CDxMcpServer } from './server.js';
3
+ import type { Services } from './services.js';
4
+ /**
5
+ * Registry of tools organized by toolset.
6
+ * Tools can belong to multiple toolsets via their `toolsets` array.
7
+ */
8
+ export type ToolRegistry = Record<Toolset, McpTool[]>;
9
+ /**
10
+ * Creates the tool registry from all toolset providers.
11
+ * Tools are organized by their declared `toolsets` array, allowing
12
+ * a single tool to appear in multiple toolsets.
13
+ *
14
+ * @param services - Services instance for dependency injection
15
+ * @returns Complete tool registry
16
+ */
17
+ export declare function createToolRegistry(services: Services): ToolRegistry;
18
+ /**
19
+ * Register tools with the MCP server based on startup flags.
20
+ *
21
+ * Tool selection logic:
22
+ * 1. If no valid tools result from --toolsets and --tools, perform auto-discovery
23
+ * 2. Start with all tools from --toolsets (or auto-discovered toolsets)
24
+ * 3. Add individual tools from --tools (can be from any toolset)
25
+ *
26
+ * Auto-discovery always enables at least the BASE_TOOLSET (SCAPI), even if no
27
+ * project types are detected in the workspace.
28
+ *
29
+ * Example:
30
+ * --toolsets STOREFRONTNEXT,MRT --tools cartridge_deploy
31
+ * This enables STOREFRONTNEXT and MRT toolsets, plus adds cartridge_deploy from CARTRIDGES.
32
+ *
33
+ * @param flags - Startup flags from CLI
34
+ * @param server - B2CDxMcpServer instance
35
+ * @param services - Services instance
36
+ */
37
+ export declare function registerToolsets(flags: StartupFlags, server: B2CDxMcpServer, services: Services): Promise<void>;
@@ -0,0 +1,212 @@
1
+ /*
2
+ * Copyright (c) 2025, Salesforce, Inc.
3
+ * SPDX-License-Identifier: Apache-2
4
+ * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
+ */
6
+ import { getLogger } from '@salesforce/b2c-tooling-sdk/logging';
7
+ import { detectWorkspaceType } from '@salesforce/b2c-tooling-sdk/discovery';
8
+ import { ALL_TOOLSETS, TOOLSETS, VALID_TOOLSET_NAMES } from './utils/index.js';
9
+ import { createCartridgesTools } from './tools/cartridges/index.js';
10
+ import { createMrtTools } from './tools/mrt/index.js';
11
+ import { createPwav3Tools } from './tools/pwav3/index.js';
12
+ import { createScapiTools } from './tools/scapi/index.js';
13
+ import { createStorefrontNextTools } from './tools/storefrontnext/index.js';
14
+ /**
15
+ * Base toolset that is always enabled.
16
+ * Provides SCAPI discovery and custom API scaffolding tools.
17
+ */
18
+ const BASE_TOOLSET = 'SCAPI';
19
+ /**
20
+ * Toolset mapping by project type.
21
+ * Each project type enables specific toolsets IN ADDITION to the base toolset.
22
+ */
23
+ const PROJECT_TYPE_TOOLSETS = {
24
+ cartridges: ['CARTRIDGES'],
25
+ 'pwa-kit-v3': ['PWAV3', 'MRT'],
26
+ 'storefront-next': ['STOREFRONTNEXT', 'MRT', 'CARTRIDGES'],
27
+ };
28
+ /**
29
+ * Gets toolsets for a project type, always including the base toolset.
30
+ */
31
+ function getToolsetsForProjectType(projectType) {
32
+ const additionalToolsets = PROJECT_TYPE_TOOLSETS[projectType] ?? [];
33
+ return [...additionalToolsets, BASE_TOOLSET];
34
+ }
35
+ /**
36
+ * Maps multiple detected project types to a union of MCP toolsets.
37
+ *
38
+ * Combines toolsets from all matched project types, enabling hybrid
39
+ * project support (e.g., cartridges + pwa-kit-v3 gets CARTRIDGES + PWAV3 + MRT + SCAPI).
40
+ *
41
+ * @param projectTypes - Array of detected project types
42
+ * @returns Union of all toolsets for the detected project types (always includes base toolset)
43
+ */
44
+ function getToolsetsForProjectTypes(projectTypes) {
45
+ const toolsetSet = new Set();
46
+ // Always include base toolset
47
+ toolsetSet.add(BASE_TOOLSET);
48
+ // Add toolsets for each detected project type
49
+ for (const projectType of projectTypes) {
50
+ for (const toolset of getToolsetsForProjectType(projectType)) {
51
+ toolsetSet.add(toolset);
52
+ }
53
+ }
54
+ return [...toolsetSet];
55
+ }
56
+ /**
57
+ * Creates the tool registry from all toolset providers.
58
+ * Tools are organized by their declared `toolsets` array, allowing
59
+ * a single tool to appear in multiple toolsets.
60
+ *
61
+ * @param services - Services instance for dependency injection
62
+ * @returns Complete tool registry
63
+ */
64
+ export function createToolRegistry(services) {
65
+ const registry = {
66
+ CARTRIDGES: [],
67
+ MRT: [],
68
+ PWAV3: [],
69
+ SCAPI: [],
70
+ STOREFRONTNEXT: [],
71
+ };
72
+ // Collect all tools from all factories
73
+ const allTools = [
74
+ ...createCartridgesTools(services),
75
+ ...createMrtTools(services),
76
+ ...createPwav3Tools(services),
77
+ ...createScapiTools(services),
78
+ ...createStorefrontNextTools(services),
79
+ ];
80
+ // Organize tools by their declared toolsets (supports multi-toolset)
81
+ for (const tool of allTools) {
82
+ for (const toolset of tool.toolsets) {
83
+ registry[toolset].push(tool);
84
+ }
85
+ }
86
+ return registry;
87
+ }
88
+ /**
89
+ * Performs workspace auto-discovery and returns appropriate toolsets.
90
+ * Always includes BASE_TOOLSET even if no project types are detected.
91
+ *
92
+ * @param flags - Startup flags containing workingDirectory
93
+ * @param reason - Reason for triggering auto-discovery (for logging)
94
+ * @returns Array of toolsets to enable
95
+ */
96
+ async function performAutoDiscovery(flags, reason) {
97
+ const logger = getLogger();
98
+ // Working directory from --working-directory flag or SFCC_WORKING_DIRECTORY env var
99
+ const workingDirectory = flags.workingDirectory ?? process.cwd();
100
+ // Warn if working directory wasn't explicitly configured
101
+ if (!flags.workingDirectory) {
102
+ logger.warn({ cwd: workingDirectory }, 'No --working-directory flag or SFCC_WORKING_DIRECTORY env var provided. ' +
103
+ 'MCP clients like Cursor and Claude Desktop often spawn servers from ~ instead of the project directory. ' +
104
+ 'Set --working-directory or SFCC_WORKING_DIRECTORY for reliable auto-discovery.');
105
+ }
106
+ const detectionResult = await detectWorkspaceType(workingDirectory);
107
+ // Map all detected project types to MCP toolsets (union)
108
+ // Note: getToolsetsForProjectTypes always includes BASE_TOOLSET
109
+ const mappedToolsets = getToolsetsForProjectTypes(detectionResult.projectTypes);
110
+ logger.info({
111
+ reason,
112
+ projectTypes: detectionResult.projectTypes,
113
+ matchedPatterns: detectionResult.matchedPatterns,
114
+ enabledToolsets: mappedToolsets,
115
+ }, `Auto-discovery (${reason}): project types: ${detectionResult.projectTypes.join(', ') || 'none'}`);
116
+ return mappedToolsets;
117
+ }
118
+ /**
119
+ * Register tools with the MCP server based on startup flags.
120
+ *
121
+ * Tool selection logic:
122
+ * 1. If no valid tools result from --toolsets and --tools, perform auto-discovery
123
+ * 2. Start with all tools from --toolsets (or auto-discovered toolsets)
124
+ * 3. Add individual tools from --tools (can be from any toolset)
125
+ *
126
+ * Auto-discovery always enables at least the BASE_TOOLSET (SCAPI), even if no
127
+ * project types are detected in the workspace.
128
+ *
129
+ * Example:
130
+ * --toolsets STOREFRONTNEXT,MRT --tools cartridge_deploy
131
+ * This enables STOREFRONTNEXT and MRT toolsets, plus adds cartridge_deploy from CARTRIDGES.
132
+ *
133
+ * @param flags - Startup flags from CLI
134
+ * @param server - B2CDxMcpServer instance
135
+ * @param services - Services instance
136
+ */
137
+ export async function registerToolsets(flags, server, services) {
138
+ const toolsets = flags.toolsets ?? [];
139
+ const individualTools = flags.tools ?? [];
140
+ const allowNonGaTools = flags.allowNonGaTools ?? false;
141
+ const logger = getLogger();
142
+ // Create the tool registry (all available tools)
143
+ const toolRegistry = createToolRegistry(services);
144
+ // Build flat list of all tools for lookup
145
+ const allTools = Object.values(toolRegistry).flat();
146
+ const allToolsByName = new Map(allTools.map((tool) => [tool.name, tool]));
147
+ const existingToolNames = new Set(allToolsByName.keys());
148
+ // Determine valid individual tools
149
+ const invalidTools = individualTools.filter((name) => !existingToolNames.has(name));
150
+ const validIndividualTools = individualTools.filter((name) => existingToolNames.has(name));
151
+ // Warn about invalid --tools names (but continue with valid ones)
152
+ if (invalidTools.length > 0) {
153
+ logger.warn({ invalidTools, validTools: [...existingToolNames] }, `Ignoring invalid tool name(s): "${invalidTools.join('", "')}"`);
154
+ }
155
+ // Warn about invalid --toolsets names (but continue with valid ones)
156
+ const invalidToolsets = toolsets.filter((t) => !VALID_TOOLSET_NAMES.includes(t));
157
+ if (invalidToolsets.length > 0) {
158
+ logger.warn({ invalidToolsets, validToolsets: VALID_TOOLSET_NAMES }, `Ignoring invalid toolset(s): "${invalidToolsets.join('", "')}"`);
159
+ }
160
+ // Determine which toolsets to enable
161
+ const validToolsets = toolsets.filter((t) => TOOLSETS.includes(t));
162
+ const toolsetsToEnable = new Set(toolsets.includes(ALL_TOOLSETS) ? TOOLSETS : validToolsets);
163
+ // Auto-discovery: If no valid toolsets AND no valid individual tools, detect workspace type.
164
+ // This handles both: (1) no flags provided, and (2) all provided flags are invalid.
165
+ // Auto-discovery enables appropriate toolsets based on workspace type,
166
+ // or at minimum BASE_TOOLSET if no project types are detected.
167
+ if (toolsetsToEnable.size === 0 && validIndividualTools.length === 0) {
168
+ const discoveredToolsets = await performAutoDiscovery(flags, 'no valid toolsets or tools');
169
+ for (const toolset of discoveredToolsets) {
170
+ toolsetsToEnable.add(toolset);
171
+ }
172
+ }
173
+ // Build the set of tools to register:
174
+ // 1. Start with tools from enabled toolsets
175
+ // 2. Add individual tools from --tools
176
+ const toolsToRegister = [];
177
+ const registeredToolNames = new Set();
178
+ // Step 1: Add tools from enabled toolsets
179
+ for (const toolset of toolsetsToEnable) {
180
+ for (const tool of toolRegistry[toolset]) {
181
+ if (!registeredToolNames.has(tool.name)) {
182
+ toolsToRegister.push(tool);
183
+ registeredToolNames.add(tool.name);
184
+ }
185
+ }
186
+ }
187
+ // Step 2: Add individual tools from --tools (can be from any toolset)
188
+ for (const toolName of validIndividualTools) {
189
+ const tool = allToolsByName.get(toolName);
190
+ if (tool && !registeredToolNames.has(toolName)) {
191
+ toolsToRegister.push(tool);
192
+ registeredToolNames.add(toolName);
193
+ }
194
+ }
195
+ // Register all selected tools
196
+ await registerTools(toolsToRegister, server, allowNonGaTools);
197
+ }
198
+ /**
199
+ * Register a list of tools with the server.
200
+ */
201
+ async function registerTools(tools, server, allowNonGaTools) {
202
+ for (const tool of tools) {
203
+ // Skip non-GA tools if not allowed
204
+ if (tool.isGA === false && !allowNonGaTools) {
205
+ continue;
206
+ }
207
+ // Register the tool
208
+ // TODO: Telemetry - Tool registration includes timing/error tracking
209
+ server.addTool(tool.name, tool.description, tool.inputSchema, async (args) => tool.handler(args));
210
+ }
211
+ }
212
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1,46 @@
1
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
2
+ import type { CallToolResult, Implementation } from '@modelcontextprotocol/sdk/types.js';
3
+ import type { ServerOptions } from '@modelcontextprotocol/sdk/server/index.js';
4
+ import type { Transport } from '@modelcontextprotocol/sdk/shared/transport.js';
5
+ import type { ZodRawShape } from 'zod';
6
+ import type { Telemetry } from '@salesforce/b2c-tooling-sdk/telemetry';
7
+ /**
8
+ * Extended server options.
9
+ */
10
+ export interface B2CDxMcpServerOptions extends ServerOptions {
11
+ /**
12
+ * Telemetry instance for tracking server and tool events.
13
+ * If not provided, telemetry is disabled.
14
+ */
15
+ telemetry?: Telemetry;
16
+ }
17
+ /**
18
+ * A server implementation that extends the base MCP server.
19
+ *
20
+ * @augments {McpServer}
21
+ */
22
+ export declare class B2CDxMcpServer extends McpServer {
23
+ private telemetry?;
24
+ /**
25
+ * Creates a new B2CDxMcpServer instance
26
+ *
27
+ * @param serverInfo - The server implementation details
28
+ * @param options - Optional server configuration
29
+ */
30
+ constructor(serverInfo: Implementation, options?: B2CDxMcpServerOptions);
31
+ /**
32
+ * Register a tool with the server.
33
+ *
34
+ * This method provides a convenient way to register tools.
35
+ *
36
+ * @param name - Tool name
37
+ * @param description - Tool description
38
+ * @param inputSchema - Zod schema for input validation
39
+ * @param handler - Function to handle tool invocations
40
+ */
41
+ addTool(name: string, description: string, inputSchema: ZodRawShape, handler: (args: Record<string, unknown>) => Promise<CallToolResult>): void;
42
+ /**
43
+ * Connect to a transport.
44
+ */
45
+ connect(transport: Transport): Promise<void>;
46
+ }
package/dist/server.js ADDED
@@ -0,0 +1,98 @@
1
+ /*
2
+ * Copyright (c) 2025, Salesforce, Inc.
3
+ * SPDX-License-Identifier: Apache-2
4
+ * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
5
+ */
6
+ import { McpServer } from '@modelcontextprotocol/sdk/server/mcp.js';
7
+ /**
8
+ * A server implementation that extends the base MCP server.
9
+ *
10
+ * @augments {McpServer}
11
+ */
12
+ export class B2CDxMcpServer extends McpServer {
13
+ telemetry;
14
+ /**
15
+ * Creates a new B2CDxMcpServer instance
16
+ *
17
+ * @param serverInfo - The server implementation details
18
+ * @param options - Optional server configuration
19
+ */
20
+ constructor(serverInfo, options) {
21
+ super(serverInfo, options);
22
+ this.telemetry = options?.telemetry;
23
+ // Set up oninitialized handler
24
+ this.server.oninitialized = () => {
25
+ const clientInfo = this.server.getClientVersion();
26
+ if (clientInfo) {
27
+ this.telemetry?.addAttributes({
28
+ clientName: clientInfo.name,
29
+ clientVersion: clientInfo.version,
30
+ });
31
+ }
32
+ };
33
+ }
34
+ /**
35
+ * Register a tool with the server.
36
+ *
37
+ * This method provides a convenient way to register tools.
38
+ *
39
+ * @param name - Tool name
40
+ * @param description - Tool description
41
+ * @param inputSchema - Zod schema for input validation
42
+ * @param handler - Function to handle tool invocations
43
+ */
44
+ addTool(name, description, inputSchema, handler) {
45
+ const wrappedHandler = async (args, _extra) => {
46
+ const startTime = Date.now();
47
+ try {
48
+ const result = await handler(args);
49
+ const runTimeMs = Date.now() - startTime;
50
+ await this.telemetry
51
+ ?.sendEventAndFlush('TOOL_CALLED', {
52
+ toolName: name,
53
+ runTimeMs,
54
+ isError: result.isError ?? false,
55
+ })
56
+ .catch(() => { });
57
+ return result;
58
+ }
59
+ catch (error) {
60
+ const runTimeMs = Date.now() - startTime;
61
+ await this.telemetry
62
+ ?.sendEventAndFlush('TOOL_CALLED', {
63
+ toolName: name,
64
+ runTimeMs,
65
+ isError: true,
66
+ })
67
+ .catch(() => { });
68
+ throw error;
69
+ }
70
+ };
71
+ // Use the new registerTool API (tool() is deprecated)
72
+ this.registerTool(name, { description, inputSchema }, wrappedHandler);
73
+ }
74
+ /**
75
+ * Connect to a transport.
76
+ */
77
+ async connect(transport) {
78
+ try {
79
+ await super.connect(transport);
80
+ const statusPromise = this.isConnected()
81
+ ? this.telemetry?.sendEventAndFlush('SERVER_STATUS', { status: 'started' })
82
+ : this.telemetry?.sendEventAndFlush('SERVER_STATUS', {
83
+ status: 'error',
84
+ errorMessage: 'Server not connected after connect() call',
85
+ });
86
+ await (statusPromise ?? Promise.resolve()).catch(() => { });
87
+ }
88
+ catch (error) {
89
+ const errorPromise = this.telemetry?.sendEventAndFlush('SERVER_STATUS', {
90
+ status: 'error',
91
+ errorMessage: error instanceof Error ? error.message : String(error),
92
+ });
93
+ await (errorPromise ?? Promise.resolve()).catch(() => { });
94
+ throw error;
95
+ }
96
+ }
97
+ }
98
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1,168 @@
1
+ /**
2
+ * Services module providing dependency injection for MCP tools.
3
+ *
4
+ * The {@link Services} class is the central dependency container for tools,
5
+ * providing:
6
+ * - Pre-resolved B2CInstance for WebDAV/OCAPI operations
7
+ * - Pre-resolved MRT authentication for Managed Runtime operations
8
+ * - MRT project/environment configuration
9
+ * - File system utilities for local operations
10
+ *
11
+ * ## Creating Services
12
+ *
13
+ * Use {@link Services.fromResolvedConfig} with an already-resolved configuration:
14
+ *
15
+ * ```typescript
16
+ * // In a command that extends BaseCommand
17
+ * const services = Services.fromResolvedConfig(this.resolvedConfig);
18
+ * ```
19
+ *
20
+ * ## Resolution Pattern
21
+ *
22
+ * Both B2CInstance and MRT auth are resolved once at server startup (not on each tool call).
23
+ * This provides fail-fast behavior and consistent performance.
24
+ *
25
+ * **B2C Instance** (for WebDAV/OCAPI tools):
26
+ * - Flags (highest priority) merged with dw.json (auto-discovered or via --config)
27
+ *
28
+ * **MRT Auth** (for Managed Runtime tools):
29
+ * 1. `--api-key` flag (oclif also checks `SFCC_MRT_API_KEY` env var)
30
+ * 2. `~/.mobify` config file (or `~/.mobify--[hostname]` if `--cloud-origin` is set)
31
+ *
32
+ * **MRT Origin** (for Managed Runtime API URL):
33
+ * 1. `--cloud-origin` flag (oclif also checks `SFCC_MRT_CLOUD_ORIGIN` env var)
34
+ * 2. `mrtOrigin` field in dw.json
35
+ * 3. Default: `https://cloud.mobify.com`
36
+ *
37
+ * @module services
38
+ */
39
+ import fs from 'node:fs';
40
+ import type { B2CInstance } from '@salesforce/b2c-tooling-sdk';
41
+ import type { AuthStrategy } from '@salesforce/b2c-tooling-sdk/auth';
42
+ import type { ResolvedB2CConfig } from '@salesforce/b2c-tooling-sdk/config';
43
+ /**
44
+ * MRT (Managed Runtime) configuration.
45
+ * Groups auth, project, environment, and origin settings.
46
+ */
47
+ export interface MrtConfig {
48
+ /** Pre-resolved auth strategy for MRT API operations */
49
+ auth?: AuthStrategy;
50
+ /** MRT project slug from --project flag or SFCC_MRT_PROJECT env var */
51
+ project?: string;
52
+ /** MRT environment from --environment flag or SFCC_MRT_ENVIRONMENT env var */
53
+ environment?: string;
54
+ /** MRT API origin URL from --cloud-origin flag, SFCC_MRT_CLOUD_ORIGIN env var, or mrtOrigin in dw.json */
55
+ origin?: string;
56
+ }
57
+ /**
58
+ * Options for Services constructor (internal).
59
+ */
60
+ export interface ServicesOptions {
61
+ /** Pre-resolved B2C instance (if configured) */
62
+ b2cInstance?: B2CInstance;
63
+ /** Pre-resolved MRT configuration (auth, project, environment) */
64
+ mrtConfig?: MrtConfig;
65
+ }
66
+ /**
67
+ * Services class that provides utilities for MCP tools.
68
+ *
69
+ * Use the static `Services.fromResolvedConfig()` factory method to create
70
+ * an instance from an already-resolved configuration.
71
+ *
72
+ * @example
73
+ * ```typescript
74
+ * // In a command that extends BaseCommand
75
+ * const services = Services.fromResolvedConfig(this.resolvedConfig);
76
+ *
77
+ * // Access resolved config
78
+ * services.b2cInstance; // B2CInstance | undefined
79
+ * services.mrtConfig.auth; // AuthStrategy | undefined
80
+ * services.mrtConfig.project; // string | undefined
81
+ * ```
82
+ */
83
+ export declare class Services {
84
+ /**
85
+ * Pre-resolved B2C instance for WebDAV/OCAPI operations.
86
+ * Resolved once at server startup from InstanceCommand flags and dw.json.
87
+ * Undefined if no B2C instance configuration was available.
88
+ */
89
+ readonly b2cInstance?: B2CInstance;
90
+ /**
91
+ * Pre-resolved MRT configuration (auth, project, environment, origin).
92
+ * Resolved once at server startup from MrtCommand flags and ~/.mobify.
93
+ */
94
+ readonly mrtConfig: MrtConfig;
95
+ constructor(opts?: ServicesOptions);
96
+ /**
97
+ * Creates a Services instance from an already-resolved configuration.
98
+ *
99
+ * @param config - Already-resolved configuration from BaseCommand.resolvedConfig
100
+ * @returns Services instance with resolved config
101
+ *
102
+ * @example
103
+ * ```typescript
104
+ * // In a command that extends BaseCommand
105
+ * const services = Services.fromResolvedConfig(this.resolvedConfig);
106
+ * ```
107
+ */
108
+ static fromResolvedConfig(config: ResolvedB2CConfig): Services;
109
+ /**
110
+ * Check if a file or directory exists.
111
+ *
112
+ * @param targetPath - Path to check
113
+ * @returns True if exists, false otherwise
114
+ */
115
+ exists(targetPath: string): boolean;
116
+ /**
117
+ * Get the current working directory.
118
+ */
119
+ getCwd(): string;
120
+ /**
121
+ * Get the user's home directory.
122
+ */
123
+ getHomeDir(): string;
124
+ /**
125
+ * Get OS platform information.
126
+ */
127
+ getPlatform(): NodeJS.Platform;
128
+ /**
129
+ * Get system temporary directory.
130
+ */
131
+ getTmpDir(): string;
132
+ /**
133
+ * Join path segments.
134
+ *
135
+ * @param segments - Path segments to join
136
+ * @returns Joined path
137
+ */
138
+ joinPath(...segments: string[]): string;
139
+ /**
140
+ * List directory contents.
141
+ *
142
+ * @param dirPath - Directory path to list
143
+ * @returns Array of directory entries
144
+ */
145
+ listDirectory(dirPath: string): fs.Dirent[];
146
+ /**
147
+ * Read a file from the filesystem.
148
+ *
149
+ * @param filePath - Path to the file
150
+ * @param encoding - File encoding (default: utf8)
151
+ * @returns File contents as a string
152
+ */
153
+ readFile(filePath: string, encoding?: 'ascii' | 'base64' | 'hex' | 'latin1' | 'utf8'): string;
154
+ /**
155
+ * Resolve a path relative to the current working directory.
156
+ *
157
+ * @param segments - Path segments to join and resolve
158
+ * @returns Absolute path
159
+ */
160
+ resolvePath(...segments: string[]): string;
161
+ /**
162
+ * Get file or directory stats.
163
+ *
164
+ * @param targetPath - Path to get stats for
165
+ * @returns File stats object
166
+ */
167
+ stat(targetPath: string): fs.Stats;
168
+ }