@unchainedshop/api 3.1.10 → 3.1.12

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 (173) hide show
  1. package/lib/express/createMCPMiddleware.d.ts +4 -0
  2. package/lib/express/createMCPMiddleware.d.ts.map +1 -0
  3. package/lib/express/createMCPMiddleware.js +68 -0
  4. package/lib/express/createMCPMiddleware.js.map +1 -0
  5. package/lib/express/mcpHandler.d.ts.map +1 -0
  6. package/lib/express/mcpHandler.js +68 -0
  7. package/lib/express/mcpHandler.js.map +1 -0
  8. package/lib/fastify/createMCPMiddleware.d.ts +2 -0
  9. package/lib/fastify/createMCPMiddleware.d.ts.map +1 -0
  10. package/lib/fastify/createMCPMiddleware.js +2 -0
  11. package/lib/fastify/createMCPMiddleware.js.map +1 -0
  12. package/lib/fastify/index copy.d.ts.map +1 -0
  13. package/lib/fastify/index copy.js +157 -0
  14. package/lib/fastify/index copy.js.map +1 -0
  15. package/lib/fastify/mcpHandler.d.ts +8 -0
  16. package/lib/fastify/mcpHandler.d.ts.map +1 -0
  17. package/lib/fastify/mcpHandler.js +46 -0
  18. package/lib/fastify/mcpHandler.js.map +1 -0
  19. package/lib/loaders/assortmentLinkLoader.d.ts +12 -0
  20. package/lib/loaders/assortmentLinkLoader.d.ts.map +1 -0
  21. package/lib/loaders/assortmentLinkLoader.js +23 -0
  22. package/lib/loaders/assortmentLinkLoader.js.map +1 -0
  23. package/lib/loaders/assortmentLinksLoader.d.ts +14 -0
  24. package/lib/loaders/assortmentLinksLoader.d.ts.map +1 -0
  25. package/lib/loaders/assortmentLinksLoader.js +38 -0
  26. package/lib/loaders/assortmentLinksLoader.js.map +1 -0
  27. package/lib/loaders/assortmentLoader.d.ts +10 -0
  28. package/lib/loaders/assortmentLoader.d.ts.map +1 -0
  29. package/lib/loaders/assortmentLoader.js +15 -0
  30. package/lib/loaders/assortmentLoader.js.map +1 -0
  31. package/lib/loaders/assortmentMediaTextLoader.d.ts +12 -0
  32. package/lib/loaders/assortmentMediaTextLoader.d.ts.map +1 -0
  33. package/lib/loaders/assortmentMediaTextLoader.js +15 -0
  34. package/lib/loaders/assortmentMediaTextLoader.js.map +1 -0
  35. package/lib/loaders/assortmentMediasLoader.d.ts +10 -0
  36. package/lib/loaders/assortmentMediasLoader.d.ts.map +1 -0
  37. package/lib/loaders/assortmentMediasLoader.js +18 -0
  38. package/lib/loaders/assortmentMediasLoader.js.map +1 -0
  39. package/lib/loaders/assortmentProductLoader.d.ts +12 -0
  40. package/lib/loaders/assortmentProductLoader.d.ts.map +1 -0
  41. package/lib/loaders/assortmentProductLoader.js +14 -0
  42. package/lib/loaders/assortmentProductLoader.js.map +1 -0
  43. package/lib/loaders/assortmentProductsLoader.d.ts +10 -0
  44. package/lib/loaders/assortmentProductsLoader.d.ts.map +1 -0
  45. package/lib/loaders/assortmentProductsLoader.js +18 -0
  46. package/lib/loaders/assortmentProductsLoader.js.map +1 -0
  47. package/lib/loaders/assortmentTextLoader.d.ts +12 -0
  48. package/lib/loaders/assortmentTextLoader.d.ts.map +1 -0
  49. package/lib/loaders/assortmentTextLoader.js +15 -0
  50. package/lib/loaders/assortmentTextLoader.js.map +1 -0
  51. package/lib/loaders/buildLocaleMap.d.ts +6 -0
  52. package/lib/loaders/buildLocaleMap.d.ts.map +1 -0
  53. package/lib/loaders/buildLocaleMap.js +38 -0
  54. package/lib/loaders/buildLocaleMap.js.map +1 -0
  55. package/lib/loaders/buildTextMap.d.ts +1 -1
  56. package/lib/loaders/buildTextMap.d.ts.map +1 -1
  57. package/lib/loaders/buildTextMap.js +16 -6
  58. package/lib/loaders/buildTextMap.js.map +1 -1
  59. package/lib/loaders/countryLoader.d.ts +10 -0
  60. package/lib/loaders/countryLoader.d.ts.map +1 -0
  61. package/lib/loaders/countryLoader.js +14 -0
  62. package/lib/loaders/countryLoader.js.map +1 -0
  63. package/lib/loaders/currencyLoader.d.ts +10 -0
  64. package/lib/loaders/currencyLoader.d.ts.map +1 -0
  65. package/lib/loaders/currencyLoader.js +14 -0
  66. package/lib/loaders/currencyLoader.js.map +1 -0
  67. package/lib/loaders/deliveryProviderLoader.d.ts +10 -0
  68. package/lib/loaders/deliveryProviderLoader.d.ts.map +1 -0
  69. package/lib/loaders/deliveryProviderLoader.js +13 -0
  70. package/lib/loaders/deliveryProviderLoader.js.map +1 -0
  71. package/lib/loaders/fileLoader.d.ts +10 -0
  72. package/lib/loaders/fileLoader.d.ts.map +1 -0
  73. package/lib/loaders/fileLoader.js +13 -0
  74. package/lib/loaders/fileLoader.js.map +1 -0
  75. package/lib/loaders/filterLoader.d.ts +10 -0
  76. package/lib/loaders/filterLoader.d.ts.map +1 -0
  77. package/lib/loaders/filterLoader.js +14 -0
  78. package/lib/loaders/filterLoader.js.map +1 -0
  79. package/lib/loaders/filterTextLoader.d.ts +14 -0
  80. package/lib/loaders/filterTextLoader.d.ts.map +1 -0
  81. package/lib/loaders/filterTextLoader.js +15 -0
  82. package/lib/loaders/filterTextLoader.js.map +1 -0
  83. package/lib/loaders/index.d.ts.map +1 -1
  84. package/lib/loaders/index.js +1 -29
  85. package/lib/loaders/index.js.map +1 -1
  86. package/lib/loaders/languageLoader.d.ts +10 -0
  87. package/lib/loaders/languageLoader.d.ts.map +1 -0
  88. package/lib/loaders/languageLoader.js +14 -0
  89. package/lib/loaders/languageLoader.js.map +1 -0
  90. package/lib/loaders/orderLoader.d.ts +10 -0
  91. package/lib/loaders/orderLoader.d.ts.map +1 -0
  92. package/lib/loaders/orderLoader.js +16 -0
  93. package/lib/loaders/orderLoader.js.map +1 -0
  94. package/lib/loaders/paymentProviderLoader.d.ts +10 -0
  95. package/lib/loaders/paymentProviderLoader.d.ts.map +1 -0
  96. package/lib/loaders/paymentProviderLoader.js +13 -0
  97. package/lib/loaders/paymentProviderLoader.js.map +1 -0
  98. package/lib/loaders/productLoader.d.ts +10 -0
  99. package/lib/loaders/productLoader.d.ts.map +1 -0
  100. package/lib/loaders/productLoader.js +16 -0
  101. package/lib/loaders/productLoader.js.map +1 -0
  102. package/lib/loaders/productLoaderBySKU.d.ts +10 -0
  103. package/lib/loaders/productLoaderBySKU.d.ts.map +1 -0
  104. package/lib/loaders/productLoaderBySKU.js +16 -0
  105. package/lib/loaders/productLoaderBySKU.js.map +1 -0
  106. package/lib/loaders/productMediaTextLoader.d.ts +12 -0
  107. package/lib/loaders/productMediaTextLoader.d.ts.map +1 -0
  108. package/lib/loaders/productMediaTextLoader.js +15 -0
  109. package/lib/loaders/productMediaTextLoader.js.map +1 -0
  110. package/lib/loaders/productMediasLoader.d.ts +10 -0
  111. package/lib/loaders/productMediasLoader.d.ts.map +1 -0
  112. package/lib/loaders/productMediasLoader.js +18 -0
  113. package/lib/loaders/productMediasLoader.js.map +1 -0
  114. package/lib/loaders/productTextLoader.d.ts +12 -0
  115. package/lib/loaders/productTextLoader.d.ts.map +1 -0
  116. package/lib/loaders/productTextLoader.js +15 -0
  117. package/lib/loaders/productTextLoader.js.map +1 -0
  118. package/lib/loaders/userLoader.d.ts +10 -0
  119. package/lib/loaders/userLoader.d.ts.map +1 -0
  120. package/lib/loaders/userLoader.js +17 -0
  121. package/lib/loaders/userLoader.js.map +1 -0
  122. package/lib/loaders/utils.d.ts +7 -0
  123. package/lib/loaders/utils.d.ts.map +1 -0
  124. package/lib/loaders/utils.js +29 -0
  125. package/lib/loaders/utils.js.map +1 -0
  126. package/lib/mcp/index.d.ts +4 -0
  127. package/lib/mcp/index.d.ts.map +1 -0
  128. package/lib/mcp/index.js +12 -0
  129. package/lib/mcp/index.js.map +1 -0
  130. package/lib/mcp/server.d.ts +4 -0
  131. package/lib/mcp/server.d.ts.map +1 -0
  132. package/lib/mcp/server.js +60 -0
  133. package/lib/mcp/server.js.map +1 -0
  134. package/lib/mcp/tools/getProduct.d.ts +51 -0
  135. package/lib/mcp/tools/getProduct.d.ts.map +1 -0
  136. package/lib/mcp/tools/getProduct.js +428 -0
  137. package/lib/mcp/tools/getProduct.js.map +1 -0
  138. package/lib/mcp/tools/index.d.ts +6 -0
  139. package/lib/mcp/tools/index.d.ts.map +1 -0
  140. package/lib/mcp/tools/index.js +6 -0
  141. package/lib/mcp/tools/index.js.map +1 -0
  142. package/lib/mcp/tools/listProducts.d.ts +112 -0
  143. package/lib/mcp/tools/listProducts.d.ts.map +1 -0
  144. package/lib/mcp/tools/listProducts.js +111 -0
  145. package/lib/mcp/tools/listProducts.js.map +1 -0
  146. package/lib/mcp/types.d.ts +27 -0
  147. package/lib/mcp/types.d.ts.map +1 -0
  148. package/lib/mcp/types.js +5 -0
  149. package/lib/mcp/types.js.map +1 -0
  150. package/lib/mcp/utils/html.d.ts +16 -0
  151. package/lib/mcp/utils/html.d.ts.map +1 -0
  152. package/lib/mcp/utils/html.js +102 -0
  153. package/lib/mcp/utils/html.js.map +1 -0
  154. package/lib/middleware/accountLockout.d.ts.map +1 -0
  155. package/lib/middleware/accountLockout.js +84 -0
  156. package/lib/middleware/accountLockout.js.map +1 -0
  157. package/lib/middleware/rateLimiter.d.ts.map +1 -0
  158. package/lib/middleware/rateLimiter.js +91 -0
  159. package/lib/middleware/rateLimiter.js.map +1 -0
  160. package/lib/plugins/inputValidation.d.ts.map +1 -0
  161. package/lib/plugins/inputValidation.js +95 -0
  162. package/lib/plugins/inputValidation.js.map +1 -0
  163. package/lib/schema/mutation.js +1 -1
  164. package/lib/utils/inputValidation.d.ts.map +1 -0
  165. package/lib/utils/inputValidation.js +51 -0
  166. package/lib/utils/inputValidation.js.map +1 -0
  167. package/package.json +1 -1
  168. package/src/loaders/buildLocaleMap.test.ts +72 -0
  169. package/src/loaders/buildLocaleMap.ts +39 -0
  170. package/src/loaders/buildTextMap.test.ts +55 -0
  171. package/src/loaders/buildTextMap.ts +22 -6
  172. package/src/loaders/index.ts +1 -31
  173. package/src/schema/mutation.ts +1 -1
