@commercetools-frontend/application-config 25.1.0 → 26.0.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/commercetools-frontend-application-config.cjs.dev.js +71 -31
- package/dist/commercetools-frontend-application-config.cjs.prod.js +71 -31
- package/dist/commercetools-frontend-application-config.esm.js +69 -30
- package/dist/{formatters-7f327585.cjs.prod.js → formatters-4515015b.cjs.prod.js} +1 -1
- package/dist/{formatters-882eafa8.esm.js → formatters-5629a23b.esm.js} +1 -1
- package/dist/{formatters-a76b45b9.cjs.dev.js → formatters-5a68b5ac.cjs.dev.js} +1 -1
- package/package.json +4 -4
- package/ssr/dist/commercetools-frontend-application-config-ssr.cjs.dev.js +1 -1
- package/ssr/dist/commercetools-frontend-application-config-ssr.cjs.prod.js +1 -1
- package/ssr/dist/commercetools-frontend-application-config-ssr.esm.js +1 -1
|
@@ -31,12 +31,13 @@ var _possibleConstructorReturn = require('@babel/runtime-corejs3/helpers/possibl
|
|
|
31
31
|
var _getPrototypeOf = require('@babel/runtime-corejs3/helpers/getPrototypeOf');
|
|
32
32
|
var _inherits = require('@babel/runtime-corejs3/helpers/inherits');
|
|
33
33
|
var _wrapNativeSuper = require('@babel/runtime-corejs3/helpers/wrapNativeSuper');
|
|
34
|
+
var _startsWithInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/starts-with');
|
|
34
35
|
var _trimInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/trim');
|
|
35
36
|
var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
|
|
36
|
-
var
|
|
37
|
+
var path$1 = require('path');
|
|
37
38
|
var _reduceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/reduce');
|
|
38
39
|
var _bindInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/bind');
|
|
39
|
-
var formatters = require('./formatters-
|
|
40
|
+
var formatters = require('./formatters-5a68b5ac.cjs.dev.js');
|
|
40
41
|
var _Set = require('@babel/runtime-corejs3/core-js-stable/set');
|
|
41
42
|
var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array');
|
|
42
43
|
var Ajv = require('ajv');
|
|
@@ -67,9 +68,10 @@ var _mapInstanceProperty__default = /*#__PURE__*/_interopDefault(_mapInstancePro
|
|
|
67
68
|
var _parseInt__default = /*#__PURE__*/_interopDefault(_parseInt);
|
|
68
69
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
69
70
|
var _Reflect$construct__default = /*#__PURE__*/_interopDefault(_Reflect$construct);
|
|
71
|
+
var _startsWithInstanceProperty__default = /*#__PURE__*/_interopDefault(_startsWithInstanceProperty);
|
|
70
72
|
var _trimInstanceProperty__default = /*#__PURE__*/_interopDefault(_trimInstanceProperty);
|
|
71
73
|
var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
|
|
72
|
-
var
|
|
74
|
+
var path__default$1 = /*#__PURE__*/_interopDefault(path$1);
|
|
73
75
|
var _reduceInstanceProperty__default = /*#__PURE__*/_interopDefault(_reduceInstanceProperty);
|
|
74
76
|
var _bindInstanceProperty__default = /*#__PURE__*/_interopDefault(_bindInstanceProperty);
|
|
75
77
|
var _Set__default = /*#__PURE__*/_interopDefault(_Set);
|
|
@@ -218,6 +220,11 @@ const variableSyntax = /\${([ ~:\w.'",\-/()@]+?)}/g;
|
|
|
218
220
|
const envRefSyntax = /^env:/g;
|
|
219
221
|
const intlRefSyntax = /^intl:/g;
|
|
220
222
|
const filePathRefSyntax = /^path:/g;
|
|
223
|
+
|
|
224
|
+
// Safe regex pattern escaping function
|
|
225
|
+
const escapeRegExp = string => {
|
|
226
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
227
|
+
};
|
|
221
228
|
const hasVariablePlaceholder = valueOfEnvConfig => typeof valueOfEnvConfig === 'string' &&
|
|
222
229
|
// Using `{regex}.test()` might cause false positives if called multiple
|
|
223
230
|
// times on a global regular expression:
|
|
@@ -237,8 +244,7 @@ const substituteEnvVariablePlaceholder = (valueOfPlaceholder, matchedString, val
|
|
|
237
244
|
if (!hasEnvField) {
|
|
238
245
|
throw new Error(`Missing environment variable '${requestedEnvVar}' specified in config as 'env:${requestedEnvVar}'.`);
|
|
239
246
|
}
|
|
240
|
-
|
|
241
|
-
return valueOfEnvConfig.replace(new RegExp(`(${escapedMatchedString})+`, 'g'), loadingOptions.processEnv[requestedEnvVar]);
|
|
247
|
+
return valueOfEnvConfig.replace(new RegExp(escapeRegExp(matchedString), 'g'), loadingOptions.processEnv[requestedEnvVar]);
|
|
242
248
|
};
|
|
243
249
|
const substituteIntlVariablePlaceholder = (valueOfPlaceholder, matchedString, valueOfEnvConfig, loadingOptions) => {
|
|
244
250
|
const _valueOfPlaceholder$s3 = valueOfPlaceholder.split(':'),
|
|
@@ -255,43 +261,77 @@ const substituteIntlVariablePlaceholder = (valueOfPlaceholder, matchedString, va
|
|
|
255
261
|
}
|
|
256
262
|
const translation = translations[requestedIntlMessageId];
|
|
257
263
|
const translationValue = isStructuredJson(translation) ? translation.string : translation;
|
|
258
|
-
|
|
259
|
-
return valueOfEnvConfig.replace(new RegExp(`(${escapedMatchedString})+`, 'g'), translationValue);
|
|
264
|
+
return valueOfEnvConfig.replace(new RegExp(escapeRegExp(matchedString), 'g'), translationValue);
|
|
260
265
|
};
|
|
261
266
|
const substituteFilePathVariablePlaceholder = (valueOfPlaceholder, matchedString, valueOfEnvConfig, loadingOptions) => {
|
|
262
267
|
const _valueOfPlaceholder$s5 = valueOfPlaceholder.split(':'),
|
|
263
268
|
_valueOfPlaceholder$s6 = _slicedToArray(_valueOfPlaceholder$s5, 2),
|
|
264
269
|
filePathOrModule = _valueOfPlaceholder$s6[1];
|
|
265
|
-
const
|
|
266
|
-
// Relative paths should be resolved from the application folder.
|
|
270
|
+
const resolvedPath = require.resolve(filePathOrModule, {
|
|
267
271
|
paths: [loadingOptions.applicationPath]
|
|
268
|
-
})
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// Security check: Prevent path traversal attacks.
|
|
275
|
+
// require.resolve() already provides protection by only resolving modules
|
|
276
|
+
// accessible from the applicationPath. However, we add an extra layer to
|
|
277
|
+
// prevent access to sensitive system files outside the workspace.
|
|
278
|
+
const normalizedPath = path__default$1["default"].normalize(resolvedPath);
|
|
279
|
+
const applicationPath = path__default$1["default"].normalize(loadingOptions.applicationPath);
|
|
280
|
+
|
|
281
|
+
// Find workspace root by traversing up from applicationPath until we find
|
|
282
|
+
// package.json, pnpm-workspace.yaml, or reach root
|
|
283
|
+
let workspaceRoot = applicationPath;
|
|
284
|
+
let currentPath = applicationPath;
|
|
285
|
+
const rootPath = path__default$1["default"].parse(currentPath).root;
|
|
286
|
+
while (currentPath !== rootPath) {
|
|
287
|
+
const hasPackageJson = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'package.json'));
|
|
288
|
+
const hasWorkspaceConfig = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'pnpm-workspace.yaml')) || fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'lerna.json'));
|
|
289
|
+
if (hasPackageJson) {
|
|
290
|
+
workspaceRoot = currentPath;
|
|
291
|
+
if (hasWorkspaceConfig) {
|
|
292
|
+
// Found workspace root
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
currentPath = path__default$1["default"].dirname(currentPath);
|
|
297
|
+
}
|
|
298
|
+
const relativePath = path__default$1["default"].relative(workspaceRoot, normalizedPath);
|
|
299
|
+
|
|
300
|
+
// Path is safe if it's within the workspace root.
|
|
301
|
+
// Use path.relative() to avoid string prefix vulnerabilities (e.g., "/app" vs "/app-evil")
|
|
302
|
+
const isSafePath = !_startsWithInstanceProperty__default["default"](relativePath).call(relativePath, '..') && !path__default$1["default"].isAbsolute(relativePath);
|
|
303
|
+
if (!isSafePath) {
|
|
304
|
+
throw new Error(`Access to files outside workspace directory is not allowed: ${filePathOrModule}`);
|
|
305
|
+
}
|
|
306
|
+
const content = fs__default$1["default"].readFileSync(normalizedPath, {
|
|
269
307
|
encoding: 'utf-8'
|
|
270
308
|
});
|
|
271
|
-
|
|
272
|
-
return valueOfEnvConfig.replace(new RegExp(`(${escapedMatchedString})+`, 'g'), content);
|
|
309
|
+
return valueOfEnvConfig.replace(new RegExp(escapeRegExp(matchedString), 'g'), content);
|
|
273
310
|
};
|
|
274
311
|
const getValueOfPlaceholder = valueWithPlaceholder => valueWithPlaceholder.replace(variableSyntax, (_match, varName) => _trimInstanceProperty__default["default"](varName).call(varName)).replace(/\s/g, '');
|
|
275
|
-
const substituteVariablePlaceholders = (config, loadingOptions) =>
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
312
|
+
const substituteVariablePlaceholders = (config, loadingOptions) => {
|
|
313
|
+
const result = JSON.parse(_JSON$stringify__default["default"](config), (_key, value) => {
|
|
314
|
+
// Only strings are allowed
|
|
315
|
+
let substitutedValue = value;
|
|
316
|
+
if (hasVariablePlaceholder(substitutedValue)) {
|
|
317
|
+
const matchResult = substitutedValue.match(variableSyntax);
|
|
318
|
+
if (matchResult) {
|
|
319
|
+
_forEachInstanceProperty__default["default"](matchResult).call(matchResult, matchedString => {
|
|
320
|
+
const valueOfPlaceholder = getValueOfPlaceholder(matchedString);
|
|
321
|
+
if (isEnvVariablePlaceholder(valueOfPlaceholder)) {
|
|
322
|
+
substitutedValue = substituteEnvVariablePlaceholder(valueOfPlaceholder, matchedString, substitutedValue, loadingOptions);
|
|
323
|
+
} else if (isIntlVariablePlaceholder(valueOfPlaceholder)) {
|
|
324
|
+
substitutedValue = substituteIntlVariablePlaceholder(valueOfPlaceholder, matchedString, substitutedValue, loadingOptions);
|
|
325
|
+
} else if (isFilePathVariablePlaceholder(valueOfPlaceholder)) {
|
|
326
|
+
substitutedValue = substituteFilePathVariablePlaceholder(valueOfPlaceholder, matchedString, substitutedValue, loadingOptions);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
291
330
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
331
|
+
return substitutedValue;
|
|
332
|
+
});
|
|
333
|
+
return result;
|
|
334
|
+
};
|
|
295
335
|
|
|
296
336
|
var customApplicationSchemaJson = {
|
|
297
337
|
$schema: "http://json-schema.org/draft-07/schema",
|
|
@@ -31,12 +31,13 @@ var _possibleConstructorReturn = require('@babel/runtime-corejs3/helpers/possibl
|
|
|
31
31
|
var _getPrototypeOf = require('@babel/runtime-corejs3/helpers/getPrototypeOf');
|
|
32
32
|
var _inherits = require('@babel/runtime-corejs3/helpers/inherits');
|
|
33
33
|
var _wrapNativeSuper = require('@babel/runtime-corejs3/helpers/wrapNativeSuper');
|
|
34
|
+
var _startsWithInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/starts-with');
|
|
34
35
|
var _trimInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/trim');
|
|
35
36
|
var _JSON$stringify = require('@babel/runtime-corejs3/core-js-stable/json/stringify');
|
|
36
|
-
var
|
|
37
|
+
var path$1 = require('path');
|
|
37
38
|
var _reduceInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/reduce');
|
|
38
39
|
var _bindInstanceProperty = require('@babel/runtime-corejs3/core-js-stable/instance/bind');
|
|
39
|
-
var formatters = require('./formatters-
|
|
40
|
+
var formatters = require('./formatters-4515015b.cjs.prod.js');
|
|
40
41
|
var _Set = require('@babel/runtime-corejs3/core-js-stable/set');
|
|
41
42
|
var _Array$isArray = require('@babel/runtime-corejs3/core-js-stable/array/is-array');
|
|
42
43
|
var Ajv = require('ajv');
|
|
@@ -67,9 +68,10 @@ var _mapInstanceProperty__default = /*#__PURE__*/_interopDefault(_mapInstancePro
|
|
|
67
68
|
var _parseInt__default = /*#__PURE__*/_interopDefault(_parseInt);
|
|
68
69
|
var fs__default = /*#__PURE__*/_interopDefault(fs);
|
|
69
70
|
var _Reflect$construct__default = /*#__PURE__*/_interopDefault(_Reflect$construct);
|
|
71
|
+
var _startsWithInstanceProperty__default = /*#__PURE__*/_interopDefault(_startsWithInstanceProperty);
|
|
70
72
|
var _trimInstanceProperty__default = /*#__PURE__*/_interopDefault(_trimInstanceProperty);
|
|
71
73
|
var _JSON$stringify__default = /*#__PURE__*/_interopDefault(_JSON$stringify);
|
|
72
|
-
var
|
|
74
|
+
var path__default$1 = /*#__PURE__*/_interopDefault(path$1);
|
|
73
75
|
var _reduceInstanceProperty__default = /*#__PURE__*/_interopDefault(_reduceInstanceProperty);
|
|
74
76
|
var _bindInstanceProperty__default = /*#__PURE__*/_interopDefault(_bindInstanceProperty);
|
|
75
77
|
var _Set__default = /*#__PURE__*/_interopDefault(_Set);
|
|
@@ -218,6 +220,11 @@ const variableSyntax = /\${([ ~:\w.'",\-/()@]+?)}/g;
|
|
|
218
220
|
const envRefSyntax = /^env:/g;
|
|
219
221
|
const intlRefSyntax = /^intl:/g;
|
|
220
222
|
const filePathRefSyntax = /^path:/g;
|
|
223
|
+
|
|
224
|
+
// Safe regex pattern escaping function
|
|
225
|
+
const escapeRegExp = string => {
|
|
226
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
227
|
+
};
|
|
221
228
|
const hasVariablePlaceholder = valueOfEnvConfig => typeof valueOfEnvConfig === 'string' &&
|
|
222
229
|
// Using `{regex}.test()` might cause false positives if called multiple
|
|
223
230
|
// times on a global regular expression:
|
|
@@ -237,8 +244,7 @@ const substituteEnvVariablePlaceholder = (valueOfPlaceholder, matchedString, val
|
|
|
237
244
|
if (!hasEnvField) {
|
|
238
245
|
throw new Error(`Missing environment variable '${requestedEnvVar}' specified in config as 'env:${requestedEnvVar}'.`);
|
|
239
246
|
}
|
|
240
|
-
|
|
241
|
-
return valueOfEnvConfig.replace(new RegExp(`(${escapedMatchedString})+`, 'g'), loadingOptions.processEnv[requestedEnvVar]);
|
|
247
|
+
return valueOfEnvConfig.replace(new RegExp(escapeRegExp(matchedString), 'g'), loadingOptions.processEnv[requestedEnvVar]);
|
|
242
248
|
};
|
|
243
249
|
const substituteIntlVariablePlaceholder = (valueOfPlaceholder, matchedString, valueOfEnvConfig, loadingOptions) => {
|
|
244
250
|
const _valueOfPlaceholder$s3 = valueOfPlaceholder.split(':'),
|
|
@@ -255,43 +261,77 @@ const substituteIntlVariablePlaceholder = (valueOfPlaceholder, matchedString, va
|
|
|
255
261
|
}
|
|
256
262
|
const translation = translations[requestedIntlMessageId];
|
|
257
263
|
const translationValue = isStructuredJson(translation) ? translation.string : translation;
|
|
258
|
-
|
|
259
|
-
return valueOfEnvConfig.replace(new RegExp(`(${escapedMatchedString})+`, 'g'), translationValue);
|
|
264
|
+
return valueOfEnvConfig.replace(new RegExp(escapeRegExp(matchedString), 'g'), translationValue);
|
|
260
265
|
};
|
|
261
266
|
const substituteFilePathVariablePlaceholder = (valueOfPlaceholder, matchedString, valueOfEnvConfig, loadingOptions) => {
|
|
262
267
|
const _valueOfPlaceholder$s5 = valueOfPlaceholder.split(':'),
|
|
263
268
|
_valueOfPlaceholder$s6 = _slicedToArray(_valueOfPlaceholder$s5, 2),
|
|
264
269
|
filePathOrModule = _valueOfPlaceholder$s6[1];
|
|
265
|
-
const
|
|
266
|
-
// Relative paths should be resolved from the application folder.
|
|
270
|
+
const resolvedPath = require.resolve(filePathOrModule, {
|
|
267
271
|
paths: [loadingOptions.applicationPath]
|
|
268
|
-
})
|
|
272
|
+
});
|
|
273
|
+
|
|
274
|
+
// Security check: Prevent path traversal attacks.
|
|
275
|
+
// require.resolve() already provides protection by only resolving modules
|
|
276
|
+
// accessible from the applicationPath. However, we add an extra layer to
|
|
277
|
+
// prevent access to sensitive system files outside the workspace.
|
|
278
|
+
const normalizedPath = path__default$1["default"].normalize(resolvedPath);
|
|
279
|
+
const applicationPath = path__default$1["default"].normalize(loadingOptions.applicationPath);
|
|
280
|
+
|
|
281
|
+
// Find workspace root by traversing up from applicationPath until we find
|
|
282
|
+
// package.json, pnpm-workspace.yaml, or reach root
|
|
283
|
+
let workspaceRoot = applicationPath;
|
|
284
|
+
let currentPath = applicationPath;
|
|
285
|
+
const rootPath = path__default$1["default"].parse(currentPath).root;
|
|
286
|
+
while (currentPath !== rootPath) {
|
|
287
|
+
const hasPackageJson = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'package.json'));
|
|
288
|
+
const hasWorkspaceConfig = fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'pnpm-workspace.yaml')) || fs__default$1["default"].existsSync(path__default$1["default"].join(currentPath, 'lerna.json'));
|
|
289
|
+
if (hasPackageJson) {
|
|
290
|
+
workspaceRoot = currentPath;
|
|
291
|
+
if (hasWorkspaceConfig) {
|
|
292
|
+
// Found workspace root
|
|
293
|
+
break;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
currentPath = path__default$1["default"].dirname(currentPath);
|
|
297
|
+
}
|
|
298
|
+
const relativePath = path__default$1["default"].relative(workspaceRoot, normalizedPath);
|
|
299
|
+
|
|
300
|
+
// Path is safe if it's within the workspace root.
|
|
301
|
+
// Use path.relative() to avoid string prefix vulnerabilities (e.g., "/app" vs "/app-evil")
|
|
302
|
+
const isSafePath = !_startsWithInstanceProperty__default["default"](relativePath).call(relativePath, '..') && !path__default$1["default"].isAbsolute(relativePath);
|
|
303
|
+
if (!isSafePath) {
|
|
304
|
+
throw new Error(`Access to files outside workspace directory is not allowed: ${filePathOrModule}`);
|
|
305
|
+
}
|
|
306
|
+
const content = fs__default$1["default"].readFileSync(normalizedPath, {
|
|
269
307
|
encoding: 'utf-8'
|
|
270
308
|
});
|
|
271
|
-
|
|
272
|
-
return valueOfEnvConfig.replace(new RegExp(`(${escapedMatchedString})+`, 'g'), content);
|
|
309
|
+
return valueOfEnvConfig.replace(new RegExp(escapeRegExp(matchedString), 'g'), content);
|
|
273
310
|
};
|
|
274
311
|
const getValueOfPlaceholder = valueWithPlaceholder => valueWithPlaceholder.replace(variableSyntax, (_match, varName) => _trimInstanceProperty__default["default"](varName).call(varName)).replace(/\s/g, '');
|
|
275
|
-
const substituteVariablePlaceholders = (config, loadingOptions) =>
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
312
|
+
const substituteVariablePlaceholders = (config, loadingOptions) => {
|
|
313
|
+
const result = JSON.parse(_JSON$stringify__default["default"](config), (_key, value) => {
|
|
314
|
+
// Only strings are allowed
|
|
315
|
+
let substitutedValue = value;
|
|
316
|
+
if (hasVariablePlaceholder(substitutedValue)) {
|
|
317
|
+
const matchResult = substitutedValue.match(variableSyntax);
|
|
318
|
+
if (matchResult) {
|
|
319
|
+
_forEachInstanceProperty__default["default"](matchResult).call(matchResult, matchedString => {
|
|
320
|
+
const valueOfPlaceholder = getValueOfPlaceholder(matchedString);
|
|
321
|
+
if (isEnvVariablePlaceholder(valueOfPlaceholder)) {
|
|
322
|
+
substitutedValue = substituteEnvVariablePlaceholder(valueOfPlaceholder, matchedString, substitutedValue, loadingOptions);
|
|
323
|
+
} else if (isIntlVariablePlaceholder(valueOfPlaceholder)) {
|
|
324
|
+
substitutedValue = substituteIntlVariablePlaceholder(valueOfPlaceholder, matchedString, substitutedValue, loadingOptions);
|
|
325
|
+
} else if (isFilePathVariablePlaceholder(valueOfPlaceholder)) {
|
|
326
|
+
substitutedValue = substituteFilePathVariablePlaceholder(valueOfPlaceholder, matchedString, substitutedValue, loadingOptions);
|
|
327
|
+
}
|
|
328
|
+
});
|
|
329
|
+
}
|
|
291
330
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
331
|
+
return substitutedValue;
|
|
332
|
+
});
|
|
333
|
+
return result;
|
|
334
|
+
};
|
|
295
335
|
|
|
296
336
|
var customApplicationSchemaJson = {
|
|
297
337
|
$schema: "http://json-schema.org/draft-07/schema",
|
|
@@ -28,12 +28,13 @@ import _possibleConstructorReturn from '@babel/runtime-corejs3/helpers/esm/possi
|
|
|
28
28
|
import _getPrototypeOf from '@babel/runtime-corejs3/helpers/esm/getPrototypeOf';
|
|
29
29
|
import _inherits from '@babel/runtime-corejs3/helpers/esm/inherits';
|
|
30
30
|
import _wrapNativeSuper from '@babel/runtime-corejs3/helpers/esm/wrapNativeSuper';
|
|
31
|
+
import _startsWithInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/starts-with';
|
|
31
32
|
import _trimInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/trim';
|
|
32
33
|
import _JSON$stringify from '@babel/runtime-corejs3/core-js-stable/json/stringify';
|
|
33
|
-
import
|
|
34
|
+
import path$1 from 'path';
|
|
34
35
|
import _reduceInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/reduce';
|
|
35
36
|
import _bindInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/bind';
|
|
36
|
-
import { f as formatEntryPointUriPathToResourceAccessKey, e as entryPointUriPathToResourceAccesses } from './formatters-
|
|
37
|
+
import { f as formatEntryPointUriPathToResourceAccessKey, e as entryPointUriPathToResourceAccesses } from './formatters-5629a23b.esm.js';
|
|
37
38
|
import _Set from '@babel/runtime-corejs3/core-js-stable/set';
|
|
38
39
|
import _Array$isArray from '@babel/runtime-corejs3/core-js-stable/array/is-array';
|
|
39
40
|
import Ajv from 'ajv';
|
|
@@ -183,6 +184,11 @@ const variableSyntax = /\${([ ~:\w.'",\-/()@]+?)}/g;
|
|
|
183
184
|
const envRefSyntax = /^env:/g;
|
|
184
185
|
const intlRefSyntax = /^intl:/g;
|
|
185
186
|
const filePathRefSyntax = /^path:/g;
|
|
187
|
+
|
|
188
|
+
// Safe regex pattern escaping function
|
|
189
|
+
const escapeRegExp = string => {
|
|
190
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
191
|
+
};
|
|
186
192
|
const hasVariablePlaceholder = valueOfEnvConfig => typeof valueOfEnvConfig === 'string' &&
|
|
187
193
|
// Using `{regex}.test()` might cause false positives if called multiple
|
|
188
194
|
// times on a global regular expression:
|
|
@@ -202,8 +208,7 @@ const substituteEnvVariablePlaceholder = (valueOfPlaceholder, matchedString, val
|
|
|
202
208
|
if (!hasEnvField) {
|
|
203
209
|
throw new Error(`Missing environment variable '${requestedEnvVar}' specified in config as 'env:${requestedEnvVar}'.`);
|
|
204
210
|
}
|
|
205
|
-
|
|
206
|
-
return valueOfEnvConfig.replace(new RegExp(`(${escapedMatchedString})+`, 'g'), loadingOptions.processEnv[requestedEnvVar]);
|
|
211
|
+
return valueOfEnvConfig.replace(new RegExp(escapeRegExp(matchedString), 'g'), loadingOptions.processEnv[requestedEnvVar]);
|
|
207
212
|
};
|
|
208
213
|
const substituteIntlVariablePlaceholder = (valueOfPlaceholder, matchedString, valueOfEnvConfig, loadingOptions) => {
|
|
209
214
|
const _valueOfPlaceholder$s3 = valueOfPlaceholder.split(':'),
|
|
@@ -220,43 +225,77 @@ const substituteIntlVariablePlaceholder = (valueOfPlaceholder, matchedString, va
|
|
|
220
225
|
}
|
|
221
226
|
const translation = translations[requestedIntlMessageId];
|
|
222
227
|
const translationValue = isStructuredJson(translation) ? translation.string : translation;
|
|
223
|
-
|
|
224
|
-
return valueOfEnvConfig.replace(new RegExp(`(${escapedMatchedString})+`, 'g'), translationValue);
|
|
228
|
+
return valueOfEnvConfig.replace(new RegExp(escapeRegExp(matchedString), 'g'), translationValue);
|
|
225
229
|
};
|
|
226
230
|
const substituteFilePathVariablePlaceholder = (valueOfPlaceholder, matchedString, valueOfEnvConfig, loadingOptions) => {
|
|
227
231
|
const _valueOfPlaceholder$s5 = valueOfPlaceholder.split(':'),
|
|
228
232
|
_valueOfPlaceholder$s6 = _slicedToArray(_valueOfPlaceholder$s5, 2),
|
|
229
233
|
filePathOrModule = _valueOfPlaceholder$s6[1];
|
|
230
|
-
const
|
|
231
|
-
// Relative paths should be resolved from the application folder.
|
|
234
|
+
const resolvedPath = require.resolve(filePathOrModule, {
|
|
232
235
|
paths: [loadingOptions.applicationPath]
|
|
233
|
-
})
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Security check: Prevent path traversal attacks.
|
|
239
|
+
// require.resolve() already provides protection by only resolving modules
|
|
240
|
+
// accessible from the applicationPath. However, we add an extra layer to
|
|
241
|
+
// prevent access to sensitive system files outside the workspace.
|
|
242
|
+
const normalizedPath = path$1.normalize(resolvedPath);
|
|
243
|
+
const applicationPath = path$1.normalize(loadingOptions.applicationPath);
|
|
244
|
+
|
|
245
|
+
// Find workspace root by traversing up from applicationPath until we find
|
|
246
|
+
// package.json, pnpm-workspace.yaml, or reach root
|
|
247
|
+
let workspaceRoot = applicationPath;
|
|
248
|
+
let currentPath = applicationPath;
|
|
249
|
+
const rootPath = path$1.parse(currentPath).root;
|
|
250
|
+
while (currentPath !== rootPath) {
|
|
251
|
+
const hasPackageJson = fs$1.existsSync(path$1.join(currentPath, 'package.json'));
|
|
252
|
+
const hasWorkspaceConfig = fs$1.existsSync(path$1.join(currentPath, 'pnpm-workspace.yaml')) || fs$1.existsSync(path$1.join(currentPath, 'lerna.json'));
|
|
253
|
+
if (hasPackageJson) {
|
|
254
|
+
workspaceRoot = currentPath;
|
|
255
|
+
if (hasWorkspaceConfig) {
|
|
256
|
+
// Found workspace root
|
|
257
|
+
break;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
currentPath = path$1.dirname(currentPath);
|
|
261
|
+
}
|
|
262
|
+
const relativePath = path$1.relative(workspaceRoot, normalizedPath);
|
|
263
|
+
|
|
264
|
+
// Path is safe if it's within the workspace root.
|
|
265
|
+
// Use path.relative() to avoid string prefix vulnerabilities (e.g., "/app" vs "/app-evil")
|
|
266
|
+
const isSafePath = !_startsWithInstanceProperty(relativePath).call(relativePath, '..') && !path$1.isAbsolute(relativePath);
|
|
267
|
+
if (!isSafePath) {
|
|
268
|
+
throw new Error(`Access to files outside workspace directory is not allowed: ${filePathOrModule}`);
|
|
269
|
+
}
|
|
270
|
+
const content = fs$1.readFileSync(normalizedPath, {
|
|
234
271
|
encoding: 'utf-8'
|
|
235
272
|
});
|
|
236
|
-
|
|
237
|
-
return valueOfEnvConfig.replace(new RegExp(`(${escapedMatchedString})+`, 'g'), content);
|
|
273
|
+
return valueOfEnvConfig.replace(new RegExp(escapeRegExp(matchedString), 'g'), content);
|
|
238
274
|
};
|
|
239
275
|
const getValueOfPlaceholder = valueWithPlaceholder => valueWithPlaceholder.replace(variableSyntax, (_match, varName) => _trimInstanceProperty(varName).call(varName)).replace(/\s/g, '');
|
|
240
|
-
const substituteVariablePlaceholders = (config, loadingOptions) =>
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
276
|
+
const substituteVariablePlaceholders = (config, loadingOptions) => {
|
|
277
|
+
const result = JSON.parse(_JSON$stringify(config), (_key, value) => {
|
|
278
|
+
// Only strings are allowed
|
|
279
|
+
let substitutedValue = value;
|
|
280
|
+
if (hasVariablePlaceholder(substitutedValue)) {
|
|
281
|
+
const matchResult = substitutedValue.match(variableSyntax);
|
|
282
|
+
if (matchResult) {
|
|
283
|
+
_forEachInstanceProperty(matchResult).call(matchResult, matchedString => {
|
|
284
|
+
const valueOfPlaceholder = getValueOfPlaceholder(matchedString);
|
|
285
|
+
if (isEnvVariablePlaceholder(valueOfPlaceholder)) {
|
|
286
|
+
substitutedValue = substituteEnvVariablePlaceholder(valueOfPlaceholder, matchedString, substitutedValue, loadingOptions);
|
|
287
|
+
} else if (isIntlVariablePlaceholder(valueOfPlaceholder)) {
|
|
288
|
+
substitutedValue = substituteIntlVariablePlaceholder(valueOfPlaceholder, matchedString, substitutedValue, loadingOptions);
|
|
289
|
+
} else if (isFilePathVariablePlaceholder(valueOfPlaceholder)) {
|
|
290
|
+
substitutedValue = substituteFilePathVariablePlaceholder(valueOfPlaceholder, matchedString, substitutedValue, loadingOptions);
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
}
|
|
256
294
|
}
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
295
|
+
return substitutedValue;
|
|
296
|
+
});
|
|
297
|
+
return result;
|
|
298
|
+
};
|
|
260
299
|
|
|
261
300
|
var customApplicationSchemaJson = {
|
|
262
301
|
$schema: "http://json-schema.org/draft-07/schema",
|
|
@@ -59,7 +59,7 @@ const formatEntryPointUriPathToResourceAccessKey = entryPointUriPath => {
|
|
|
59
59
|
// Regex below checking if the character is numeric.
|
|
60
60
|
// If the word after the hyphen is numeric, replace the hyphen with a forward slash.
|
|
61
61
|
// If not, omit the hyphen and uppercase the first character
|
|
62
|
-
if (i > 0 &&
|
|
62
|
+
if (i > 0 && /^\d+$/.test(word[0])) {
|
|
63
63
|
return `/${word}`;
|
|
64
64
|
}
|
|
65
65
|
return upperFirst__default["default"](word);
|
|
@@ -42,7 +42,7 @@ const formatEntryPointUriPathToResourceAccessKey = entryPointUriPath => {
|
|
|
42
42
|
// Regex below checking if the character is numeric.
|
|
43
43
|
// If the word after the hyphen is numeric, replace the hyphen with a forward slash.
|
|
44
44
|
// If not, omit the hyphen and uppercase the first character
|
|
45
|
-
if (i > 0 &&
|
|
45
|
+
if (i > 0 && /^\d+$/.test(word[0])) {
|
|
46
46
|
return `/${word}`;
|
|
47
47
|
}
|
|
48
48
|
return upperFirst(word);
|
|
@@ -59,7 +59,7 @@ const formatEntryPointUriPathToResourceAccessKey = entryPointUriPath => {
|
|
|
59
59
|
// Regex below checking if the character is numeric.
|
|
60
60
|
// If the word after the hyphen is numeric, replace the hyphen with a forward slash.
|
|
61
61
|
// If not, omit the hyphen and uppercase the first character
|
|
62
|
-
if (i > 0 &&
|
|
62
|
+
if (i > 0 && /^\d+$/.test(word[0])) {
|
|
63
63
|
return `/${word}`;
|
|
64
64
|
}
|
|
65
65
|
return upperFirst__default["default"](word);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@commercetools-frontend/application-config",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "26.0.0",
|
|
4
4
|
"description": "Configuration utilities for building Custom Applications",
|
|
5
5
|
"bugs": "https://github.com/commercetools/merchant-center-application-kit/issues",
|
|
6
6
|
"repository": {
|
|
@@ -45,7 +45,7 @@
|
|
|
45
45
|
"@babel/register": "^7.22.15",
|
|
46
46
|
"@babel/runtime": "^7.22.15",
|
|
47
47
|
"@babel/runtime-corejs3": "^7.22.15",
|
|
48
|
-
"@commercetools-frontend/constants": "
|
|
48
|
+
"@commercetools-frontend/constants": "26.0.0",
|
|
49
49
|
"@types/lodash": "^4.14.198",
|
|
50
50
|
"@types/react": "^19.0.3",
|
|
51
51
|
"ajv": "8.17.1",
|
|
@@ -54,13 +54,13 @@
|
|
|
54
54
|
"cosmiconfig-typescript-loader": "6.1.0",
|
|
55
55
|
"dompurify": "^3.0.0",
|
|
56
56
|
"jsdom": "^21.1.2",
|
|
57
|
-
"lodash": "4.17.
|
|
57
|
+
"lodash": "4.17.23",
|
|
58
58
|
"omit-empty-es": "1.2.0"
|
|
59
59
|
},
|
|
60
60
|
"devDependencies": {
|
|
61
61
|
"@types/jsdom": "^21.1.2",
|
|
62
62
|
"json-schema-to-typescript": "15.0.4",
|
|
63
|
-
"@commercetools-frontend/assets": "
|
|
63
|
+
"@commercetools-frontend/assets": "26.0.0"
|
|
64
64
|
},
|
|
65
65
|
"engines": {
|
|
66
66
|
"node": "18.x || 20.x || >=22.0.0"
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var formatters = require('../../dist/formatters-
|
|
5
|
+
var formatters = require('../../dist/formatters-5a68b5ac.cjs.dev.js');
|
|
6
6
|
require('@babel/runtime-corejs3/core-js-stable/object/keys');
|
|
7
7
|
require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols');
|
|
8
8
|
require('@babel/runtime-corejs3/core-js-stable/instance/filter');
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var formatters = require('../../dist/formatters-
|
|
5
|
+
var formatters = require('../../dist/formatters-4515015b.cjs.prod.js');
|
|
6
6
|
require('@babel/runtime-corejs3/core-js-stable/object/keys');
|
|
7
7
|
require('@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols');
|
|
8
8
|
require('@babel/runtime-corejs3/core-js-stable/instance/filter');
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export { d as computeCustomViewPermissionsKeys, c as computeCustomViewResourceAccesses, a as entryPointUriPathToPermissionKeys, e as entryPointUriPathToResourceAccesses, f as formatEntryPointUriPathToResourceAccessKey, b as formatPermissionGroupNameToResourceAccessKey } from '../../dist/formatters-
|
|
1
|
+
export { d as computeCustomViewPermissionsKeys, c as computeCustomViewResourceAccesses, a as entryPointUriPathToPermissionKeys, e as entryPointUriPathToResourceAccesses, f as formatEntryPointUriPathToResourceAccessKey, b as formatPermissionGroupNameToResourceAccessKey } from '../../dist/formatters-5629a23b.esm.js';
|
|
2
2
|
import '@babel/runtime-corejs3/core-js-stable/object/keys';
|
|
3
3
|
import '@babel/runtime-corejs3/core-js-stable/object/get-own-property-symbols';
|
|
4
4
|
import '@babel/runtime-corejs3/core-js-stable/instance/filter';
|