diff --git a/.changeset/vscode-sfcc-config-env.md b/.changeset/vscode-sfcc-config-env.md new file mode 100644 index 000000000..1422b544e --- /dev/null +++ b/.changeset/vscode-sfcc-config-env.md @@ -0,0 +1,5 @@ +--- +'b2c-vs-extension': patch +--- + +Honor the `SFCC_CONFIG` environment variable when resolving instance configuration. Previously the extension only looked for a `dw.json` in the workspace folder and ignored a global `dw.json` referenced by `SFCC_CONFIG`, so projects that relied on that env var (e.g. alongside a project `.env`) resolved to "No B2C Commerce instance configured". The extension now threads `SFCC_CONFIG` through as the explicit config path, matching the CLI's `--config` flag. diff --git a/packages/b2c-vs-extension/package.json b/packages/b2c-vs-extension/package.json index 8ddef7d47..745b5019a 100644 --- a/packages/b2c-vs-extension/package.json +++ b/packages/b2c-vs-extension/package.json @@ -2278,7 +2278,7 @@ "@types/react-dom": "18.3.1", "@types/vscode": "^1.105.1", "@vscode/test-cli": "^0.0.12", - "@vscode/test-electron": "^2.5.2", + "@vscode/test-electron": "^3.1.0", "@vscode/vsce": "^3.9.1", "c8": "catalog:", "esbuild": "^0.24.0", diff --git a/packages/b2c-vs-extension/src/config-provider.ts b/packages/b2c-vs-extension/src/config-provider.ts index 69c3f884d..3a564319d 100644 --- a/packages/b2c-vs-extension/src/config-provider.ts +++ b/packages/b2c-vs-extension/src/config-provider.ts @@ -326,7 +326,17 @@ export class B2CExtensionConfig implements vscode.Disposable { } } - const config = await resolveConfig({}, {workingDirectory, sourcesBefore: [new EnvSource()]}); + // Honor SFCC_CONFIG (an explicit dw.json path), the same env var the CLI + // exposes via its `--config` flag. This is a file *path*, not a config + // field, so EnvSource can't carry it — it must be threaded through as + // `configPath`. Read it after the .env load so a project .env can set or + // override it, matching CLI precedence. Falls back to workingDirectory/dw.json. + const configPath = process.env.SFCC_CONFIG || undefined; + if (configPath) { + this.log.appendLine(`[Config] Using explicit config path from SFCC_CONFIG: ${configPath}`); + } + + const config = await resolveConfig({}, {workingDirectory, configPath, sourcesBefore: [new EnvSource()]}); this.config = config; if (!config.hasB2CInstanceConfig()) { diff --git a/packages/b2c-vs-extension/src/test/config-provider.test.ts b/packages/b2c-vs-extension/src/test/config-provider.test.ts index b56b5a425..4056b2ab7 100644 --- a/packages/b2c-vs-extension/src/test/config-provider.test.ts +++ b/packages/b2c-vs-extension/src/test/config-provider.test.ts @@ -4,6 +4,8 @@ * For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0 */ import * as assert from 'assert'; +import * as fs from 'fs'; +import * as os from 'os'; import * as path from 'path'; import * as vscode from 'vscode'; import {B2CExtensionConfig} from '../config-provider.js'; @@ -56,4 +58,37 @@ suite('B2CExtensionConfig workspace discovery', () => { log.dispose(); } }); + + test('honors SFCC_CONFIG (global dw.json path) over the workspace dw.json', async () => { + // Regression: the extension previously ignored SFCC_CONFIG (a dw.json *path*, + // as exposed by the CLI's --config flag) and only ever loaded a dw.json from + // the workspace folder. A project relying on a global dw.json via SFCC_CONFIG + // resolved to "No B2C Commerce instance configured". + const dir = fs.mkdtempSync(path.join(os.tmpdir(), 'b2c-sfcc-config-')); + const globalDwJson = path.join(dir, 'dw.json'); + fs.writeFileSync(globalDwJson, JSON.stringify({hostname: 'global-config.invalid', username: 'u', password: 'p'})); + + const previous = process.env.SFCC_CONFIG; + process.env.SFCC_CONFIG = globalDwJson; + + const log = vscode.window.createOutputChannel('B2C Config SFCC_CONFIG Test'); + const provider = new B2CExtensionConfig(log); + + try { + await provider.ensureResolved(); + const instance = provider.getInstance(); + assert.ok(instance, 'expected an instance resolved from SFCC_CONFIG'); + assert.strictEqual(instance.config.hostname, 'global-config.invalid'); + assert.strictEqual(provider.getConfigError(), null); + } finally { + provider.dispose(); + log.dispose(); + if (previous === undefined) { + delete process.env.SFCC_CONFIG; + } else { + process.env.SFCC_CONFIG = previous; + } + fs.rmSync(dir, {recursive: true, force: true}); + } + }); }); diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 53edf2aab..243c682e8 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -627,15 +627,15 @@ importers: '@salesforce/b2c-tooling-sdk': specifier: workspace:* version: link:../b2c-tooling-sdk - swagger-ui-dist: - specifier: ^5.18.0 - version: 5.32.0 react: specifier: 18.3.1 version: 18.3.1 react-dom: specifier: 18.3.1 version: 18.3.1(react@18.3.1) + swagger-ui-dist: + specifier: ^5.18.0 + version: 5.32.0 vscode-html-languageservice: specifier: 'catalog:' version: 5.6.0 @@ -662,8 +662,8 @@ importers: specifier: ^0.0.12 version: 0.0.12 '@vscode/test-electron': - specifier: ^2.5.2 - version: 2.5.2 + specifier: ^3.1.0 + version: 3.1.0 '@vscode/vsce': specifier: ^3.9.1 version: 3.9.1 @@ -2678,6 +2678,7 @@ packages: '@modelcontextprotocol/inspector@0.18.0': resolution: {integrity: sha512-aBrBDaI8MtvyS9j3TMRgTHZaOwbe/zh2rbIVplIBtxWifaSfvQX9DbnoI3xv9sZjgeFyF/3CwZdfEVTUx2RfBg==} engines: {node: '>=22.7.5'} + deprecated: 'v1 is deprecated. Upgrade to v2: npm i @modelcontextprotocol/inspector@latest. v1 gets security fixes only, published under the v1-latest tag.' hasBin: true '@modelcontextprotocol/sdk@1.26.0': @@ -4325,9 +4326,9 @@ packages: engines: {node: '>=18'} hasBin: true - '@vscode/test-electron@2.5.2': - resolution: {integrity: sha512-8ukpxv4wYe0iWMRQU18jhzJOHkeGKbnw7xWRX3Zw1WJA4cEKbHcmmLPdPrPtL6rhDcrlCZN+xKRpv09n4gRHYg==} - engines: {node: '>=16'} + '@vscode/test-electron@3.1.0': + resolution: {integrity: sha512-CRqv5u+YYoseuNVJ6Tyo4k0sF0mx4qnKMihRB0PjsUF8Dc0WKtCXo6CNL6nWWm5esfFQsQA/pejMj4ZbpJVLTw==} + engines: {node: '>=22'} '@vscode/vsce-sign-alpine-arm64@2.0.6': resolution: {integrity: sha512-wKkJBsvKF+f0GfsUuGT0tSW0kZL87QggEiqNqK6/8hvqsXvpx8OsTEc3mnE1kejkh5r+qUyQ7PtF8jZYN0mo8Q==} @@ -5349,6 +5350,10 @@ packages: resolution: {integrity: sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww==} engines: {node: '>=10.13.0'} + enhanced-resolve@5.24.5: + resolution: {integrity: sha512-L1l8TNvomm6UVW5B253AGxQagSQr+vGwhMlrrfRS2qmhx46AMpMVJKQYLvWYbysTMY8VoicOvzHzoHMbyzB+4A==} + engines: {node: '>=10.13.0'} + enquirer@2.4.1: resolution: {integrity: sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==} engines: {node: '>=8.6'} @@ -6877,6 +6882,11 @@ packages: engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} hasBin: true + mocha@11.8.0: + resolution: {integrity: sha512-VyCeUdGN3A9lmCTTgG4yuvY9ixxaDk+xt2R/7/+1AP6EqNG+G9OKkzBwhVtVYoNX8YsxNSgAl8mOv3IAeOpFbw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + hasBin: true + mri@1.2.0: resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==} engines: {node: '>=4'} @@ -8102,6 +8112,10 @@ packages: resolution: {integrity: sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==} engines: {node: '>=6'} + tapable@2.3.3: + resolution: {integrity: sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==} + engines: {node: '>=6'} + tar-fs@2.1.4: resolution: {integrity: sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==} @@ -8126,8 +8140,8 @@ packages: resolution: {integrity: sha512-lk+vH+MccxNqgVqSnkMVKx4VLJfnLjDBGzH16JVZjKE2DoxP57s6/vt6JmXV5I3jBcfGrxNrYtC+mPtU7WJztA==} engines: {node: '>=18'} - test-exclude@7.0.1: - resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} + test-exclude@7.0.2: + resolution: {integrity: sha512-u9E6A+ZDYdp7a4WnarkXPZOx8Ilz46+kby6p1yZ8zsGTz9gYa6FIS7lj2oezzNKmtdyyJNNmmXDppga5GB7kSw==} engines: {node: '>=18'} test-exclude@8.0.0: @@ -13218,16 +13232,16 @@ snapshots: '@types/mocha': 10.0.10 c8: 10.1.3 chokidar: 3.6.0 - enhanced-resolve: 5.18.3 + enhanced-resolve: 5.24.5 glob: 10.5.0 minimatch: 9.0.9 - mocha: 11.7.5 + mocha: 11.8.0 supports-color: 10.2.2 yargs: 17.7.2(patch_hash=93c6b35288ee71f8125ecb75d3f2a609bfaf8917db71d23b4e0034f39a0d9961) transitivePeerDependencies: - monocart-coverage-reports - '@vscode/test-electron@2.5.2': + '@vscode/test-electron@3.1.0': dependencies: http-proxy-agent: 7.0.2 https-proxy-agent: 7.0.6(supports-color@10.2.2) @@ -13743,7 +13757,7 @@ snapshots: istanbul-lib-coverage: 3.2.2 istanbul-lib-report: 3.0.1 istanbul-reports: 3.2.0 - test-exclude: 7.0.1 + test-exclude: 7.0.2 v8-to-istanbul: 9.3.0 yargs: 17.7.2(patch_hash=93c6b35288ee71f8125ecb75d3f2a609bfaf8917db71d23b4e0034f39a0d9961) yargs-parser: 21.1.1 @@ -14302,6 +14316,11 @@ snapshots: graceful-fs: 4.2.11 tapable: 2.3.0 + enhanced-resolve@5.24.5: + dependencies: + graceful-fs: 4.2.11 + tapable: 2.3.3 + enquirer@2.4.1: dependencies: ansi-colors: 4.1.3 @@ -16153,6 +16172,30 @@ snapshots: yargs-parser: 21.1.1 yargs-unparser: 2.0.0 + mocha@11.8.0: + dependencies: + browser-stdout: 1.3.1 + chokidar: 4.0.3 + debug: 4.4.3(supports-color@8.1.1) + diff: 7.0.0 + escape-string-regexp: 4.0.0 + find-up: 5.0.0 + glob: 10.5.0 + he: 1.2.0 + is-path-inside: 3.0.3 + js-yaml: 4.2.0 + log-symbols: 4.1.0 + minimatch: 9.0.9 + ms: 2.1.3 + picocolors: 1.1.1 + serialize-javascript: 7.0.6 + strip-json-comments: 3.1.1 + supports-color: 8.1.1 + workerpool: 9.3.4 + yargs: 17.7.2(patch_hash=93c6b35288ee71f8125ecb75d3f2a609bfaf8917db71d23b4e0034f39a0d9961) + yargs-parser: 21.1.1 + yargs-unparser: 2.0.0 + mri@1.2.0: {} ms@2.0.0: {} @@ -17519,6 +17562,8 @@ snapshots: tapable@2.3.0: {} + tapable@2.3.3: {} + tar-fs@2.1.4: dependencies: chownr: 1.1.4 @@ -17572,11 +17617,11 @@ snapshots: ansi-escapes: 7.2.0 supports-hyperlinks: 3.2.0 - test-exclude@7.0.1: + test-exclude@7.0.2: dependencies: '@istanbuljs/schema': 0.1.3 glob: 10.5.0 - minimatch: 9.0.9 + minimatch: 10.2.4 test-exclude@8.0.0: dependencies: