@unchainedshop/api 4.3.0 → 4.3.1

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 (77) hide show
  1. package/lib/express/chatHandler.d.ts.map +1 -1
  2. package/lib/express/chatHandler.js +1 -3
  3. package/lib/express/chatHandler.js.map +1 -1
  4. package/lib/express/index.d.ts.map +1 -1
  5. package/lib/express/index.js +1 -1
  6. package/lib/express/index.js.map +1 -1
  7. package/lib/fastify/chatHandler.d.ts.map +1 -1
  8. package/lib/fastify/chatHandler.js +1 -3
  9. package/lib/fastify/chatHandler.js.map +1 -1
  10. package/lib/fastify/ercMetadataHandler.d.ts.map +1 -1
  11. package/lib/fastify/ercMetadataHandler.js +7 -4
  12. package/lib/fastify/ercMetadataHandler.js.map +1 -1
  13. package/lib/fastify/index.js +1 -1
  14. package/lib/fastify/index.js.map +1 -1
  15. package/lib/loaders/index.d.ts +27 -1
  16. package/lib/loaders/index.d.ts.map +1 -1
  17. package/lib/loaders/index.js +10 -2
  18. package/lib/loaders/index.js.map +1 -1
  19. package/lib/loaders/productBySKULoader.d.ts +10 -0
  20. package/lib/loaders/productBySKULoader.d.ts.map +1 -0
  21. package/lib/loaders/productBySKULoader.js +16 -0
  22. package/lib/loaders/productBySKULoader.js.map +1 -0
  23. package/lib/loaders/productVariationByKeyLoader.d.ts +12 -0
  24. package/lib/loaders/productVariationByKeyLoader.d.ts.map +1 -0
  25. package/lib/loaders/productVariationByKeyLoader.js +14 -0
  26. package/lib/loaders/productVariationByKeyLoader.js.map +1 -0
  27. package/lib/loaders/productVariationLoader.d.ts +10 -0
  28. package/lib/loaders/productVariationLoader.d.ts.map +1 -0
  29. package/lib/loaders/productVariationLoader.js +13 -0
  30. package/lib/loaders/productVariationLoader.js.map +1 -0
  31. package/lib/loaders/productVariationTextLoader.d.ts +14 -0
  32. package/lib/loaders/productVariationTextLoader.d.ts.map +1 -0
  33. package/lib/loaders/productVariationTextLoader.js +24 -0
  34. package/lib/loaders/productVariationTextLoader.js.map +1 -0
  35. package/lib/loaders/quotationLoader.d.ts +10 -0
  36. package/lib/loaders/quotationLoader.d.ts.map +1 -0
  37. package/lib/loaders/quotationLoader.js +13 -0
  38. package/lib/loaders/quotationLoader.js.map +1 -0
  39. package/lib/mcp/resources/localization.d.ts.map +1 -1
  40. package/lib/mcp/resources/localization.js +0 -15
  41. package/lib/mcp/resources/localization.js.map +1 -1
  42. package/lib/mongo-store.d.ts +94 -0
  43. package/lib/mongo-store.d.ts.map +1 -0
  44. package/lib/mongo-store.js +368 -0
  45. package/lib/mongo-store.js.map +1 -0
  46. package/lib/resolvers/type/index.d.ts +1 -1
  47. package/lib/resolvers/type/order/order-item-types.d.ts +1 -1
  48. package/lib/resolvers/type/order/order-item-types.d.ts.map +1 -1
  49. package/lib/resolvers/type/order/order-item-types.js +2 -3
  50. package/lib/resolvers/type/order/order-item-types.js.map +1 -1
  51. package/lib/resolvers/type/product/product-variation-assignment-vector.d.ts.map +1 -1
  52. package/lib/resolvers/type/product/product-variation-assignment-vector.js +4 -6
  53. package/lib/resolvers/type/product/product-variation-assignment-vector.js.map +1 -1
  54. package/lib/resolvers/type/product/product-variation-option-types.d.ts.map +1 -1
  55. package/lib/resolvers/type/product/product-variation-option-types.js +2 -3
  56. package/lib/resolvers/type/product/product-variation-option-types.js.map +1 -1
  57. package/lib/resolvers/type/product/product-variation-types.d.ts.map +1 -1
  58. package/lib/resolvers/type/product/product-variation-types.js +2 -3
  59. package/lib/resolvers/type/product/product-variation-types.js.map +1 -1
  60. package/package.json +6 -9
  61. package/src/express/chatHandler.ts +3 -8
  62. package/src/express/index.ts +3 -2
  63. package/src/fastify/chatHandler.ts +3 -8
  64. package/src/fastify/ercMetadataHandler.ts +9 -4
  65. package/src/fastify/index.ts +1 -1
  66. package/src/loaders/index.ts +11 -2
  67. package/src/loaders/productVariationByKeyLoader.ts +20 -0
  68. package/src/loaders/productVariationLoader.ts +19 -0
  69. package/src/loaders/productVariationTextLoader.ts +37 -0
  70. package/src/loaders/quotationLoader.ts +19 -0
  71. package/src/mcp/resources/localization.ts +0 -15
  72. package/src/mongo-store.ts +500 -0
  73. package/src/resolvers/type/order/order-item-types.ts +2 -3
  74. package/src/resolvers/type/product/product-variation-assignment-vector.ts +4 -6
  75. package/src/resolvers/type/product/product-variation-option-types.ts +2 -3
  76. package/src/resolvers/type/product/product-variation-types.ts +2 -3
  77. /package/src/loaders/{productLoaderBySKU.ts → productBySKULoader.ts} +0 -0