@@ -0,0 +1,51 @@
1
+ import { GraphQLError } from 'graphql';
2
+ // Dangerous patterns to check for
3
+ const DANGEROUS_PATTERNS = [
4
+ /<script/i, // Script tags
5
+ /<iframe/i, // Iframes
6
+ /<object/i, // Object embeds
7
+ /<embed/i, // Embed tags
8
+ /<link/i, // Link tags (can load CSS)
9
+ /javascript:/i, // JavaScript protocol
10
+ /vbscript:/i, // VBScript protocol
11
+ /on\w+\s*=/i, // Event handlers (onclick, onload, etc)
12
+ /<meta/i, // Meta tags
13
+ /data:text\/html/i, // Data URLs with HTML
14
+ /<svg.*onload/i, // SVG with event handlers
15
+ /&#x?[0-9a-f]+;/i, // HTML entities (could be obfuscation)
16
+ /\\u[0-9a-f]{4}/i, // Unicode escapes
17
+ /expression\s*\(/i, // CSS expressions
18
+ /@import/i, // CSS imports
19
+ /<!--|-->/, // HTML comments
20
+ ];
21
+ // Check for dangerous patterns in any string
22
+ export function checkForDangerousContent(value) {
23
+ if (!value)
24
+ return;
25
+ for (const dangerous of DANGEROUS_PATTERNS) {
26
+ if (dangerous.test(value)) {
27
+ throw new GraphQLError('Input contains potentially dangerous content', {
28
+ extensions: { code: 'SECURITY_VALIDATION_ERROR' },
29
+ });
30
+ }
31
+ }
32
+ }
33
+ // Validate an entire object recursively
34
+ export function validateObject(obj, path = '') {
35
+ if (typeof obj === 'string') {
36
+ checkForDangerousContent(obj);
37
+ return obj;
38
+ }
39
+ if (Array.isArray(obj)) {
40
+ return obj.map((item, index) => validateObject(item, `${path}[${index}]`));
41
+ }
42
+ if (obj && typeof obj === 'object') {
43
+ const validated = {};
44
+ for (const [key, value] of Object.entries(obj)) {
45
+ validated[key] = validateObject(value, path ? `${path}.${key}` : key);
46
+ }
47
+ return validated;
48
+ }
49
+ return obj;
50
+ }
51
+ //# sourceMappingURL=inputValidation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inputValidation.js","sourceRoot":"","sources":["../../src/utils/inputValidation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAEvC,kCAAkC;AAClC,MAAM,kBAAkB,GAAG;IACzB,UAAU,EAAE,cAAc;IAC1B,UAAU,EAAE,UAAU;IACtB,UAAU,EAAE,gBAAgB;IAC5B,SAAS,EAAE,aAAa;IACxB,QAAQ,EAAE,2BAA2B;IACrC,cAAc,EAAE,sBAAsB;IACtC,YAAY,EAAE,oBAAoB;IAClC,YAAY,EAAE,wCAAwC;IACtD,QAAQ,EAAE,YAAY;IACtB,kBAAkB,EAAE,sBAAsB;IAC1C,eAAe,EAAE,0BAA0B;IAC3C,iBAAiB,EAAE,uCAAuC;IAC1D,iBAAiB,EAAE,kBAAkB;IACrC,kBAAkB,EAAE,kBAAkB;IACtC,UAAU,EAAE,cAAc;IAC1B,UAAU,EAAE,gBAAgB;CAC7B,CAAC;AAEF,6CAA6C;AAC7C,MAAM,UAAU,wBAAwB,CAAC,KAAa;IACpD,IAAI,CAAC,KAAK;QAAE,OAAO;IAEnB,KAAK,MAAM,SAAS,IAAI,kBAAkB,EAAE,CAAC;QAC3C,IAAI,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YAC1B,MAAM,IAAI,YAAY,CAAC,8CAA8C,EAAE;gBACrE,UAAU,EAAE,EAAE,IAAI,EAAE,2BAA2B,EAAE;aAClD,CAAC,CAAC;QACL,CAAC;IACH,CAAC;AACH,CAAC;AAED,wCAAwC;AACxC,MAAM,UAAU,cAAc,CAAC,GAAQ,EAAE,IAAI,GAAG,EAAE;IAChD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QAC5B,wBAAwB,CAAC,GAAG,CAAC,CAAC;QAC9B,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;QACvB,OAAO,GAAG,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,cAAc,CAAC,IAAI,EAAE,GAAG,IAAI,IAAI,KAAK,GAAG,CAAC,CAAC,CAAC;IAC7E,CAAC;IAED,IAAI,GAAG,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,SAAS,GAAG,EAAE,CAAC;QACrB,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;YAC/C,SAAS,CAAC,GAAG,CAAC,GAAG,cAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unchainedshop/api",
3
- "version": "3.1.10",
3
+ "version": "3.1.12",
4
4
  "main": "lib/api-index.js",
5
5
  "types": "lib/api-index.d.ts",
6
6
  "type": "module",
@@ -0,0 +1,72 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import buildLocaleMap from './buildLocaleMap.js';
4
+
5
+ const testTexts = [
6
+ // 1 has translations in French and German
7
+ { locale: 'fr', _id: '1', entityId: '1' },
8
+ { locale: 'de', _id: '2', entityId: '1' },
9
+
10
+ // 2 only has Ialien translations
11
+ { locale: 'it', _id: '3', entityId: '2' },
12
+
13
+ // 3 only has English translations
14
+ { locale: 'en', _id: '4', entityId: '3' },
15
+
16
+ // 4 only has German translations
17
+ { locale: 'de', _id: '5', entityId: '4' },
18
+ ];
19
+
20
+ describe('buildLocaleMap', () => {
21
+ it('Mixed usage of default locale and forced languages', () => {
22
+ const queries = [
23
+ { locale: 'de-CH' },
24
+ { locale: 'fr' },
25
+ { locale: 'it' },
26
+ ];
27
+ const expected = {
28
+ 'de': ['de-CH', 'fr', 'it'],
29
+ 'fr': ['fr'],
30
+ 'it': ['it'],
31
+ };
32
+ const result = buildLocaleMap(queries, testTexts);
33
+ assert.deepStrictEqual(result, expected);
34
+ });
35
+
36
+ it('Mixed usage of forced languages', () => {
37
+ const queries = [
38
+ { locale: 'fr' },
39
+ { locale: 'it' },
40
+ ];
41
+ const expected = {
42
+ 'de': ['fr', 'it'],
43
+ 'fr': ['fr'],
44
+ 'it': ['it'],
45
+ };
46
+ const result = buildLocaleMap(queries, testTexts);
47
+ assert.deepStrictEqual(result, expected);
48
+ });
49
+
50
+ it('Only default locale', () => {
51
+ const queries = [
52
+ { locale: 'de_CH' },
53
+ ];
54
+ const expected = {
55
+ 'de': ['de_CH'],
56
+ };
57
+ const result = buildLocaleMap(queries, testTexts);
58
+ assert.deepStrictEqual(result, expected);
59
+ });
60
+
61
+ it('Only one forced language locale', () => {
62
+ const queries = [
63
+ { locale: 'fr' },
64
+ ];
65
+ const expected = {
66
+ 'fr': ['fr'],
67
+ 'de': ['fr'],
68
+ };
69
+ const result = buildLocaleMap(queries, testTexts);
70
+ assert.deepStrictEqual(result, expected);
71
+ });
72
+ });
@@ -0,0 +1,39 @@
1
+ import { systemLocale } from '@unchainedshop/utils';
2
+
3
+ function getLocaleStrings(locale: string): string[] {
4
+ try {
5
+ const localeObj = new Intl.Locale(locale);
6
+ // Optimized Set creation and spread
7
+ const locales = new Set<string>();
8
+ locales.add(localeObj.baseName);
9
+ locales.add(localeObj.language);
10
+ locales.add(systemLocale.baseName);
11
+ locales.add(systemLocale.language);
12
+ return Array.from(locales);
13
+ } catch {
14
+ // Optimized Set creation and spread
15
+ const locales = new Set<string>();
16
+ locales.add(systemLocale.baseName);
17
+ locales.add(systemLocale.language);
18
+ return Array.from(locales);
19
+ }
20
+ }
21
+ export default function buildLocaleMap(
22
+ queries: Readonly<Array<{ locale: string }>>,
23
+ texts: Readonly<Array<{ locale?: string }>>,
24
+ ): Record<string, string[]> {
25
+ // key = texts.locale
26
+ // value = input query locale
27
+ const queryLocales = new Set(queries.map((q) => q.locale));
28
+ const textLocales = new Set(texts.map((t) => t.locale));
29
+ const localeMap = {};
30
+ for (const queryLocale of queryLocales) {
31
+ const potentialMatches = getLocaleStrings(queryLocale);
32
+ const matches = potentialMatches.filter((l) => textLocales.has(l));
33
+ for (const match of matches) {
34
+ if (!localeMap[match]) localeMap[match] = [];
35
+ localeMap[match].push(queryLocale);
36
+ }
37
+ }
38
+ return localeMap;
39
+ }
@@ -0,0 +1,55 @@
1
+ import { describe, it } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import buildTextMap from './buildTextMap.js';
4
+
5
+ const testTexts = [
6
+ // 1 has translations in French and German
7
+ { locale: 'fr', _id: 'french-1', entityId: '1' },
8
+ { locale: 'de', _id: 'german-1', entityId: '1' },
9
+
10
+ // 2 only has Ialien translations
11
+ { locale: 'it', _id: 'italian-2', entityId: '2' },
12
+
13
+ // 3 only has English translations
14
+ { locale: 'en', _id: 'english-3', entityId: '3' },
15
+
16
+ // 4 only has German translations
17
+ { locale: 'de', _id: 'german-4', entityId: '4' },
18
+ ];
19
+
20
+ describe('buildTextMap', () => {
21
+ it('Generate a correct text map for all fallbacks', () => {
22
+ const localeMap = {
23
+ 'de': ['de-CH', 'fr', 'it'],
24
+ 'fr': ['fr'],
25
+ 'it': ['it'],
26
+ };
27
+ const expected = {
28
+ 'de-CH1': {
29
+ _id: 'german-1',
30
+ },
31
+ 'fr1': {
32
+ _id: 'french-1',
33
+ },
34
+ 'it1': {
35
+ _id: 'german-1',
36
+ },
37
+ 'de-CH4': {
38
+ _id: 'german-4',
39
+ },
40
+ 'fr4': {
41
+ _id: 'german-4',
42
+ },
43
+ 'it4': {
44
+ _id: 'german-4',
45
+ },
46
+ 'it2': {
47
+ _id: 'italian-2',
48
+ },
49
+ };
50
+ const result = buildTextMap(localeMap, testTexts, (text) => text.entityId);
51
+
52
+ assert.partialDeepStrictEqual(result, expected);
53
+ });
54
+
55
+ });
@@ -1,17 +1,33 @@
1
1
  type ArrayElement<T> = T extends (infer U)[] ? U : never;
2
2
 
3
+ /* This file has been optimized for performance to the last drop. Don't refactor! */
4
+
3
5
  export default function buildTextMap<T extends Array<{ locale?: string }>>(
4
6
  localeMap: Record<string, string[]>,
5
7
  texts: Readonly<T>,
6
8
  buildId: (item: ArrayElement<T>) => string,
7
9
  ) {
8
- const textsMap = {};
9
- for (const [originLocale, localesForText] of Object.entries(localeMap)) {
10
- for (const text of texts) {
10
+ const textsMap: Record<string, ArrayElement<T>> = {}; // Added type for textsMap
11
+ const localeMapKeys = Object.keys(localeMap);
12
+
13
+ for (let i = 0; i < localeMapKeys.length; i++) {
14
+ const originLocale = localeMapKeys[i];
15
+ const localesForText = localeMap[originLocale];
16
+
17
+ for (let j = 0; j < texts.length; j++) {
18
+ const text = texts[j];
11
19
  if (originLocale !== text.locale) continue;
12
- for (const locale of localesForText) {
13
- if (textsMap[locale + buildId(text as any)]) continue;
14
- textsMap[locale + buildId(text as any)] = text;
20
+
21
+ const idPart = buildId(text as ArrayElement<T>); // Ensured correct type for buildId argument
22
+
23
+ for (let k = 0; k < localesForText.length; k++) {
24
+ const locale = localesForText[k];
25
+ const key = locale + idPart;
26
+ if (textsMap[key] && locale !== text.locale) {
27
+ // If the key already exists and the locale is a fallback, skip this text
28
+ continue;
29
+ }
30
+ textsMap[key] = text as ArrayElement<T>; // Ensured correct type for assignment
15
31
  }
16
32
  }
17
33
  }
@@ -1,5 +1,4 @@
1
1
  import DataLoader from 'dataloader';
2
- import { systemLocale } from '@unchainedshop/utils';
3
2
  import { UnchainedCore } from '@unchainedshop/core';
4
3
  import { Product, ProductText, ProductMediaText, ProductMedia } from '@unchainedshop/core-products';
5
4
  import { Filter, FilterText } from '@unchainedshop/core-filters';
@@ -13,37 +12,8 @@ import {
13
12
  } from '@unchainedshop/core-assortments';
14
13
  import { File } from '@unchainedshop/core-files';
15
14
  import buildTextMap from './buildTextMap.js';
15
+ import buildLocaleMap from './buildLocaleMap.js';
16
16
 
17
- function getLocaleStrings(locale: string) {
18
- try {
19
- const localeObj = new Intl.Locale(locale);
20
- return [
21
- ...new Set([localeObj.baseName, localeObj.language, systemLocale.baseName, systemLocale.language]),
22
- ];
23
- } catch {
24
- return [...new Set([systemLocale.baseName, systemLocale.language])];
25
- }
26
- }
27
-
28
- function buildLocaleMap(
29
- queries: Readonly<Array<{ locale: string }>>,
30
- texts: Readonly<Array<{ locale?: string }>>,
31
- ): Record<string, string[]> {
32
- // key = texts.locale
33
- // value = input query locale
34
- const queryLocales: Array<any> = [...new Set(queries.map((q) => q.locale))];
35
- const textLocales: Array<string> = [...new Set(texts.map((t) => t.locale))];
36
- const localeMap = {};
37
- for (const queryLocale of queryLocales) {
38
- const potentialMatches = getLocaleStrings(queryLocale);
39
- const matches = potentialMatches.filter((l) => textLocales.includes(l));
40
- for (const match of matches) {
41
- if (!localeMap[match]) localeMap[match] = [];
42
- localeMap[match].push(queryLocale);
43
- }
44
- }
45
- return localeMap;
46
- }
47
17
 
48
18
  const loaders = async (unchainedAPI: UnchainedCore) => {
49
19
  return {
@@ -339,7 +339,7 @@ export default [
339
339
  """
340
340
  Set a new password for a specific user
341
341
  """
342
- setPassword(newPassword!: String, userId: ID!): User!
342
+ setPassword(newPassword: String!, userId: ID!): User!
343
343
 
344
344
  """
345
345
  Set roles of a user