@salesforce/b2c-tooling-sdk 2.3.0 → 2.5.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/data/guides/enrichment.json +291 -0
- package/data/guides/index.json +426 -37
- package/data/schemas/dw.schema.json +590 -0
- package/data/tooling/index.json +18 -9
- package/dist/esm/cli/base-command.d.ts +20 -1
- package/dist/esm/cli/base-command.js +61 -11
- package/dist/esm/cli/base-command.js.map +1 -1
- package/dist/esm/cli/cartridge-command.js +2 -1
- package/dist/esm/cli/cartridge-command.js.map +1 -1
- package/dist/esm/cli/command-search.d.ts +85 -0
- package/dist/esm/cli/command-search.js +147 -0
- package/dist/esm/cli/command-search.js.map +1 -0
- package/dist/esm/cli/config.d.ts +10 -1
- package/dist/esm/cli/config.js +18 -9
- package/dist/esm/cli/config.js.map +1 -1
- package/dist/esm/cli/hooks.d.ts +13 -0
- package/dist/esm/cli/hooks.js +11 -0
- package/dist/esm/cli/hooks.js.map +1 -1
- package/dist/esm/cli/index.d.ts +2 -0
- package/dist/esm/cli/index.js +2 -0
- package/dist/esm/cli/index.js.map +1 -1
- package/dist/esm/cli/instance-command.d.ts +1 -0
- package/dist/esm/cli/instance-command.js +2 -1
- package/dist/esm/cli/instance-command.js.map +1 -1
- package/dist/esm/cli/mrt-command.d.ts +3 -2
- package/dist/esm/cli/mrt-command.js +4 -4
- package/dist/esm/cli/mrt-command.js.map +1 -1
- package/dist/esm/cli/oauth-command.d.ts +1 -0
- package/dist/esm/cli/ods-command.d.ts +1 -0
- package/dist/esm/cli/webdav-command.d.ts +1 -0
- package/dist/esm/clients/custom-apis.d.ts +36 -2
- package/dist/esm/clients/custom-apis.js +57 -4
- package/dist/esm/clients/custom-apis.js.map +1 -1
- package/dist/esm/clients/index.d.ts +1 -1
- package/dist/esm/clients/index.js +1 -1
- package/dist/esm/clients/index.js.map +1 -1
- package/dist/esm/clients/scapi-backend-utils.d.ts +15 -0
- package/dist/esm/clients/scapi-backend-utils.js +28 -1
- package/dist/esm/clients/scapi-backend-utils.js.map +1 -1
- package/dist/esm/clients/scapi-fallback-backend.js +2 -2
- package/dist/esm/clients/scapi-fallback-backend.js.map +1 -1
- package/dist/esm/clients/scapi-schemas.generated.d.ts +2 -2
- package/dist/esm/compat/dispatcher.js +2 -2
- package/dist/esm/compat/dispatcher.js.map +1 -1
- package/dist/esm/config/config-origins.d.ts +19 -0
- package/dist/esm/config/config-origins.js +11 -0
- package/dist/esm/config/config-origins.js.map +1 -0
- package/dist/esm/config/config-write.d.ts +86 -0
- package/dist/esm/config/config-write.js +296 -0
- package/dist/esm/config/config-write.js.map +1 -0
- package/dist/esm/config/dw-json-schema.d.ts +14 -0
- package/dist/esm/config/dw-json-schema.js +269 -0
- package/dist/esm/config/dw-json-schema.js.map +1 -0
- package/dist/esm/config/dw-json.d.ts +2 -0
- package/dist/esm/config/dw-json.js +10 -6
- package/dist/esm/config/dw-json.js.map +1 -1
- package/dist/esm/config/index.d.ts +13 -4
- package/dist/esm/config/index.js +8 -3
- package/dist/esm/config/index.js.map +1 -1
- package/dist/esm/config/instance-manager.d.ts +64 -28
- package/dist/esm/config/instance-manager.js +145 -63
- package/dist/esm/config/instance-manager.js.map +1 -1
- package/dist/esm/config/mapping.d.ts +5 -0
- package/dist/esm/config/mapping.js +20 -1
- package/dist/esm/config/mapping.js.map +1 -1
- package/dist/esm/config/project-environment.d.ts +62 -0
- package/dist/esm/config/project-environment.js +113 -0
- package/dist/esm/config/project-environment.js.map +1 -1
- package/dist/esm/config/resolver.d.ts +22 -0
- package/dist/esm/config/resolver.js +106 -37
- package/dist/esm/config/resolver.js.map +1 -1
- package/dist/esm/config/sources/dw-json-source.d.ts +9 -1
- package/dist/esm/config/sources/dw-json-source.js +59 -23
- package/dist/esm/config/sources/dw-json-source.js.map +1 -1
- package/dist/esm/config/sources/env-source.d.ts +70 -9
- package/dist/esm/config/sources/env-source.js +205 -47
- package/dist/esm/config/sources/env-source.js.map +1 -1
- package/dist/esm/config/sources/index.d.ts +1 -1
- package/dist/esm/config/sources/index.js +1 -1
- package/dist/esm/config/sources/index.js.map +1 -1
- package/dist/esm/config/types.d.ts +53 -3
- package/dist/esm/docs/search.js +3 -1
- package/dist/esm/docs/search.js.map +1 -1
- package/dist/esm/docs/types.d.ts +3 -1
- package/dist/esm/guidance/bundle.d.ts +33 -0
- package/dist/esm/guidance/bundle.js +268 -0
- package/dist/esm/guidance/bundle.js.map +1 -0
- package/dist/esm/guidance/catalog.d.ts +8 -1
- package/dist/esm/guidance/catalog.js +48 -6
- package/dist/esm/guidance/catalog.js.map +1 -1
- package/dist/esm/guidance/index.d.ts +1 -0
- package/dist/esm/guidance/index.js +1 -0
- package/dist/esm/guidance/index.js.map +1 -1
- package/dist/esm/guidance/types.d.ts +17 -1
- package/dist/esm/guidance/types.js.map +1 -1
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/operations/jobs/run-system-job.js +2 -2
- package/dist/esm/operations/jobs/run-system-job.js.map +1 -1
- package/dist/esm/plugins/discovery.js +2 -1
- package/dist/esm/plugins/discovery.js.map +1 -1
- package/dist/esm/scapi/catalog.d.ts +5 -2
- package/dist/esm/scapi/catalog.js.map +1 -1
- package/dist/esm/scapi/index.d.ts +6 -2
- package/dist/esm/scapi/index.js +4 -2
- package/dist/esm/scapi/index.js.map +1 -1
- package/dist/esm/scapi/live.d.ts +14 -3
- package/dist/esm/scapi/live.js +33 -5
- package/dist/esm/scapi/live.js.map +1 -1
- package/dist/esm/scapi/local.d.ts +26 -0
- package/dist/esm/scapi/local.js +143 -0
- package/dist/esm/scapi/local.js.map +1 -0
- package/dist/esm/scapi/request.d.ts +2 -2
- package/dist/esm/scapi/request.js +4 -2
- package/dist/esm/scapi/request.js.map +1 -1
- package/dist/esm/scapi/runtime.d.ts +5 -0
- package/dist/esm/scapi/runtime.js.map +1 -1
- package/dist/esm/scapi/schema-source.d.ts +90 -0
- package/dist/esm/scapi/schema-source.js +146 -0
- package/dist/esm/scapi/schema-source.js.map +1 -0
- package/dist/esm/scapi/worker-source.js +31 -7
- package/dist/esm/scapi/worker-source.js.map +1 -1
- package/dist/esm/telemetry/telemetry.d.ts +1 -0
- package/dist/esm/telemetry/telemetry.js +18 -1
- package/dist/esm/telemetry/telemetry.js.map +1 -1
- package/dist/esm/telemetry/types.d.ts +9 -0
- package/dist/esm/test-utils/config-isolation.js +21 -15
- package/dist/esm/test-utils/config-isolation.js.map +1 -1
- package/dist/esm/ux/agent-context.d.ts +69 -0
- package/dist/esm/ux/agent-context.js +133 -0
- package/dist/esm/ux/agent-context.js.map +1 -0
- package/dist/esm/ux/confirm.d.ts +27 -0
- package/dist/esm/ux/confirm.js +32 -0
- package/dist/esm/ux/confirm.js.map +1 -1
- package/dist/esm/ux/index.d.ts +2 -1
- package/dist/esm/ux/index.js +2 -1
- package/dist/esm/ux/index.js.map +1 -1
- package/node_modules/@salesforce/b2c-api-schemas/manifest.json +83 -42
- package/node_modules/@salesforce/b2c-api-schemas/package.json +1 -1
- package/node_modules/@salesforce/b2c-api-schemas/scapi/cdn/zones/v1.json +6798 -238
- package/node_modules/@salesforce/b2c-api-schemas/scapi/checkout/orders/v1.json +2296 -205
- package/node_modules/@salesforce/b2c-api-schemas/scapi/checkout/shopper-baskets/v1.json +5571 -666
- package/node_modules/@salesforce/b2c-api-schemas/scapi/checkout/shopper-baskets/v2.json +6062 -371
- package/node_modules/@salesforce/b2c-api-schemas/scapi/checkout/shopper-orders/v1.json +3426 -360
- package/node_modules/@salesforce/b2c-api-schemas/scapi/checkout/shopper-payments/v1.json +351 -99
- package/node_modules/@salesforce/b2c-api-schemas/scapi/configuration/cors/v1.json +172 -12
- package/node_modules/@salesforce/b2c-api-schemas/scapi/configuration/preferences/v1.json +1497 -111
- package/node_modules/@salesforce/b2c-api-schemas/scapi/configuration/shopper-configurations/v1.json +202 -36
- package/node_modules/@salesforce/b2c-api-schemas/scapi/configuration/timeouts/v1.json +79 -10
- package/node_modules/@salesforce/b2c-api-schemas/scapi/custom-object/custom-objects/v1.json +785 -49
- package/node_modules/@salesforce/b2c-api-schemas/scapi/custom-object/shopper-custom-objects/v1.json +191 -40
- package/node_modules/@salesforce/b2c-api-schemas/scapi/customer/customers/v1.json +1483 -107
- package/node_modules/@salesforce/b2c-api-schemas/scapi/customer/shopper-customers/v1.json +4854 -787
- package/node_modules/@salesforce/b2c-api-schemas/scapi/dx/custom-apis/v1.json +119 -15
- package/node_modules/@salesforce/b2c-api-schemas/scapi/dx/object-definitions/v1.json +1699 -80
- package/node_modules/@salesforce/b2c-api-schemas/scapi/dx/scapi-schemas/v1.json +252 -18
- package/node_modules/@salesforce/b2c-api-schemas/scapi/dx/scripts/v1.json +329 -23
- package/node_modules/@salesforce/b2c-api-schemas/scapi/experience/experiences/v1.json +4208 -234
- package/node_modules/@salesforce/b2c-api-schemas/scapi/experience/shopper-experience/v1.json +1591 -247
- package/node_modules/@salesforce/b2c-api-schemas/scapi/intelligence/analytics/v1.json +396 -8
- package/node_modules/@salesforce/b2c-api-schemas/scapi/inventory/availability/v1.json +1242 -69
- package/node_modules/@salesforce/b2c-api-schemas/scapi/inventory/impex/v1.json +2354 -248
- package/node_modules/@salesforce/b2c-api-schemas/scapi/inventory/reservation/v1.json +1550 -45
- package/node_modules/@salesforce/b2c-api-schemas/scapi/inventory/segmentation/v1.json +6615 -0
- package/node_modules/@salesforce/b2c-api-schemas/scapi/merchant/roles/v1.json +1520 -59
- package/node_modules/@salesforce/b2c-api-schemas/scapi/merchant/users/v1.json +397 -17
- package/node_modules/@salesforce/b2c-api-schemas/scapi/observability/metrics/v1.json +1241 -27
- package/node_modules/@salesforce/b2c-api-schemas/scapi/operation/jobs/v1.json +1069 -68
- package/node_modules/@salesforce/b2c-api-schemas/scapi/operation/replications/v1.json +410 -23
- package/node_modules/@salesforce/b2c-api-schemas/scapi/pricing/assignments/v1.json +502 -102
- package/node_modules/@salesforce/b2c-api-schemas/scapi/pricing/campaigns/v1.json +1112 -94
- package/node_modules/@salesforce/b2c-api-schemas/scapi/pricing/coupons/v1.json +820 -93
- package/node_modules/@salesforce/b2c-api-schemas/scapi/pricing/gift-certificates/v1.json +845 -92
- package/node_modules/@salesforce/b2c-api-schemas/scapi/pricing/promotions/v1.json +2716 -674
- package/node_modules/@salesforce/b2c-api-schemas/scapi/pricing/shopper-gift-certificates/v1.json +130 -47
- package/node_modules/@salesforce/b2c-api-schemas/scapi/pricing/shopper-promotions/v1.json +233 -63
- package/node_modules/@salesforce/b2c-api-schemas/scapi/pricing/source-code-groups/v1.json +630 -70
- package/node_modules/@salesforce/b2c-api-schemas/scapi/product/catalogs/v1.json +2886 -348
- package/node_modules/@salesforce/b2c-api-schemas/scapi/product/inventory-lists/v1.json +520 -19
- package/node_modules/@salesforce/b2c-api-schemas/scapi/product/price-books/v1.json +3115 -293
- package/node_modules/@salesforce/b2c-api-schemas/scapi/product/products/v1.json +3313 -138
- package/node_modules/@salesforce/b2c-api-schemas/scapi/product/shopper-availability/v1.json +266 -52
- package/node_modules/@salesforce/b2c-api-schemas/scapi/product/shopper-delivery-estimates/v1.json +256 -48
- package/node_modules/@salesforce/b2c-api-schemas/scapi/product/shopper-products/v1.json +1744 -306
- package/node_modules/@salesforce/b2c-api-schemas/scapi/search/shopper-search/v1.json +1661 -120
- package/node_modules/@salesforce/b2c-api-schemas/scapi/shopper/auth/v1.json +2174 -118
- package/node_modules/@salesforce/b2c-api-schemas/scapi/shopper/auth-admin/v1.json +1373 -24
- package/node_modules/@salesforce/b2c-api-schemas/scapi/shopper/consents/v1.json +531 -20
- package/node_modules/@salesforce/b2c-api-schemas/scapi/shopper/shopper-agents/v1.json +154 -6
- package/node_modules/@salesforce/b2c-api-schemas/scapi/shopper/shopper-consents/v1.json +596 -79
- package/node_modules/@salesforce/b2c-api-schemas/scapi/shopper/shopper-context/v1.json +456 -42
- package/node_modules/@salesforce/b2c-api-schemas/scapi/site/seo/v1.json +101 -23
- package/node_modules/@salesforce/b2c-api-schemas/scapi/site/shopper-seo/v1.json +184 -41
- package/node_modules/@salesforce/b2c-api-schemas/scapi/site/sites/v1.json +995 -47
- package/node_modules/@salesforce/b2c-api-schemas/scapi/store/shopper-stores/v1.json +370 -67
- package/node_modules/@salesforce/b2c-api-schemas/scapi/store/store-redirect-mappings/v1.json +319 -11
- package/node_modules/@salesforce/b2c-api-schemas/scapi/store/stores/v1.json +1109 -64
- package/node_modules/@salesforce/b2c-api-schemas/scapi/storefront/deployments/v1.json +1442 -0
- package/node_modules/@salesforce/b2c-api-schemas/scapi/storefront/environments/v1.json +4293 -0
- package/node_modules/@salesforce/b2c-api-schemas/scapi/storefront/storefronts/v1.json +1371 -0
- package/package.json +5 -2
- package/specs/scapi-schemas-v1.yaml +4 -1
|
@@ -0,0 +1,296 @@
|
|
|
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
|
+
/**
|
|
7
|
+
* Read and write individual configuration fields at the source that supplies them.
|
|
8
|
+
*
|
|
9
|
+
* Writes go to the highest-priority source currently supplying a field, so the
|
|
10
|
+
* new value always takes effect. A field no source supplies goes to the entry
|
|
11
|
+
* that selected the instance (for example the active dw.json config). Sources
|
|
12
|
+
* that don't implement {@link ConfigSource.updateConfig} (shell environment,
|
|
13
|
+
* ~/.mobify, package.json) are never written; credential stores are written
|
|
14
|
+
* through {@link ConfigSource.storeCredential} for their declared fields.
|
|
15
|
+
*
|
|
16
|
+
* @module config/config-write
|
|
17
|
+
*/
|
|
18
|
+
import { getConfigOrigins } from './config-origins.js';
|
|
19
|
+
import { DW_JSON_FIELDS } from './dw-json-schema.js';
|
|
20
|
+
import { CONFIG_KEY_ALIASES, kebabToCamelCase } from './mapping.js';
|
|
21
|
+
import { CREDENTIAL_GROUPS } from './resolver.js';
|
|
22
|
+
/** dw.json keys whose normalized field has a different name. */
|
|
23
|
+
const FIELD_RENAMES = { oauthScopes: 'scopes' };
|
|
24
|
+
/** dw.json keys managed by other commands (`setup instance ...`) or shorthands of another key. */
|
|
25
|
+
const UNSETTABLE_KEYS = new Set(['name', 'active', 'user-auth']);
|
|
26
|
+
/** Error raised when a configuration field can't be read or written safely. */
|
|
27
|
+
export class ConfigWriteError extends Error {
|
|
28
|
+
code;
|
|
29
|
+
constructor(code, message) {
|
|
30
|
+
super(message);
|
|
31
|
+
this.code = code;
|
|
32
|
+
this.name = 'ConfigWriteError';
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function camelToKebabCase(value) {
|
|
36
|
+
return value.replace(/[A-Z]/g, (char) => `-${char.toLowerCase()}`);
|
|
37
|
+
}
|
|
38
|
+
/** All keys `setup set` accepts, in dw.json order. */
|
|
39
|
+
export function listConfigKeys() {
|
|
40
|
+
return Object.entries(DW_JSON_FIELDS)
|
|
41
|
+
.filter(([key]) => !UNSETTABLE_KEYS.has(key))
|
|
42
|
+
.map(([key, schema]) => {
|
|
43
|
+
const dwKey = kebabToCamelCase(key);
|
|
44
|
+
return { key, field: (FIELD_RENAMES[dwKey] ?? dwKey), schema };
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolve a user-supplied key (dw.json kebab-case, camelCase, a legacy alias,
|
|
49
|
+
* or the normalized field name) to a settable configuration key.
|
|
50
|
+
*
|
|
51
|
+
* @throws ConfigWriteError for unknown or unsettable keys
|
|
52
|
+
*/
|
|
53
|
+
export function resolveConfigKey(input) {
|
|
54
|
+
const trimmed = input.trim();
|
|
55
|
+
const canonical = CONFIG_KEY_ALIASES[trimmed] ?? kebabToCamelCase(trimmed);
|
|
56
|
+
const key = camelToKebabCase(canonical);
|
|
57
|
+
if (UNSETTABLE_KEYS.has(key)) {
|
|
58
|
+
throw new ConfigWriteError('CONFIG_KEY_UNKNOWN', key === 'user-auth'
|
|
59
|
+
? '`user-auth` is shorthand for `auth-methods`; set `auth-methods` instead.'
|
|
60
|
+
: `\`${key}\` is managed by \`b2c setup instance\` commands.`);
|
|
61
|
+
}
|
|
62
|
+
const found = listConfigKeys().find((entry) => entry.key === key || entry.field === canonical);
|
|
63
|
+
if (!found) {
|
|
64
|
+
throw new ConfigWriteError('CONFIG_KEY_UNKNOWN', `Unknown configuration key "${input}". Keys use dw.json names, for example: ${listConfigKeys()
|
|
65
|
+
.slice(0, 6)
|
|
66
|
+
.map((entry) => entry.key)
|
|
67
|
+
.join(', ')}.`);
|
|
68
|
+
}
|
|
69
|
+
return found;
|
|
70
|
+
}
|
|
71
|
+
function describeSchema(schema) {
|
|
72
|
+
if (Array.isArray(schema.oneOf))
|
|
73
|
+
return schema.oneOf.map(describeSchema).join(' or ');
|
|
74
|
+
if (Array.isArray(schema.enum))
|
|
75
|
+
return `one of ${schema.enum.join(', ')}`;
|
|
76
|
+
if (schema.type === 'array' && schema.items)
|
|
77
|
+
return `array of ${describeSchema(schema.items)}`;
|
|
78
|
+
return String(schema.type ?? 'value');
|
|
79
|
+
}
|
|
80
|
+
/** Validate a value against the JSON Schema subset used by the dw.json schema. */
|
|
81
|
+
function validate(schema, value, path) {
|
|
82
|
+
if (Array.isArray(schema.oneOf)) {
|
|
83
|
+
const options = schema.oneOf;
|
|
84
|
+
return options.some((option) => validate(option, value, path) === undefined)
|
|
85
|
+
? undefined
|
|
86
|
+
: `${path} must be ${describeSchema(schema)}`;
|
|
87
|
+
}
|
|
88
|
+
switch (schema.type) {
|
|
89
|
+
case 'array': {
|
|
90
|
+
if (!Array.isArray(value))
|
|
91
|
+
return `${path} must be an array`;
|
|
92
|
+
for (const [index, item] of value.entries()) {
|
|
93
|
+
const error = schema.items ? validate(schema.items, item, `${path}[${index}]`) : undefined;
|
|
94
|
+
if (error)
|
|
95
|
+
return error;
|
|
96
|
+
}
|
|
97
|
+
break;
|
|
98
|
+
}
|
|
99
|
+
case 'boolean': {
|
|
100
|
+
if (typeof value !== 'boolean')
|
|
101
|
+
return `${path} must be true or false`;
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
case 'object': {
|
|
105
|
+
if (!value || typeof value !== 'object' || Array.isArray(value))
|
|
106
|
+
return `${path} must be a JSON object`;
|
|
107
|
+
const record = value;
|
|
108
|
+
const properties = (schema.properties ?? {});
|
|
109
|
+
for (const required of schema.required ?? []) {
|
|
110
|
+
if (record[required] === undefined)
|
|
111
|
+
return `${path}.${required} is required`;
|
|
112
|
+
}
|
|
113
|
+
for (const [name, item] of Object.entries(record)) {
|
|
114
|
+
if (!properties[name]) {
|
|
115
|
+
if (schema.additionalProperties === false)
|
|
116
|
+
return `${path}.${name} is not a known property`;
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
const error = validate(properties[name], item, `${path}.${name}`);
|
|
120
|
+
if (error)
|
|
121
|
+
return error;
|
|
122
|
+
}
|
|
123
|
+
break;
|
|
124
|
+
}
|
|
125
|
+
case 'string': {
|
|
126
|
+
if (typeof value !== 'string')
|
|
127
|
+
return `${path} must be a string`;
|
|
128
|
+
break;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
if (Array.isArray(schema.enum) && !schema.enum.includes(value)) {
|
|
132
|
+
return `${path} must be ${describeSchema(schema)}`;
|
|
133
|
+
}
|
|
134
|
+
return undefined;
|
|
135
|
+
}
|
|
136
|
+
function acceptsStringList(schema) {
|
|
137
|
+
if (Array.isArray(schema.oneOf))
|
|
138
|
+
return schema.oneOf.some(acceptsStringList);
|
|
139
|
+
return schema.type === 'array' && schema.items?.type === 'string';
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Coerce a command-line value to the key's type.
|
|
143
|
+
*
|
|
144
|
+
* String keys keep the text as given. Other keys accept JSON (`true`,
|
|
145
|
+
* `["a","b"]`, `{"level":"NO_DELETE"}`); string-list keys also accept a
|
|
146
|
+
* plain or comma-separated value (`./schemas` becomes `["./schemas"]`).
|
|
147
|
+
*
|
|
148
|
+
* @throws ConfigWriteError when the value doesn't match the key's schema
|
|
149
|
+
*/
|
|
150
|
+
export function parseConfigValue(key, raw) {
|
|
151
|
+
const candidates = [];
|
|
152
|
+
if (key.schema.type === 'string') {
|
|
153
|
+
candidates.push(raw);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
try {
|
|
157
|
+
candidates.push(JSON.parse(raw));
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
// Not JSON; fall through to the plain-text forms below.
|
|
161
|
+
}
|
|
162
|
+
if (acceptsStringList(key.schema)) {
|
|
163
|
+
candidates.push(raw
|
|
164
|
+
.split(',')
|
|
165
|
+
.map((item) => item.trim())
|
|
166
|
+
.filter(Boolean));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
let error;
|
|
170
|
+
for (const candidate of candidates) {
|
|
171
|
+
error = validate(key.schema, candidate, key.key);
|
|
172
|
+
if (!error)
|
|
173
|
+
return candidate;
|
|
174
|
+
}
|
|
175
|
+
throw new ConfigWriteError('CONFIG_VALUE_INVALID', `Invalid value for ${key.key}: ${error ?? `expected ${describeSchema(key.schema)}`}.`);
|
|
176
|
+
}
|
|
177
|
+
function describeSource(info) {
|
|
178
|
+
return info.location ? `${info.name} (${info.location})` : info.name;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* Whether a source can persist `field`: through {@link ConfigSource.updateConfig},
|
|
182
|
+
* or for a credential store, {@link ConfigSource.storeCredential} for a declared
|
|
183
|
+
* credential field.
|
|
184
|
+
*/
|
|
185
|
+
function canWrite(origin, field) {
|
|
186
|
+
const { source } = origin;
|
|
187
|
+
return Boolean(source.updateConfig || (source.storeCredential && source.credentialFields?.includes(field)));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Locate a field in a resolved configuration: which source supplies it and
|
|
191
|
+
* which source a write should update.
|
|
192
|
+
*
|
|
193
|
+
* The target is, in order: the source supplying the field; the source
|
|
194
|
+
* supplying the other half of its credential pair; or, for a field nothing
|
|
195
|
+
* sets, the source that supplied the instance itself (its `instanceName`, else
|
|
196
|
+
* its `hostname`). A derived value (a sandbox hostname worked out from its
|
|
197
|
+
* tenant ID) counts as supplied by the source of the field it came from. Every
|
|
198
|
+
* rule uses only {@link ConfigSourceInfo} and the optional write methods, so
|
|
199
|
+
* plugin sources take part the same way dw.json does.
|
|
200
|
+
*/
|
|
201
|
+
export function locateConfigField(config, field) {
|
|
202
|
+
const origins = getConfigOrigins(config) ?? [];
|
|
203
|
+
const supplies = (info, name) => info.fields.includes(name) && !info.fieldsIgnored?.includes(name);
|
|
204
|
+
/** The origin supplying `name`, following a derived value back to the origin of its base field. */
|
|
205
|
+
const originOf = (name) => {
|
|
206
|
+
const direct = origins.find((origin) => supplies(origin.info, name));
|
|
207
|
+
if (direct)
|
|
208
|
+
return direct;
|
|
209
|
+
const base = config.sources.find((info) => info.derivedFrom && supplies(info, name))?.derivedFrom?.field;
|
|
210
|
+
return base ? origins.find((origin) => supplies(origin.info, base)) : undefined;
|
|
211
|
+
};
|
|
212
|
+
const supplier = config.sources.find((info) => supplies(info, field));
|
|
213
|
+
// A credential pair (client ID + secret) must come from one source, so the
|
|
214
|
+
// other half of a supplied pair decides where this field goes.
|
|
215
|
+
const partners = CREDENTIAL_GROUPS.find((group) => group.includes(field)) ?? [field];
|
|
216
|
+
const own = originOf(field);
|
|
217
|
+
const supplying = own ?? partners.map(originOf).find(Boolean);
|
|
218
|
+
if (supplying) {
|
|
219
|
+
if (!canWrite(supplying, field)) {
|
|
220
|
+
return {
|
|
221
|
+
supplier: own?.info,
|
|
222
|
+
error: new ConfigWriteError('CONFIG_SOURCE_READ_ONLY', own
|
|
223
|
+
? `${field} comes from ${describeSource(supplying.info)}, which can't be written. Change or remove it there.`
|
|
224
|
+
: `${field} pairs with ${partners.filter((partner) => partner !== field).join(', ')} from ${describeSource(supplying.info)}, which can't be written. Set both there.`),
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
return { supplier, target: supplying };
|
|
228
|
+
}
|
|
229
|
+
if (supplier || config.values[field] !== undefined) {
|
|
230
|
+
const base = supplier?.derivedFrom;
|
|
231
|
+
return {
|
|
232
|
+
supplier,
|
|
233
|
+
error: new ConfigWriteError('CONFIG_SOURCE_READ_ONLY', base
|
|
234
|
+
? `${field} is derived from ${base.field}${base.source ? '' : ' given as a flag'}, so it can't be written here.`
|
|
235
|
+
: `${field} comes from ${supplier ? describeSource(supplier) : 'a command-line flag'}, which can't be written.`),
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
// Nothing supplies the field: write it where the instance itself is defined.
|
|
239
|
+
const instanceOrigin = originOf('instanceName') ?? originOf('hostname');
|
|
240
|
+
if (instanceOrigin && canWrite(instanceOrigin, field))
|
|
241
|
+
return { target: instanceOrigin };
|
|
242
|
+
return {
|
|
243
|
+
error: new ConfigWriteError('CONFIG_NO_WRITE_TARGET', instanceOrigin
|
|
244
|
+
? `${field} isn't set, and ${describeSource(instanceOrigin.info)} can't store it.`
|
|
245
|
+
: `${field} isn't set and no instance is selected to write it to. Select one with --instance, mark one active with \`b2c setup instance set-active\`, or create one with \`b2c setup instance create\`.`),
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
/** Persist one field through whichever write method the target source implements. */
|
|
249
|
+
async function persist(config, { source, info, options }, field, value) {
|
|
250
|
+
if (source.updateConfig)
|
|
251
|
+
return source.updateConfig({ [field]: value }, options);
|
|
252
|
+
const instance = config.values.instanceName ?? options.instance;
|
|
253
|
+
if (!instance) {
|
|
254
|
+
throw new ConfigWriteError('CONFIG_NO_WRITE_TARGET', `${source.name} stores credentials per instance, and no instance name is selected. Use --instance.`);
|
|
255
|
+
}
|
|
256
|
+
if (value === undefined) {
|
|
257
|
+
if (!source.removeCredential) {
|
|
258
|
+
throw new ConfigWriteError('CONFIG_SOURCE_READ_ONLY', `${source.name} can't remove ${field}.`);
|
|
259
|
+
}
|
|
260
|
+
await source.removeCredential(instance, field, options);
|
|
261
|
+
}
|
|
262
|
+
else {
|
|
263
|
+
if (typeof value !== 'string')
|
|
264
|
+
throw new ConfigWriteError('CONFIG_VALUE_INVALID', `${field} must be a string.`);
|
|
265
|
+
await source.storeCredential(instance, field, value, options);
|
|
266
|
+
}
|
|
267
|
+
return { location: info.location ?? source.name, instance };
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Set or remove (`value === undefined`) a field at the source that supplies it.
|
|
271
|
+
*
|
|
272
|
+
* @throws ConfigWriteError when the field has no writable target
|
|
273
|
+
*/
|
|
274
|
+
export async function writeConfigField(config, field, value) {
|
|
275
|
+
const location = locateConfigField(config, field);
|
|
276
|
+
if (value === undefined && !location.supplier) {
|
|
277
|
+
throw new ConfigWriteError('CONFIG_NOT_SET', `${field} isn't set.`);
|
|
278
|
+
}
|
|
279
|
+
const base = value === undefined ? location.supplier?.derivedFrom : undefined;
|
|
280
|
+
if (base) {
|
|
281
|
+
throw new ConfigWriteError('CONFIG_NOT_SET', `${field} isn't set; it's derived from ${base.field}${base.source ? ` in ${base.source}` : ''}. Unset ${base.field} instead.`);
|
|
282
|
+
}
|
|
283
|
+
if (!location.target)
|
|
284
|
+
throw location.error;
|
|
285
|
+
const result = await persist(config, location.target, field, value);
|
|
286
|
+
return { ...result, source: location.target.source.name };
|
|
287
|
+
}
|
|
288
|
+
/**
|
|
289
|
+
* Remove a field from the source that supplies it.
|
|
290
|
+
*
|
|
291
|
+
* @throws ConfigWriteError when the field isn't set or its source can't be written
|
|
292
|
+
*/
|
|
293
|
+
export async function removeConfigField(config, field) {
|
|
294
|
+
return writeConfigField(config, field, undefined);
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=config-write.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-write.js","sourceRoot":"","sources":["../../../src/config/config-write.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/** A JSON Schema fragment (draft-07 subset). */
|
|
2
|
+
export type JsonSchema = Record<string, unknown>;
|
|
3
|
+
/** Public URL of the published schema (usable as `"$schema"` in dw.json). */
|
|
4
|
+
export declare const DW_JSON_SCHEMA_URL = "https://salesforcecommercecloud.github.io/b2c-developer-tooling/schemas/dw.schema.json";
|
|
5
|
+
/**
|
|
6
|
+
* Canonical instance-level fields keyed by kebab-case name (the on-disk spelling).
|
|
7
|
+
* Descriptions mirror the Settings Reference in the configuration guide.
|
|
8
|
+
*/
|
|
9
|
+
export declare const DW_JSON_FIELDS: Record<string, JsonSchema>;
|
|
10
|
+
/**
|
|
11
|
+
* Builds the `dw.json` JSON Schema from {@link DW_JSON_FIELDS}, adding the
|
|
12
|
+
* camelCase spelling and legacy aliases for every field.
|
|
13
|
+
*/
|
|
14
|
+
export declare function buildDwJsonSchema(): JsonSchema;
|
|
@@ -0,0 +1,269 @@
|
|
|
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
|
+
/**
|
|
7
|
+
* JSON Schema for `dw.json` configuration files.
|
|
8
|
+
*
|
|
9
|
+
* This module is the single source of truth for the published schema at
|
|
10
|
+
* `data/schemas/dw.schema.json` (regenerate with `pnpm run generate:dw-json-schema`).
|
|
11
|
+
* Editors use it for validation, completion, and hover docs; the VS Code
|
|
12
|
+
* extension registers it for every `dw.json`.
|
|
13
|
+
*
|
|
14
|
+
* `dw.json` accepts both kebab-case (canonical) and camelCase spellings, plus a
|
|
15
|
+
* few legacy aliases (see {@link CONFIG_KEY_ALIASES}). The schema lists every
|
|
16
|
+
* accepted spelling so editors do not flag valid files. Unknown keys are allowed
|
|
17
|
+
* because other tools share `dw.json`.
|
|
18
|
+
*
|
|
19
|
+
* @module config/dw-json-schema
|
|
20
|
+
*/
|
|
21
|
+
import { CLIENT_AUTH_METHODS } from '../auth/client-credentials.js';
|
|
22
|
+
import { CONFIG_KEY_ALIASES, kebabToCamelCase } from './mapping.js';
|
|
23
|
+
/** Public URL of the published schema (usable as `"$schema"` in dw.json). */
|
|
24
|
+
export const DW_JSON_SCHEMA_URL = 'https://salesforcecommercecloud.github.io/b2c-developer-tooling/schemas/dw.schema.json';
|
|
25
|
+
const DOCS_URL = 'https://salesforcecommercecloud.github.io/b2c-developer-tooling/guide/configuration.html';
|
|
26
|
+
const stringArray = { type: 'array', items: { type: 'string' } };
|
|
27
|
+
const AUTH_METHODS = ['client-credentials', 'jwt', 'user', 'implicit', 'basic', 'api-key'];
|
|
28
|
+
/**
|
|
29
|
+
* Canonical instance-level fields keyed by kebab-case name (the on-disk spelling).
|
|
30
|
+
* Descriptions mirror the Settings Reference in the configuration guide.
|
|
31
|
+
*/
|
|
32
|
+
export const DW_JSON_FIELDS = {
|
|
33
|
+
// Instance and site
|
|
34
|
+
name: { type: 'string', description: 'Connection name for instance selection (`--instance` / `SFCC_INSTANCE`).' },
|
|
35
|
+
active: { type: 'boolean', description: 'Use this entry as the default instance.' },
|
|
36
|
+
hostname: {
|
|
37
|
+
type: 'string',
|
|
38
|
+
description: 'Instance hostname, without a URL path (e.g. `abcd-001.dx.commercecloud.salesforce.com`). Env: `SFCC_SERVER`.',
|
|
39
|
+
},
|
|
40
|
+
'webdav-hostname': { type: 'string', description: 'Separate WebDAV hostname. Env: `SFCC_WEBDAV_SERVER`.' },
|
|
41
|
+
'code-version': {
|
|
42
|
+
type: 'string',
|
|
43
|
+
description: 'Default code version for operations that accept one. Env: `SFCC_CODE_VERSION`.',
|
|
44
|
+
},
|
|
45
|
+
'short-code': { type: 'string', description: 'SCAPI short code. Env: `SFCC_SHORTCODE`.' },
|
|
46
|
+
'tenant-id': {
|
|
47
|
+
type: 'string',
|
|
48
|
+
description: 'Tenant or organization ID, such as `abcd_001` or `f_ecom_abcd_001`. Env: `SFCC_TENANT_ID`.',
|
|
49
|
+
},
|
|
50
|
+
'site-id': {
|
|
51
|
+
type: 'string',
|
|
52
|
+
description: 'Default site/channel ID for supported site and shopper operations. Env: `SFCC_SITE_ID`.',
|
|
53
|
+
},
|
|
54
|
+
'api-backend': {
|
|
55
|
+
type: 'string',
|
|
56
|
+
enum: ['auto', 'scapi', 'ocapi'],
|
|
57
|
+
description: 'API backend for operations supporting both SCAPI and OCAPI. `auto` (default) prefers SCAPI with OCAPI fallback. Env: `SFCC_API_BACKEND`.',
|
|
58
|
+
},
|
|
59
|
+
// Administrative authentication
|
|
60
|
+
'client-id': { type: 'string', description: 'Account Manager API client ID. Env: `SFCC_CLIENT_ID`.' },
|
|
61
|
+
'client-secret': { type: 'string', description: 'Account Manager client secret. Env: `SFCC_CLIENT_SECRET`.' },
|
|
62
|
+
'oauth-scopes': {
|
|
63
|
+
...stringArray,
|
|
64
|
+
description: 'Requested OAuth scopes. Scope grants must be configured on the API client. Env: `SFCC_OAUTH_SCOPES` (comma-separated).',
|
|
65
|
+
},
|
|
66
|
+
'jwt-cert-path': {
|
|
67
|
+
type: 'string',
|
|
68
|
+
description: 'PEM certificate path for JWT authentication. Env: `SFCC_JWT_CERT`; flag: `--jwt-cert`.',
|
|
69
|
+
},
|
|
70
|
+
'jwt-key-path': { type: 'string', description: 'PEM private key path for JWT authentication. Env: `SFCC_JWT_KEY`.' },
|
|
71
|
+
'jwt-passphrase': {
|
|
72
|
+
type: 'string',
|
|
73
|
+
description: 'Passphrase for an encrypted JWT private key. Env: `SFCC_JWT_PASSPHRASE`.',
|
|
74
|
+
},
|
|
75
|
+
'auth-methods': {
|
|
76
|
+
type: 'array',
|
|
77
|
+
items: { type: 'string', enum: AUTH_METHODS },
|
|
78
|
+
uniqueItems: true,
|
|
79
|
+
description: 'Ordered list of allowed authentication methods. Do not combine with `user-auth`. Env: `SFCC_AUTH_METHODS` (comma-separated).',
|
|
80
|
+
},
|
|
81
|
+
'user-auth': {
|
|
82
|
+
type: 'boolean',
|
|
83
|
+
description: 'Shorthand for `"auth-methods": ["user"]` (browser login). Do not combine with `auth-methods`.',
|
|
84
|
+
},
|
|
85
|
+
'account-manager-host': {
|
|
86
|
+
type: 'string',
|
|
87
|
+
description: 'Account Manager hostname override. Env: `SFCC_ACCOUNT_MANAGER_HOST`.',
|
|
88
|
+
},
|
|
89
|
+
'client-auth-method': {
|
|
90
|
+
type: 'string',
|
|
91
|
+
enum: [...CLIENT_AUTH_METHODS],
|
|
92
|
+
description: 'How client credentials are sent to Account Manager (default `basic`). Env: `SFCC_CLIENT_AUTH_METHOD`; flag: `--client-auth-method`.',
|
|
93
|
+
},
|
|
94
|
+
// Shopper authentication
|
|
95
|
+
'slas-client-id': {
|
|
96
|
+
type: 'string',
|
|
97
|
+
description: 'Shopper Login and API Access Service (SLAS) client ID. Env: `SFCC_SLAS_CLIENT_ID`.',
|
|
98
|
+
},
|
|
99
|
+
'slas-client-secret': {
|
|
100
|
+
type: 'string',
|
|
101
|
+
description: 'Secret for a private SLAS client; omit for public clients. Env: `SFCC_SLAS_CLIENT_SECRET`.',
|
|
102
|
+
},
|
|
103
|
+
// WebDAV and certificates
|
|
104
|
+
username: {
|
|
105
|
+
type: 'string',
|
|
106
|
+
description: 'Business Manager username (typically an email address) for WebDAV. Env: `SFCC_USERNAME`.',
|
|
107
|
+
},
|
|
108
|
+
password: { type: 'string', description: 'WebDAV access key for `username`. Env: `SFCC_PASSWORD`.' },
|
|
109
|
+
certificate: {
|
|
110
|
+
type: 'string',
|
|
111
|
+
description: 'Path to a PKCS12 (`.p12` / `.pfx`) client certificate for mTLS. Env: `SFCC_CERTIFICATE`.',
|
|
112
|
+
},
|
|
113
|
+
'certificate-passphrase': {
|
|
114
|
+
type: 'string',
|
|
115
|
+
description: 'Client certificate passphrase. Env: `SFCC_CERTIFICATE_PASSPHRASE`.',
|
|
116
|
+
},
|
|
117
|
+
'self-signed': {
|
|
118
|
+
type: 'boolean',
|
|
119
|
+
description: 'Disable server certificate verification (default `false`). Not required just because you use mTLS. Env: `SFCC_SELFSIGNED`.',
|
|
120
|
+
},
|
|
121
|
+
// Code, content, and documentation
|
|
122
|
+
cartridges: {
|
|
123
|
+
oneOf: [stringArray, { type: 'string' }],
|
|
124
|
+
description: 'Cartridge names for deploy/watch filtering and IDE discovery. Array, or a colon/comma-separated string. Env: `SFCC_CARTRIDGES`.',
|
|
125
|
+
},
|
|
126
|
+
'auto-upload': { type: 'boolean', description: 'Automatically upload code changes from the VS Code extension.' },
|
|
127
|
+
'content-library': { type: 'string', description: 'Default library for content list/export.' },
|
|
128
|
+
catalogs: { ...stringArray, description: 'Catalog IDs for WebDAV browsing. Env: `SFCC_CATALOGS`.' },
|
|
129
|
+
libraries: {
|
|
130
|
+
type: 'array',
|
|
131
|
+
items: {
|
|
132
|
+
oneOf: [
|
|
133
|
+
{ type: 'string' },
|
|
134
|
+
{
|
|
135
|
+
type: 'object',
|
|
136
|
+
required: ['id'],
|
|
137
|
+
properties: {
|
|
138
|
+
id: { type: 'string', description: 'Library ID.' },
|
|
139
|
+
siteLibrary: { type: 'boolean', description: 'Whether this is a site-private library.' },
|
|
140
|
+
},
|
|
141
|
+
},
|
|
142
|
+
],
|
|
143
|
+
},
|
|
144
|
+
description: 'Content library IDs, as strings or `{"id": "RefArch", "siteLibrary": true}` entries. Env: `SFCC_LIBRARIES`.',
|
|
145
|
+
},
|
|
146
|
+
'asset-query': {
|
|
147
|
+
...stringArray,
|
|
148
|
+
description: 'JSON dot-paths for finding static asset URLs in content (default `["image.path"]`). Env: `SFCC_ASSET_QUERY`.',
|
|
149
|
+
},
|
|
150
|
+
'import-set-exclude': {
|
|
151
|
+
...stringArray,
|
|
152
|
+
description: 'Project-relative directories to exclude recursively from import-set discovery. Env: `SFCC_IMPORT_SET_EXCLUDE`.',
|
|
153
|
+
},
|
|
154
|
+
'docs-categories': {
|
|
155
|
+
...stringArray,
|
|
156
|
+
description: 'Documentation category allowlist for supported searches. Env: `SFCC_DOCS_CATEGORIES`.',
|
|
157
|
+
},
|
|
158
|
+
'scapi-schemas': {
|
|
159
|
+
...stringArray,
|
|
160
|
+
description: 'Local SCAPI OpenAPI JSON files or directories (relative to the project directory), or http(s) URLs, for MCP code mode. Env: `SFCC_SCAPI_SCHEMAS`.',
|
|
161
|
+
},
|
|
162
|
+
// Sandboxes and analytics
|
|
163
|
+
realm: { type: 'string', description: 'Default realm for sandbox operations.' },
|
|
164
|
+
'sandbox-api-host': {
|
|
165
|
+
type: 'string',
|
|
166
|
+
description: 'On-Demand Sandbox API hostname override. Env: `SFCC_SANDBOX_API_HOST`.',
|
|
167
|
+
},
|
|
168
|
+
'cip-host': { type: 'string', description: 'CIP analytics host override. Env: `SFCC_CIP_HOST`.' },
|
|
169
|
+
safety: {
|
|
170
|
+
type: 'object',
|
|
171
|
+
description: 'Per-instance safety restrictions and confirmation rules. See the Safety Mode guide.',
|
|
172
|
+
additionalProperties: false,
|
|
173
|
+
properties: {
|
|
174
|
+
level: {
|
|
175
|
+
type: 'string',
|
|
176
|
+
enum: ['NONE', 'NO_DELETE', 'NO_UPDATE', 'READ_ONLY'],
|
|
177
|
+
description: 'Baseline restriction level. Env: `SFCC_SAFETY_LEVEL`.',
|
|
178
|
+
},
|
|
179
|
+
confirm: {
|
|
180
|
+
type: 'boolean',
|
|
181
|
+
description: 'Require interactive confirmation for blocked operations instead of refusing them.',
|
|
182
|
+
},
|
|
183
|
+
rules: {
|
|
184
|
+
type: 'array',
|
|
185
|
+
description: 'Ordered rules; the first match wins.',
|
|
186
|
+
items: {
|
|
187
|
+
type: 'object',
|
|
188
|
+
required: ['action'],
|
|
189
|
+
additionalProperties: false,
|
|
190
|
+
properties: {
|
|
191
|
+
method: { type: 'string', description: 'HTTP method pattern (e.g. `POST`, `DELETE`).' },
|
|
192
|
+
path: { type: 'string', description: 'URL path glob (e.g. `/jobs/*/executions`).' },
|
|
193
|
+
job: { type: 'string', description: 'Job ID glob.' },
|
|
194
|
+
command: { type: 'string', description: 'CLI command ID glob (e.g. `sandbox:*`, `ecdn:cache:purge`).' },
|
|
195
|
+
action: { type: 'string', enum: ['allow', 'block', 'confirm'], description: 'Action when the rule matches.' },
|
|
196
|
+
},
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
},
|
|
200
|
+
},
|
|
201
|
+
// Managed Runtime
|
|
202
|
+
'mrt-api-key': { type: 'string', description: 'Managed Runtime API key. Env: `MRT_API_KEY`.' },
|
|
203
|
+
'mrt-project': {
|
|
204
|
+
type: 'string',
|
|
205
|
+
description: 'Managed Runtime project slug (storefront ID for SCAPI MRT operations). Env: `MRT_PROJECT`.',
|
|
206
|
+
},
|
|
207
|
+
'mrt-environment': { type: 'string', description: 'Managed Runtime target environment. Env: `MRT_ENVIRONMENT`.' },
|
|
208
|
+
'mrt-origin': { type: 'string', description: 'Managed Runtime API origin override. Env: `MRT_CLOUD_ORIGIN`.' },
|
|
209
|
+
'mrt-backend': {
|
|
210
|
+
type: 'string',
|
|
211
|
+
enum: ['auto', 'legacy', 'scapi'],
|
|
212
|
+
description: 'Managed Runtime backend for supported operations (default `auto`). Env: `MRT_BACKEND`.',
|
|
213
|
+
},
|
|
214
|
+
};
|
|
215
|
+
/** Legacy and alternate spellings, excluding simple camelCase forms. */
|
|
216
|
+
function aliasesFor(camelKey) {
|
|
217
|
+
return Object.entries(CONFIG_KEY_ALIASES)
|
|
218
|
+
.filter(([, canonical]) => canonical === camelKey)
|
|
219
|
+
.map(([alias]) => alias);
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Builds the `dw.json` JSON Schema from {@link DW_JSON_FIELDS}, adding the
|
|
223
|
+
* camelCase spelling and legacy aliases for every field.
|
|
224
|
+
*/
|
|
225
|
+
export function buildDwJsonSchema() {
|
|
226
|
+
const instanceProperties = {};
|
|
227
|
+
for (const [kebab, schema] of Object.entries(DW_JSON_FIELDS)) {
|
|
228
|
+
instanceProperties[kebab] = schema;
|
|
229
|
+
const camel = kebabToCamelCase(kebab);
|
|
230
|
+
const alternates = [camel, ...aliasesFor(camel)].filter((k) => k !== kebab);
|
|
231
|
+
for (const alternate of alternates) {
|
|
232
|
+
instanceProperties[alternate] ??= {
|
|
233
|
+
...schema,
|
|
234
|
+
description: `Alternate spelling of \`${kebab}\`. ${String(schema.description ?? '')}`.trim(),
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
const instanceSchema = {
|
|
239
|
+
type: 'object',
|
|
240
|
+
properties: instanceProperties,
|
|
241
|
+
additionalProperties: true,
|
|
242
|
+
not: {
|
|
243
|
+
anyOf: [
|
|
244
|
+
{ required: ['user-auth', 'auth-methods'] },
|
|
245
|
+
{ required: ['userAuth', 'authMethods'] },
|
|
246
|
+
{ required: ['user-auth', 'authMethods'] },
|
|
247
|
+
{ required: ['userAuth', 'auth-methods'] },
|
|
248
|
+
],
|
|
249
|
+
},
|
|
250
|
+
};
|
|
251
|
+
return {
|
|
252
|
+
$schema: 'http://json-schema.org/draft-07/schema#',
|
|
253
|
+
$id: DW_JSON_SCHEMA_URL,
|
|
254
|
+
title: 'B2C Commerce dw.json',
|
|
255
|
+
description: `Connection and project configuration for B2C Commerce tooling. See ${DOCS_URL}`,
|
|
256
|
+
definitions: { instance: instanceSchema },
|
|
257
|
+
allOf: [{ $ref: '#/definitions/instance' }],
|
|
258
|
+
type: 'object',
|
|
259
|
+
properties: {
|
|
260
|
+
$schema: { type: 'string', description: 'JSON Schema reference for editor support.' },
|
|
261
|
+
configs: {
|
|
262
|
+
type: 'array',
|
|
263
|
+
description: 'Named instance entries. Select one with `--instance` / `SFCC_INSTANCE`, or mark one `active`.',
|
|
264
|
+
items: { $ref: '#/definitions/instance' },
|
|
265
|
+
},
|
|
266
|
+
},
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
//# sourceMappingURL=dw-json-schema.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dw-json-schema.js","sourceRoot":"","sources":["../../../src/config/dw-json-schema.ts"],"names":[],"mappings":"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"}
|
|
@@ -93,6 +93,8 @@ export interface DwJsonConfig {
|
|
|
93
93
|
cipHost?: string;
|
|
94
94
|
/** Documentation categories to expose (allowlist); dw.json key `docs-categories` */
|
|
95
95
|
docsCategories?: string[];
|
|
96
|
+
/** Local SCAPI OpenAPI contracts (files, directories or http(s) URLs) for MCP code mode; dw.json key `scapi-schemas` */
|
|
97
|
+
scapiSchemas?: string[];
|
|
96
98
|
/** Path to PKCS12 certificate file for mTLS (two-factor auth) */
|
|
97
99
|
certificate?: string;
|
|
98
100
|
/** Passphrase for the certificate */
|
|
@@ -297,16 +297,20 @@ export async function updateInstanceConfig(patch, options = {}) {
|
|
|
297
297
|
if (!target) {
|
|
298
298
|
throw new Error(`Instance "${options.instance}" not found`);
|
|
299
299
|
}
|
|
300
|
+
// Rebuild the entry so a replaced key keeps its position in the file.
|
|
301
|
+
const entries = Object.entries(target);
|
|
300
302
|
for (const [field, value] of Object.entries(patch)) {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
}
|
|
305
|
-
}
|
|
303
|
+
const matches = (key) => (CONFIG_KEY_ALIASES[key] ?? kebabToCamelCase(key)) === field;
|
|
304
|
+
const position = entries.findIndex(([key]) => matches(key));
|
|
305
|
+
const remaining = entries.filter(([key]) => !matches(key));
|
|
306
306
|
if (value !== undefined) {
|
|
307
|
-
|
|
307
|
+
remaining.splice(position === -1 ? remaining.length : position, 0, [camelToKebabCase(field), value]);
|
|
308
308
|
}
|
|
309
|
+
entries.splice(0, entries.length, ...remaining);
|
|
309
310
|
}
|
|
311
|
+
for (const key of Object.keys(target))
|
|
312
|
+
delete target[key];
|
|
313
|
+
Object.assign(target, Object.fromEntries(entries));
|
|
310
314
|
await saveDwJson(existing, dwJsonPath);
|
|
311
315
|
return { name: target.name, path: dwJsonPath };
|
|
312
316
|
}
|