@@ -1 +1 @@
1
- {"version":3,"file":"product-variation-option-types.d.ts","sourceRoot":"","sources":["../../../../src/resolvers/type/product/product-variation-option-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,MAAM,MAAM,gBAAgB,CAAC,CAAC,EAAE,CAAC,IAAI,CACnC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,sBAAsB,EAAE,MAAM,CAAA;CAAE,EACvD,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,OAAO,KACb,CAAC,CAAC;AAEP,MAAM,WAAW,iCAAiC;IAChD,GAAG,EAAE,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACrC,KAAK,EAAE,gBAAgB,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACjF,KAAK,EAAE,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;CACxC;AACD,eAAO,MAAM,sBAAsB,EAAE,iCAgBpC,CAAC"}
1
+ {"version":3,"file":"product-variation-option-types.d.ts","sourceRoot":"","sources":["../../../../src/resolvers/type/product/product-variation-option-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AAEpE,MAAM,MAAM,gBAAgB,CAAC,CAAC,EAAE,CAAC,IAAI,CACnC,MAAM,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,sBAAsB,EAAE,MAAM,CAAA;CAAE,EACvD,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,OAAO,KACb,CAAC,CAAC;AAEP,MAAM,WAAW,iCAAiC;IAChD,GAAG,EAAE,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;IACrC,KAAK,EAAE,gBAAgB,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;IACjF,KAAK,EAAE,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;CACxC;AACD,eAAO,MAAM,sBAAsB,EAAE,iCAepC,CAAC"}
@@ -5,9 +5,8 @@ export const ProductVariationOption = {
5
5
  value: (obj) => {
6
6
  return obj.productVariationOption;
7
7
  },
8
- texts: async (obj, { forceLocale }, { modules, locale }) => {
9
- // TODO: use variation text loader
10
- return modules.products.variations.texts.findLocalizedVariationText({
8
+ texts: async (obj, { forceLocale }, { loaders, locale }) => {
9
+ return loaders.productVariationTextLoader.load({
11
10
  productVariationId: obj._id,
12
11
  productVariationOptionValue: obj.productVariationOption,
13
12
  locale: forceLocale ? new Intl.Locale(forceLocale) : locale,
@@ -1 +1 @@
1
- {"version":3,"file":"product-variation-option-types.js","sourceRoot":"","sources":["../../../../src/resolvers/type/product/product-variation-option-types.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,sBAAsB,GAAsC;IACvE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;QACX,OAAO,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,sBAAsB,EAAE,CAAC;IACpD,CAAC;IACD,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;QACb,OAAO,GAAG,CAAC,sBAAsB,CAAC;IACpC,CAAC;IAED,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;QACzD,kCAAkC;QAClC,OAAO,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,0BAA0B,CAAC;YAClE,kBAAkB,EAAE,GAAG,CAAC,GAAG;YAC3B,2BAA2B,EAAE,GAAG,CAAC,sBAAsB;YACvD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM;SAC5D,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"product-variation-option-types.js","sourceRoot":"","sources":["../../../../src/resolvers/type/product/product-variation-option-types.ts"],"names":[],"mappings":"AAcA,MAAM,CAAC,MAAM,sBAAsB,GAAsC;IACvE,GAAG,EAAE,CAAC,GAAG,EAAE,EAAE;QACX,OAAO,GAAG,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,sBAAsB,EAAE,CAAC;IACpD,CAAC;IACD,KAAK,EAAE,CAAC,GAAG,EAAE,EAAE;QACb,OAAO,GAAG,CAAC,sBAAsB,CAAC;IACpC,CAAC;IAED,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;QACzD,OAAO,OAAO,CAAC,0BAA0B,CAAC,IAAI,CAAC;YAC7C,kBAAkB,EAAE,GAAG,CAAC,GAAG;YAC3B,2BAA2B,EAAE,GAAG,CAAC,sBAAsB;YACvD,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM;SAC5D,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"product-variation-types.d.ts","sourceRoot":"","sources":["../../../../src/resolvers/type/product/product-variation-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EACL,gBAAgB,IAAI,oBAAoB,EACxC,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,MAAM,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI,CAC7B,gBAAgB,EAAE,oBAAoB,EACtC,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,OAAO,KACb,CAAC,CAAC;AAEP,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,UAAU,CACjB,KAAK,EACL;QACE,GAAG,EAAE,MAAM,CAAC;QACZ,sBAAsB,EAAE,MAAM,CAAC;KAChC,EAAE,CACJ,CAAC;IACF,KAAK,EAAE,UAAU,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;CAC5E;AACD,eAAO,MAAM,gBAAgB,EAAE,2BAe9B,CAAC"}
1
+ {"version":3,"file":"product-variation-types.d.ts","sourceRoot":"","sources":["../../../../src/resolvers/type/product/product-variation-types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AAC9C,OAAO,EACL,gBAAgB,IAAI,oBAAoB,EACxC,oBAAoB,EACrB,MAAM,8BAA8B,CAAC;AAEtC,MAAM,MAAM,UAAU,CAAC,CAAC,EAAE,CAAC,IAAI,CAC7B,gBAAgB,EAAE,oBAAoB,EACtC,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,OAAO,KACb,CAAC,CAAC;AAEP,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,UAAU,CACjB,KAAK,EACL;QACE,GAAG,EAAE,MAAM,CAAC;QACZ,sBAAsB,EAAE,MAAM,CAAC;KAChC,EAAE,CACJ,CAAC;IACF,KAAK,EAAE,UAAU,CAAC;QAAE,WAAW,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC;CAC5E;AACD,eAAO,MAAM,gBAAgB,EAAE,2BAc9B,CAAC"}
@@ -5,9 +5,8 @@ export const ProductVariation = {
5
5
  productVariationOption: option,
6
6
  }));
7
7
  },
8
- texts: async (obj, { forceLocale }, { modules, locale }) => {
9
- // TODO: use variation text loader
10
- return modules.products.variations.texts.findLocalizedVariationText({
8
+ texts: async (obj, { forceLocale }, { loaders, locale }) => {
9
+ return loaders.productVariationTextLoader.load({
11
10
  productVariationId: obj._id,
12
11
  locale: forceLocale ? new Intl.Locale(forceLocale) : locale,
13
12
  });
@@ -1 +1 @@
1
- {"version":3,"file":"product-variation-types.js","sourceRoot":"","sources":["../../../../src/resolvers/type/product/product-variation-types.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAC,MAAM,gBAAgB,GAAgC;IAC3D,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QACf,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC1C,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,sBAAsB,EAAE,MAAM;SAC/B,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;QACzD,kCAAkC;QAClC,OAAO,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,KAAK,CAAC,0BAA0B,CAAC;YAClE,kBAAkB,EAAE,GAAG,CAAC,GAAG;YAC3B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM;SAC5D,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
1
+ {"version":3,"file":"product-variation-types.js","sourceRoot":"","sources":["../../../../src/resolvers/type/product/product-variation-types.ts"],"names":[],"mappings":"AAsBA,MAAM,CAAC,MAAM,gBAAgB,GAAgC;IAC3D,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;QACf,OAAO,CAAC,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;YAC1C,GAAG,EAAE,GAAG,CAAC,GAAG;YACZ,sBAAsB,EAAE,MAAM;SAC/B,CAAC,CAAC,CAAC;IACN,CAAC;IAED,KAAK,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE,WAAW,EAAE,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE;QACzD,OAAO,OAAO,CAAC,0BAA0B,CAAC,IAAI,CAAC;YAC7C,kBAAkB,EAAE,GAAG,CAAC,GAAG;YAC3B,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM;SAC5D,CAAC,CAAC;IACL,CAAC;CACF,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unchainedshop/api",
3
- "version": "4.3.0",
3
+ "version": "4.3.1",
4
4
  "main": "lib/api-index.js",
5
5
  "types": "lib/api-index.d.ts",
6
6
  "type": "module",
@@ -56,6 +56,7 @@
56
56
  },
57
57
  "homepage": "https://github.com/unchainedshop/unchained#readme",
58
58
  "peerDependencies": {
59
+ "@ai-sdk/mcp": "^0.0.8",
59
60
  "@fastify/cookie": ">= 11 < 12",
60
61
  "@fastify/multipart": ">= 9 < 10",
61
62
  "@fastify/session": ">= 11 < 12",
@@ -64,8 +65,6 @@
64
65
  "@noble/curves": "^2.0.0",
65
66
  "@noble/hashes": "^2.0.0",
66
67
  "ai": ">= 5 < 6",
67
- "@ai-sdk/mcp": "^0.0.8",
68
- "connect-mongo": ">= 5.1 < 6",
69
68
  "express": ">= 5 < 6",
70
69
  "express-session": ">= 1.18 < 2",
71
70
  "fastify": ">= 5.2 < 6",
@@ -80,7 +79,7 @@
80
79
  "graphql-yoga": {
81
80
  "optional": false
82
81
  },
83
- "connect-mongo": {
82
+ "express-session": {
84
83
  "optional": false
85
84
  },
86
85
  "ai": {
@@ -107,9 +106,6 @@
107
106
  "express": {
108
107
  "optional": true
109
108
  },
110
- "express-session": {
111
- "optional": true
112
- },
113
109
  "multer": {
114
110
  "optional": true
115
111
  },
@@ -131,13 +127,14 @@
131
127
  "@unchainedshop/utils": "^4.3.0",
132
128
  "dataloader": "^2.2.3",
133
129
  "expiry-map": "^2.0.0",
134
- "mime": ">= 4 < 5",
135
130
  "graphql-scalars": "^1.24.2",
131
+ "mime": ">= 4 < 5",
136
132
  "moniker": "0.1.2",
137
133
  "p-memoize": "^8.0.0",
138
134
  "zod": "^3.25.76 || ^4"
139
135
  },
140
136
  "devDependencies": {
137
+ "@ai-sdk/mcp": "^0.0.8",
141
138
  "@fastify/cookie": "^11.0.2",
142
139
  "@fastify/multipart": "^9.0.3",
143
140
  "@fastify/session": "^11.1.0",
@@ -146,8 +143,8 @@
146
143
  "@noble/curves": "^2.0.0",
147
144
  "@noble/hashes": "^2.0.0",
148
145
  "@types/express": "^5.0.3",
146
+ "@types/express-session": "^1.18.2",
149
147
  "@types/node": "^24.0.13",
150
- "@ai-sdk/mcp": "^0.0.8",
151
148
  "ai": "^5.0.80",
152
149
  "express": "^5.1.0",
153
150
  "express-session": "^1.18.1",
@@ -62,12 +62,7 @@ const setupMCPChatHandler = (chatConfiguration: ChatConfiguration & any): Reques
62
62
  },
63
63
  });
64
64
 
65
- const sdkClient = new Client(
66
- { name: 'unchained-chat-client', version: '1.0.0' },
67
- {
68
- capabilities: { resources: {} },
69
- },
70
- );
65
+ const sdkClient = new Client({ name: 'unchained-chat-client', version: '1.0.0' });
71
66
  await sdkClient.connect(resourceTransport as any);
72
67
  const transport = new StreamableHTTPClientTransport(new URL(unchainedMCPUrl), {
73
68
  requestInit: {
@@ -91,8 +86,8 @@ const setupMCPChatHandler = (chatConfiguration: ChatConfiguration & any): Reques
91
86
  resources.resources.map(async (resource) => {
92
87
  try {
93
88
  const content = await sdkClient.readResource({ uri: resource.uri });
94
- if (content?.contents?.[0]?.text) {
95
- return `${resource.name}:\n${content.contents[0].text}`;
89
+ if ((content?.contents?.[0] as any)?.text) {
90
+ return `${resource.name}:\n${(content.contents[0] as any).text}`;
96
91
  }
97
92
  } catch (e) {
98
93
  logger.error(`Failed to read resource ${resource.uri}:`, e);
@@ -1,7 +1,7 @@
1
1
  import e from 'express';
2
2
  import session from 'express-session';
3
3
  import multer from 'multer';
4
- import MongoStore from 'connect-mongo';
4
+ import MongoStore from '../mongo-store.js';
5
5
  import { Passport } from 'passport';
6
6
  import { YogaServerInstance } from 'graphql-yoga';
7
7
  import { mongodb } from '@unchainedshop/mongodb';
@@ -17,6 +17,7 @@ import createMCPMiddleware from './createMCPMiddleware.js';
17
17
  import { API_EVENTS } from '../events.js';
18
18
  import { ChatConfiguration } from '../chat/utils.js';
19
19
  import { connectChat } from './chatHandler.js';
20
+ import { CipherKey } from 'node:crypto';
20
21
  export interface AdminUIRouterOptions {
21
22
  prefix: string;
22
23
  enabled?: boolean;
@@ -217,7 +218,7 @@ export const connect = (
217
218
 
218
219
  expressApp.use(
219
220
  session({
220
- secret: process.env.UNCHAINED_TOKEN_SECRET,
221
+ secret: process.env.UNCHAINED_TOKEN_SECRET as CipherKey,
221
222
  store: MongoStore.create({
222
223
  client: (db as any).client,
223
224
  dbName: db.databaseName,
@@ -60,12 +60,7 @@ const setupMCPChatHandler = (chatConfiguration: ChatConfiguration & any) => {
60
60
  },
61
61
  });
62
62
 
63
- const sdkClient = new Client(
64
- { name: 'unchained-chat-client', version: '1.0.0' },
65
- {
66
- capabilities: { resources: {} },
67
- },
68
- );
63
+ const sdkClient = new Client({ name: 'unchained-chat-client', version: '1.0.0' });
69
64
  await sdkClient.connect(resourceTransport as any);
70
65
 
71
66
  const transport = new StreamableHTTPClientTransport(new URL(unchainedMCPUrl), {
@@ -90,8 +85,8 @@ const setupMCPChatHandler = (chatConfiguration: ChatConfiguration & any) => {
90
85
  resources.resources.map(async (resource) => {
91
86
  try {
92
87
  const content = await sdkClient.readResource({ uri: resource.uri });
93
- if (content?.contents?.[0]?.text) {
94
- return `${resource.name}:\n${content.contents[0].text}`;
88
+ if ((content?.contents?.[0] as any)?.text) {
89
+ return `${resource.name}:\n${(content.contents[0] as any).text}`;
95
90
  }
96
91
  } catch (e) {
97
92
  logger.error(`Failed to read resource ${resource.uri}:`, e);
@@ -1,6 +1,7 @@
1
1
  import { createLogger } from '@unchainedshop/logger';
2
2
  import { Context } from '../context.js';
3
3
  import { FastifyRequest, RouteHandlerMethod } from 'fastify';
4
+ import { ProductContractStandard } from '@unchainedshop/core-products';
4
5
 
5
6
  const logger = createLogger('unchained:api:erc-metadata');
6
7
 
@@ -26,10 +27,14 @@ const ercMetadataHandler: RouteHandlerMethod = async (
26
27
 
27
28
  const product = await loaders.productLoader.load({ productId });
28
29
 
29
- const [token] = await modules.warehousing.findTokens({
30
- tokenSerialNumber: (tokenFileName || localeOrTokenFilename).toLowerCase().replace('.json', ''),
31
- contractAddress: product?.tokenization?.contractAddress,
32
- });
30
+ const tokenSelector = { contractAddress: product?.tokenization?.contractAddress };
31
+
32
+ if (product.tokenization?.contractStandard !== ProductContractStandard.ERC721)
33
+ tokenSelector['tokenSerialNumber'] = (tokenFileName || localeOrTokenFilename)
34
+ .toLowerCase()
35
+ .replace('.json', '');
36
+
37
+ const [token] = await modules.warehousing.findTokens(tokenSelector);
33
38
 
34
39
  const ercMetadata = await services.warehousing.ercMetadata({
35
40
  product,
@@ -1,7 +1,7 @@
1
1
  import { getCurrentContextResolver, LoginFn, LogoutFn } from '../context.js';
2
2
  import bulkImportHandler from './bulkImportHandler.js';
3
3
  import ercMetadataHandler from './ercMetadataHandler.js';
4
- import MongoStore from 'connect-mongo';
4
+ import MongoStore from '../mongo-store.js';
5
5
  import { YogaServerInstance } from 'graphql-yoga';
6
6
  import { mongodb } from '@unchainedshop/mongodb';
7
7
  import { UnchainedCore } from '@unchainedshop/core';
@@ -10,11 +10,14 @@ import assortmentProductsLoader from './assortmentProductsLoader.js';
10
10
  import filterLoader from './filterLoader.js';
11
11
  import filterTextLoader from './filterTextLoader.js';
12
12
  import productLoader from './productLoader.js';
13
- import productLoaderBySKU from './productLoaderBySKU.js';
13
+ import productBySKULoader from './productBySKULoader.js';
14
14
  import productTextLoader from './productTextLoader.js';
15
15
  import productMediaTextLoader from './productMediaTextLoader.js';
16
16
  import productMediasLoader from './productMediasLoader.js';
17
17
  import productProxiesLoader from './productProxiesLoader.js';
18
+ import productVariationLoader from './productVariationLoader.js';
19
+ import productVariationByKeyLoader from './productVariationByKeyLoader.js';
20
+ import productVariationTextLoader from './productVariationTextLoader.js';
18
21
  import fileLoader from './fileLoader.js';
19
22
  import userLoader from './userLoader.js';
20
23
  import countryLoader from './countryLoader.js';
@@ -24,6 +27,7 @@ import deliveryProviderLoader from './deliveryProviderLoader.js';
24
27
  import paymentProviderLoader from './paymentProviderLoader.js';
25
28
  import warehousingProviderLoader from './warehousingProviderLoader.js';
26
29
  import orderLoader from './orderLoader.js';
30
+ import quotationLoader from './quotationLoader.js';
27
31
 
28
32
  const loaders = (unchainedAPI: UnchainedCore) => {
29
33
  return {
@@ -40,11 +44,14 @@ const loaders = (unchainedAPI: UnchainedCore) => {
40
44
  filterTextLoader: filterTextLoader(unchainedAPI),
41
45
 
42
46
  productLoader: productLoader(unchainedAPI),
43
- productLoaderBySKU: productLoaderBySKU(unchainedAPI),
47
+ productBySKULoader: productBySKULoader(unchainedAPI),
44
48
  productTextLoader: productTextLoader(unchainedAPI),
45
49
  productMediaTextLoader: productMediaTextLoader(unchainedAPI),
46
50
  productMediasLoader: productMediasLoader(unchainedAPI),
47
51
  productProxiesLoader: productProxiesLoader(unchainedAPI),
52
+ productVariationLoader: productVariationLoader(unchainedAPI),
53
+ productVariationByKeyLoader: productVariationByKeyLoader(unchainedAPI),
54
+ productVariationTextLoader: productVariationTextLoader(unchainedAPI),
48
55
 
49
56
  fileLoader: fileLoader(unchainedAPI),
50
57
 
@@ -63,6 +70,8 @@ const loaders = (unchainedAPI: UnchainedCore) => {
63
70
  warehousingProviderLoader: warehousingProviderLoader(unchainedAPI),
64
71
 
65
72
  orderLoader: orderLoader(unchainedAPI),
73
+
74
+ quotationLoader: quotationLoader(unchainedAPI),
66
75
  };
67
76
  };
68
77
 
@@ -0,0 +1,20 @@
1
+ import { UnchainedCore } from '@unchainedshop/core';
2
+ import { ProductVariation } from '@unchainedshop/core-products';
3
+ import DataLoader from 'dataloader';
4
+
5
+ export default (unchainedAPI: UnchainedCore) =>
6
+ new DataLoader<{ productId: string; key: string }, ProductVariation | null>(async (queries) => {
7
+ const productIds = [...new Set(queries.map((q) => q.productId).filter(Boolean))];
8
+
9
+ const variations = await unchainedAPI.modules.products.variations.findProductVariations({
10
+ productId: { $in: productIds },
11
+ });
12
+
13
+ // Create a map with composite key: productId:key
14
+ const variationMap: Record<string, ProductVariation> = {};
15
+ for (const variation of variations) {
16
+ variationMap[`${variation.productId}:${variation.key}`] = variation;
17
+ }
18
+
19
+ return queries.map((q) => variationMap[`${q.productId}:${q.key}`] || null);
20
+ });
@@ -0,0 +1,19 @@
1
+ import { UnchainedCore } from '@unchainedshop/core';
2
+ import { ProductVariation } from '@unchainedshop/core-products';
3
+ import DataLoader from 'dataloader';
4
+
5
+ export default (unchainedAPI: UnchainedCore) =>
6
+ new DataLoader<{ productVariationId: string }, ProductVariation | null>(async (queries) => {
7
+ const productVariationIds = [...new Set(queries.map((q) => q.productVariationId).filter(Boolean))];
8
+
9
+ const variations = await unchainedAPI.modules.products.variations.findProductVariations({
10
+ _id: { $in: productVariationIds },
11
+ });
12
+
13
+ const variationMap: Record<string, ProductVariation> = {};
14
+ for (const variation of variations) {
15
+ variationMap[variation._id] = variation;
16
+ }
17
+
18
+ return queries.map((q) => variationMap[q.productVariationId] || null);
19
+ });
@@ -0,0 +1,37 @@
1
+ import { UnchainedCore } from '@unchainedshop/core';
2
+ import DataLoader from 'dataloader';
3
+ import { ProductVariationText } from '@unchainedshop/core-products';
4
+ import buildTextMap from './buildTextMap.js';
5
+ import buildLocaleMap from './buildLocaleMap.js';
6
+
7
+ export default (unchainedAPI: UnchainedCore) =>
8
+ new DataLoader<
9
+ { productVariationId: string; productVariationOptionValue?: string; locale: Intl.Locale },
10
+ ProductVariationText
11
+ >(async (queries) => {
12
+ const productVariationIds = [...new Set(queries.map((q) => q.productVariationId).filter(Boolean))];
13
+
14
+ const texts = await unchainedAPI.modules.products.variations.texts.findVariationTexts(
15
+ {
16
+ productVariationId: { $in: productVariationIds },
17
+ },
18
+ {
19
+ sort: {
20
+ productVariationId: 1,
21
+ },
22
+ },
23
+ );
24
+
25
+ const localeMap = buildLocaleMap(queries, texts);
26
+
27
+ // Build a map with composite key: locale + productVariationId + productVariationOptionValue
28
+ const textsMap = buildTextMap(localeMap, texts, (text) => {
29
+ const optionValue = text.productVariationOptionValue || '';
30
+ return text.productVariationId + optionValue;
31
+ });
32
+
33
+ return queries.map((q) => {
34
+ const optionValue = q.productVariationOptionValue || '';
35
+ return textsMap[q.locale + q.productVariationId + optionValue];
36
+ });
37
+ });
@@ -0,0 +1,19 @@
1
+ import { UnchainedCore } from '@unchainedshop/core';
2
+ import { Quotation } from '@unchainedshop/core-quotations';
3
+ import DataLoader from 'dataloader';
4
+
5
+ export default (unchainedAPI: UnchainedCore) =>
6
+ new DataLoader<{ quotationId: string }, Quotation | null>(async (queries) => {
7
+ const quotationIds = [...new Set(queries.map((q) => q.quotationId).filter(Boolean))];
8
+
9
+ const quotations = await unchainedAPI.modules.quotations.findQuotations({
10
+ _id: { $in: quotationIds },
11
+ });
12
+
13
+ const quotationMap: Record<string, Quotation> = {};
14
+ for (const quotation of quotations) {
15
+ quotationMap[quotation._id] = quotation;
16
+ }
17
+
18
+ return queries.map((q) => quotationMap[q.quotationId] || null);
19
+ });
@@ -9,11 +9,6 @@ export const registerLocalizationResources = (server: McpServer, context: Contex
9
9
  description:
10
10
  'Available languages configured in the shop. Use these ISO codes when creating or updating products, filters, and assortments. Includes valid language-country dialect combinations.',
11
11
  mimeType: 'application/json',
12
- annotations: {
13
- audience: ['assistant'],
14
- priority: 1,
15
- lastModified: '2025-09-30T15:00:58Z',
16
- },
17
12
  },
18
13
  async () => {
19
14
  const [languages, countries] = await Promise.all([
@@ -58,11 +53,6 @@ export const registerLocalizationResources = (server: McpServer, context: Contex
58
53
  description:
59
54
  'Available currencies configured in the shop. Check decimal points for price conversions. All prices are stored as integers.',
60
55
  mimeType: 'application/json',
61
- annotations: {
62
- audience: ['assistant'],
63
- priority: 1,
64
- lastModified: '2025-09-30T15:00:58Z',
65
- },
66
56
  },
67
57
  async () => {
68
58
  const currencies = await context.modules.currencies.findCurrencies({ includeInactive: false });
@@ -96,11 +86,6 @@ export const registerLocalizationResources = (server: McpServer, context: Contex
96
86
  description:
97
87
  'Available countries configured in the shop. Use these ISO codes for geographic operations.',
98
88
  mimeType: 'application/json',
99
- annotations: {
100
- audience: ['assistant'],
101
- priority: 1,
102
- lastModified: '2025-09-30T15:00:58Z',
103
- },
104
89
  },
105
90
  async () => {
106
91
  const countries = await context.modules.countries.findCountries({ includeInactive: false });