@unchainedshop/api 2.0.0-beta6 → 2.0.0-beta8

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 (271) hide show
  1. package/lib/api-index.d.ts +4 -7
  2. package/lib/api-index.js +24 -14
  3. package/lib/api-index.js.map +1 -1
  4. package/lib/context.d.ts +0 -1
  5. package/lib/context.js +0 -11
  6. package/lib/context.js.map +1 -1
  7. package/lib/createGraphQLServer.d.ts +2 -2
  8. package/lib/createGraphQLServer.js +12 -53
  9. package/lib/createGraphQLServer.js.map +1 -1
  10. package/lib/errors.js +8 -3
  11. package/lib/errors.js.map +1 -1
  12. package/lib/express/createApolloMiddleware.d.ts +4 -0
  13. package/lib/express/createApolloMiddleware.js +34 -0
  14. package/lib/express/createApolloMiddleware.js.map +1 -0
  15. package/lib/express/createBulkImportMiddleware.d.ts +2 -0
  16. package/lib/express/createBulkImportMiddleware.js +79 -0
  17. package/lib/express/createBulkImportMiddleware.js.map +1 -0
  18. package/lib/express/createERCMetadataMiddleware.d.ts +3 -0
  19. package/lib/express/createERCMetadataMiddleware.js +56 -0
  20. package/lib/express/createERCMetadataMiddleware.js.map +1 -0
  21. package/lib/express/createSingleSignOnMiddleware.d.ts +6 -0
  22. package/lib/express/createSingleSignOnMiddleware.js +71 -0
  23. package/lib/express/createSingleSignOnMiddleware.js.map +1 -0
  24. package/lib/express/index.d.ts +6 -0
  25. package/lib/express/index.js +27 -0
  26. package/lib/express/index.js.map +1 -0
  27. package/lib/loaders/index.js +50 -0
  28. package/lib/loaders/index.js.map +1 -1
  29. package/lib/resolvers/index.js +1 -1
  30. package/lib/resolvers/index.js.map +1 -1
  31. package/lib/resolvers/mutations/accounts/changePassword.d.ts +0 -2
  32. package/lib/resolvers/mutations/accounts/changePassword.js +2 -2
  33. package/lib/resolvers/mutations/accounts/changePassword.js.map +1 -1
  34. package/lib/resolvers/mutations/accounts/createUser.js +2 -2
  35. package/lib/resolvers/mutations/accounts/createUser.js.map +1 -1
  36. package/lib/resolvers/mutations/accounts/enrollUser.js +1 -1
  37. package/lib/resolvers/mutations/accounts/enrollUser.js.map +1 -1
  38. package/lib/resolvers/mutations/accounts/loginWithPassword.d.ts +0 -1
  39. package/lib/resolvers/mutations/accounts/loginWithPassword.js +3 -3
  40. package/lib/resolvers/mutations/accounts/loginWithPassword.js.map +1 -1
  41. package/lib/resolvers/mutations/accounts/resetPassword.d.ts +0 -1
  42. package/lib/resolvers/mutations/accounts/resetPassword.js +1 -1
  43. package/lib/resolvers/mutations/accounts/resetPassword.js.map +1 -1
  44. package/lib/resolvers/mutations/accounts/setPassword.d.ts +0 -1
  45. package/lib/resolvers/mutations/accounts/setPassword.js +1 -1
  46. package/lib/resolvers/mutations/accounts/setPassword.js.map +1 -1
  47. package/lib/resolvers/mutations/assortments/removeAssortment.js +1 -1
  48. package/lib/resolvers/mutations/assortments/removeAssortment.js.map +1 -1
  49. package/lib/resolvers/mutations/assortments/removeAssortmentFilter.js +1 -1
  50. package/lib/resolvers/mutations/assortments/removeAssortmentFilter.js.map +1 -1
  51. package/lib/resolvers/mutations/assortments/removeAssortmentLink.js +1 -1
  52. package/lib/resolvers/mutations/assortments/removeAssortmentLink.js.map +1 -1
  53. package/lib/resolvers/mutations/assortments/removeAssortmentProduct.js +1 -1
  54. package/lib/resolvers/mutations/assortments/removeAssortmentProduct.js.map +1 -1
  55. package/lib/resolvers/mutations/enrollments/updateEnrollment.d.ts +1 -1
  56. package/lib/resolvers/mutations/filters/removeFilter.js +1 -1
  57. package/lib/resolvers/mutations/filters/removeFilter.js.map +1 -1
  58. package/lib/resolvers/mutations/filters/updateFilter.js +2 -1
  59. package/lib/resolvers/mutations/filters/updateFilter.js.map +1 -1
  60. package/lib/resolvers/mutations/index.d.ts +1 -1
  61. package/lib/resolvers/mutations/pageView.d.ts +1 -1
  62. package/lib/resolvers/mutations/pageView.js +2 -2
  63. package/lib/resolvers/mutations/pageView.js.map +1 -1
  64. package/lib/resolvers/mutations/products/removeProduct.d.ts +1 -1
  65. package/lib/resolvers/mutations/products/removeProduct.js +5 -8
  66. package/lib/resolvers/mutations/products/removeProduct.js.map +1 -1
  67. package/lib/resolvers/queries/products/product.js +1 -1
  68. package/lib/resolvers/queries/products/productCatalogPrices.d.ts +1 -1
  69. package/lib/resolvers/queries/products/productCatalogPrices.js +5 -2
  70. package/lib/resolvers/queries/products/productCatalogPrices.js.map +1 -1
  71. package/lib/resolvers/queries/products/products.js +1 -1
  72. package/lib/resolvers/queries/products/products.js.map +1 -1
  73. package/lib/resolvers/scalars/LowerCaseString.d.ts +1 -1
  74. package/lib/resolvers/scalars/index.d.ts +1 -1
  75. package/lib/resolvers/type/assortment/assortment-filter-types.d.ts +2 -2
  76. package/lib/resolvers/type/assortment/assortment-filter-types.js +13 -6
  77. package/lib/resolvers/type/assortment/assortment-filter-types.js.map +1 -1
  78. package/lib/resolvers/type/assortment/assortment-link-types.d.ts +2 -2
  79. package/lib/resolvers/type/assortment/assortment-link-types.js +14 -6
  80. package/lib/resolvers/type/assortment/assortment-link-types.js.map +1 -1
  81. package/lib/resolvers/type/assortment/assortment-media-types.d.ts +1 -1
  82. package/lib/resolvers/type/assortment/assortment-path-link-types.d.ts +1 -4
  83. package/lib/resolvers/type/assortment/assortment-path-link-types.js +0 -7
  84. package/lib/resolvers/type/assortment/assortment-path-link-types.js.map +1 -1
  85. package/lib/resolvers/type/assortment/assortment-product-types.d.ts +2 -2
  86. package/lib/resolvers/type/assortment/assortment-product-types.js +14 -6
  87. package/lib/resolvers/type/assortment/assortment-product-types.js.map +1 -1
  88. package/lib/resolvers/type/assortment/assortment-types.d.ts +1 -1
  89. package/lib/resolvers/type/bookmark-types.d.ts +1 -1
  90. package/lib/resolvers/type/bookmark-types.js +6 -2
  91. package/lib/resolvers/type/bookmark-types.js.map +1 -1
  92. package/lib/resolvers/type/country-types.d.ts +1 -1
  93. package/lib/resolvers/type/delivery-provider-types.d.ts +1 -1
  94. package/lib/resolvers/type/enrollment/enrollment-delivery-types.d.ts +2 -2
  95. package/lib/resolvers/type/enrollment/enrollment-payment-types.d.ts +2 -2
  96. package/lib/resolvers/type/enrollment/enrollment-period-types.d.ts +2 -2
  97. package/lib/resolvers/type/enrollment/enrollment-plan-tyes.d.ts +2 -2
  98. package/lib/resolvers/type/enrollment/enrollment-plan-tyes.js +6 -2
  99. package/lib/resolvers/type/enrollment/enrollment-plan-tyes.js.map +1 -1
  100. package/lib/resolvers/type/enrollment/enrollment-types.d.ts +2 -2
  101. package/lib/resolvers/type/event-types.d.ts +1 -1
  102. package/lib/resolvers/type/filter/filter-option-types.d.ts +2 -2
  103. package/lib/resolvers/type/filter/filter-types.d.ts +2 -2
  104. package/lib/resolvers/type/order/order-delivery-discount-types.d.ts +1 -1
  105. package/lib/resolvers/type/order/order-delivery-pickup-types.d.ts +1 -1
  106. package/lib/resolvers/type/order/order-delivery-shipping-types.d.ts +1 -1
  107. package/lib/resolvers/type/order/order-discount-types.d.ts +1 -1
  108. package/lib/resolvers/type/order/order-global-discount-types.d.ts +1 -1
  109. package/lib/resolvers/type/order/order-item-discount-types.d.ts +1 -1
  110. package/lib/resolvers/type/order/order-item-types.d.ts +1 -1
  111. package/lib/resolvers/type/order/order-item-types.js +13 -6
  112. package/lib/resolvers/type/order/order-item-types.js.map +1 -1
  113. package/lib/resolvers/type/order/order-payment-card-types.d.ts +1 -1
  114. package/lib/resolvers/type/order/order-payment-discount-types.d.ts +1 -1
  115. package/lib/resolvers/type/order/order-payment-generic-types.d.ts +1 -1
  116. package/lib/resolvers/type/order/order-payment-invoice-types.d.ts +1 -1
  117. package/lib/resolvers/type/order/order-types.d.ts +1 -1
  118. package/lib/resolvers/type/price-types.d.ts +1 -1
  119. package/lib/resolvers/type/product/product-bundle-item-types.js +4 -2
  120. package/lib/resolvers/type/product/product-bundle-item-types.js.map +1 -1
  121. package/lib/resolvers/type/product/product-discount.d.ts +1 -1
  122. package/lib/resolvers/type/product/product-review-types.d.ts +1 -1
  123. package/lib/resolvers/type/product/product-review-types.js +6 -2
  124. package/lib/resolvers/type/product/product-review-types.js.map +1 -1
  125. package/lib/resolvers/type/product/product-tokenized-types.js +1 -0
  126. package/lib/resolvers/type/product/product-tokenized-types.js.map +1 -1
  127. package/lib/resolvers/type/product/product-variation-assignment-types.js +4 -2
  128. package/lib/resolvers/type/product/product-variation-assignment-types.js.map +1 -1
  129. package/lib/resolvers/type/quotation-types.d.ts +2 -2
  130. package/lib/resolvers/type/quotation-types.js +7 -3
  131. package/lib/resolvers/type/quotation-types.js.map +1 -1
  132. package/lib/resolvers/type/shop-types.d.ts +1 -1
  133. package/lib/resolvers/type/token-types.d.ts +1 -1
  134. package/lib/resolvers/type/user-types.d.ts +1 -3
  135. package/lib/resolvers/type/user-types.js +0 -12
  136. package/lib/resolvers/type/user-types.js.map +1 -1
  137. package/lib/resolvers/type/webauthn-credentials-types.d.ts +1 -1
  138. package/lib/resolvers/type/work-types.d.ts +1 -1
  139. package/lib/schema/{types/log.d.ts → directives.d.ts} +0 -0
  140. package/lib/schema/directives.js +15 -0
  141. package/lib/schema/directives.js.map +1 -0
  142. package/lib/schema/index.js +2 -1
  143. package/lib/schema/index.js.map +1 -1
  144. package/lib/schema/inputTypes.js +0 -15
  145. package/lib/schema/inputTypes.js.map +1 -1
  146. package/lib/schema/mutation.js +4 -23
  147. package/lib/schema/mutation.js.map +1 -1
  148. package/lib/schema/query.js +28 -10
  149. package/lib/schema/query.js.map +1 -1
  150. package/lib/schema/types/assortment.js +9 -10
  151. package/lib/schema/types/assortment.js.map +1 -1
  152. package/lib/schema/types/color.js +1 -1
  153. package/lib/schema/types/country.js +1 -1
  154. package/lib/schema/types/currency.js +1 -1
  155. package/lib/schema/types/delivery.js +3 -2
  156. package/lib/schema/types/delivery.js.map +1 -1
  157. package/lib/schema/types/dimensions.js +1 -1
  158. package/lib/schema/types/discount.js +1 -1
  159. package/lib/schema/types/dispatch.js +1 -0
  160. package/lib/schema/types/dispatch.js.map +1 -1
  161. package/lib/schema/types/filter.js +5 -8
  162. package/lib/schema/types/filter.js.map +1 -1
  163. package/lib/schema/types/geo-position.js +1 -1
  164. package/lib/schema/types/language.js +1 -1
  165. package/lib/schema/types/media.js +1 -1
  166. package/lib/schema/types/payment.js +3 -3
  167. package/lib/schema/types/price.js +2 -2
  168. package/lib/schema/types/product/bundle-product.js +2 -3
  169. package/lib/schema/types/product/bundle-product.js.map +1 -1
  170. package/lib/schema/types/product/configurable-product.js +7 -7
  171. package/lib/schema/types/product/plan-product.js +4 -3
  172. package/lib/schema/types/product/plan-product.js.map +1 -1
  173. package/lib/schema/types/product/product.js +11 -11
  174. package/lib/schema/types/product/simple-product.js +5 -4
  175. package/lib/schema/types/product/simple-product.js.map +1 -1
  176. package/lib/schema/types/product/tokenized-product.js +6 -3
  177. package/lib/schema/types/product/tokenized-product.js.map +1 -1
  178. package/lib/schema/types/search.js +3 -8
  179. package/lib/schema/types/search.js.map +1 -1
  180. package/lib/schema/types/shop.js +2 -2
  181. package/lib/schema/types/stock.js +1 -0
  182. package/lib/schema/types/stock.js.map +1 -1
  183. package/lib/schema/types/types.js +1 -1
  184. package/lib/schema/types/user.js +1 -3
  185. package/lib/schema/types/user.js.map +1 -1
  186. package/lib/schema/types/warehousing.js +3 -3
  187. package/package.json +31 -19
  188. package/src/api-index.ts +25 -29
  189. package/src/context.ts +0 -19
  190. package/src/createGraphQLServer.ts +11 -56
  191. package/src/errors.ts +8 -3
  192. package/src/express/createApolloMiddleware.ts +40 -0
  193. package/src/express/createBulkImportMiddleware.ts +90 -0
  194. package/src/express/createERCMetadataMiddleware.ts +72 -0
  195. package/src/express/createSingleSignOnMiddleware.ts +83 -0
  196. package/src/express/index.ts +48 -0
  197. package/src/loaders/index.ts +63 -3
  198. package/src/resolvers/index.ts +1 -1
  199. package/src/resolvers/mutations/accounts/changePassword.ts +2 -4
  200. package/src/resolvers/mutations/accounts/createUser.ts +2 -2
  201. package/src/resolvers/mutations/accounts/enrollUser.ts +1 -1
  202. package/src/resolvers/mutations/accounts/loginWithPassword.ts +3 -4
  203. package/src/resolvers/mutations/accounts/resetPassword.ts +2 -2
  204. package/src/resolvers/mutations/accounts/setPassword.ts +2 -2
  205. package/src/resolvers/mutations/assortments/removeAssortment.ts +1 -1
  206. package/src/resolvers/mutations/assortments/removeAssortmentFilter.ts +1 -1
  207. package/src/resolvers/mutations/assortments/removeAssortmentLink.ts +1 -1
  208. package/src/resolvers/mutations/assortments/removeAssortmentProduct.ts +1 -1
  209. package/src/resolvers/mutations/filters/removeFilter.ts +1 -1
  210. package/src/resolvers/mutations/filters/updateFilter.ts +3 -1
  211. package/src/resolvers/mutations/pageView.ts +2 -2
  212. package/src/resolvers/mutations/products/removeProduct.ts +6 -8
  213. package/src/resolvers/queries/products/product.ts +1 -1
  214. package/src/resolvers/queries/products/productCatalogPrices.ts +5 -2
  215. package/src/resolvers/queries/products/products.ts +1 -1
  216. package/src/resolvers/type/assortment/assortment-filter-types.ts +11 -6
  217. package/src/resolvers/type/assortment/assortment-link-types.ts +12 -6
  218. package/src/resolvers/type/assortment/assortment-path-link-types.ts +0 -11
  219. package/src/resolvers/type/assortment/assortment-product-types.ts +12 -6
  220. package/src/resolvers/type/bookmark-types.ts +7 -2
  221. package/src/resolvers/type/enrollment/enrollment-plan-tyes.ts +6 -2
  222. package/src/resolvers/type/order/order-item-types.ts +13 -6
  223. package/src/resolvers/type/product/product-bundle-item-types.ts +4 -2
  224. package/src/resolvers/type/product/product-review-types.ts +6 -2
  225. package/src/resolvers/type/product/product-tokenized-types.ts +1 -0
  226. package/src/resolvers/type/product/product-variation-assignment-types.ts +4 -2
  227. package/src/resolvers/type/quotation-types.ts +6 -3
  228. package/src/resolvers/type/user-types.ts +0 -15
  229. package/src/schema/directives.js +14 -0
  230. package/src/schema/index.js +2 -1
  231. package/src/schema/inputTypes.js +0 -15
  232. package/src/schema/mutation.js +4 -23
  233. package/src/schema/query.js +28 -10
  234. package/src/schema/types/assortment.js +9 -10
  235. package/src/schema/types/color.js +1 -1
  236. package/src/schema/types/country.js +1 -1
  237. package/src/schema/types/currency.js +1 -1
  238. package/src/schema/types/delivery.js +3 -2
  239. package/src/schema/types/dimensions.js +1 -1
  240. package/src/schema/types/discount.js +1 -1
  241. package/src/schema/types/dispatch.js +1 -0
  242. package/src/schema/types/filter.js +5 -8
  243. package/src/schema/types/geo-position.js +1 -1
  244. package/src/schema/types/language.js +1 -1
  245. package/src/schema/types/media.js +1 -1
  246. package/src/schema/types/payment.js +3 -3
  247. package/src/schema/types/price.js +2 -2
  248. package/src/schema/types/product/bundle-product.js +2 -3
  249. package/src/schema/types/product/configurable-product.js +7 -7
  250. package/src/schema/types/product/plan-product.js +4 -3
  251. package/src/schema/types/product/product.js +11 -11
  252. package/src/schema/types/product/simple-product.js +5 -4
  253. package/src/schema/types/product/tokenized-product.js +6 -3
  254. package/src/schema/types/search.js +3 -8
  255. package/src/schema/types/shop.js +2 -2
  256. package/src/schema/types/stock.js +1 -0
  257. package/src/schema/types/types.js +1 -1
  258. package/src/schema/types/user.js +1 -3
  259. package/src/schema/types/warehousing.js +3 -3
  260. package/tsconfig.json +1 -0
  261. package/lib/createBulkImportServer.d.ts +0 -2
  262. package/lib/createBulkImportServer.js +0 -81
  263. package/lib/createBulkImportServer.js.map +0 -1
  264. package/lib/createERCMetadataServer.d.ts +0 -2
  265. package/lib/createERCMetadataServer.js +0 -59
  266. package/lib/createERCMetadataServer.js.map +0 -1
  267. package/lib/schema/types/log.js +0 -16
  268. package/lib/schema/types/log.js.map +0 -1
  269. package/src/createBulkImportServer.ts +0 -95
  270. package/src/createERCMetadataServer.ts +0 -78
  271. package/src/schema/types/log.js +0 -15
package/src/api-index.ts CHANGED
@@ -1,34 +1,38 @@
1
1
  import { UnchainedServerOptions } from '@unchainedshop/types/api';
2
- import { ApolloServer } from 'apollo-server-express';
3
- import createBulkImportServer from './createBulkImportServer';
2
+ import type { ApolloServer } from '@apollo/server';
3
+ import fs from 'fs';
4
+ import path from 'path';
4
5
  import createGraphQLServer from './createGraphQLServer';
5
- import { createContextResolver, getCurrentContextResolver, setCurrentContextResolver } from './context';
6
- import createERCMetadataServer from './createERCMetadataServer';
6
+ import { createContextResolver, setCurrentContextResolver, getCurrentContextResolver } from './context';
7
7
 
8
8
  export * from './context';
9
9
  export * as acl from './acl';
10
10
  export * as errors from './errors';
11
+ export * as express from './express';
11
12
  export { hashPassword } from './hashPassword';
12
13
  export * as roles from './roles';
13
-
14
14
  export { createContextResolver, getCurrentContextResolver, setCurrentContextResolver };
15
15
 
16
- const UNCHAINED_API_VERSION = '1.2.0'; // eslint-disable-line
16
+ const loadJSON = (filename) => {
17
+ try {
18
+ const base = typeof __filename !== 'undefined' && __filename;
19
+ if (!base)
20
+ return {
21
+ version: process.env.npm_package_version,
22
+ };
23
+ const absolutePath = path.resolve(path.dirname(base), filename);
24
+ const data = JSON.parse(fs.readFileSync(absolutePath, 'utf-8'));
25
+ return data;
26
+ } catch (e) {
27
+ return null;
28
+ }
29
+ };
30
+ const packageJson = loadJSON('../package.json');
31
+
32
+ const UNCHAINED_API_VERSION = process.env.UNCHAINED_API_VERSION || packageJson?.version || '1.2.x';
17
33
 
18
- export const startAPIServer = (
19
- options: UnchainedServerOptions,
20
- ): {
21
- apolloGraphQLServer: ApolloServer;
22
- bulkImportServer: any;
23
- ercMetadataServer: any;
24
- } => {
25
- const {
26
- unchainedAPI,
27
- roles,
28
- expressApp,
29
- context: customContext,
30
- ...apolloServerOptions
31
- } = options || {};
34
+ export const startAPIServer = async (options: UnchainedServerOptions): Promise<ApolloServer> => {
35
+ const { unchainedAPI, roles, context: customContext, ...apolloServerOptions } = options || {};
32
36
 
33
37
  const contextResolver = createContextResolver(unchainedAPI, roles, UNCHAINED_API_VERSION);
34
38
 
@@ -40,13 +44,5 @@ export const startAPIServer = (
40
44
  : contextResolver,
41
45
  );
42
46
 
43
- const apolloGraphQLServer = createGraphQLServer(expressApp, apolloServerOptions);
44
- const bulkImportServer = createBulkImportServer(expressApp);
45
- const ercMetadataServer = createERCMetadataServer(expressApp);
46
-
47
- return {
48
- apolloGraphQLServer,
49
- bulkImportServer,
50
- ercMetadataServer,
51
- };
47
+ return createGraphQLServer(apolloServerOptions);
52
48
  };
package/src/context.ts CHANGED
@@ -1,6 +1,5 @@
1
1
  import { UnchainedContextResolver } from '@unchainedshop/types/api';
2
2
  import { UnchainedCore } from '@unchainedshop/types/core';
3
- import { IncomingMessage, OutgoingMessage } from 'http';
4
3
  import instantiateLoaders from './loaders';
5
4
  import { getLocaleContext } from './locale-context';
6
5
  import { getUserContext } from './user-context';
@@ -32,21 +31,3 @@ export const createContextResolver =
32
31
  version,
33
32
  };
34
33
  };
35
-
36
- export const useMiddlewareWithCurrentContext = (expressApp, path, middleware) => {
37
- expressApp.use(
38
- path,
39
- async function middlewareWithContext(
40
- req: IncomingMessage & { unchainedContext?: UnchainedCore },
41
- res: OutgoingMessage,
42
- next,
43
- ) {
44
- try {
45
- req.unchainedContext = await context({ req, res });
46
- await middleware(req, res, next);
47
- } catch (error) {
48
- next(error);
49
- }
50
- },
51
- );
52
- };
@@ -1,21 +1,11 @@
1
- import { ApolloServer, ApolloError } from 'apollo-server-express';
2
- import { processRequest } from 'graphql-upload';
1
+ import { ApolloServer } from '@apollo/server';
2
+ import { GraphQLError } from 'graphql';
3
3
  import { log, LogLevel } from '@unchainedshop/logger';
4
4
  import typeDefs from './schema';
5
5
  import resolvers from './resolvers';
6
- import { getCurrentContextResolver } from './context';
7
6
 
8
7
  const { APOLLO_ENGINE_KEY } = process.env;
9
8
 
10
- const handleUploads = (options) => async (req, res, next) => {
11
- const contentType = req.headers['content-type'];
12
- const isUpload = contentType && contentType.startsWith('multipart/form-data');
13
- if (isUpload) {
14
- req.body = await processRequest(req, res, options);
15
- }
16
- next();
17
- };
18
-
19
9
  const logGraphQLServerError = (error) => {
20
10
  try {
21
11
  const {
@@ -35,21 +25,17 @@ const logGraphQLServerError = (error) => {
35
25
  } catch (e) {} // eslint-disable-line
36
26
  };
37
27
 
38
- export default (expressApp, options) => {
28
+ export default async (options) => {
39
29
  const {
40
- corsOrigins = null, // no cookie handling
41
30
  typeDefs: additionalTypeDefs = [],
42
31
  resolvers: additionalResolvers = [],
43
32
  engine = {},
44
33
  ...apolloServerOptions
45
34
  } = options || {};
46
35
 
47
- const context = getCurrentContextResolver();
48
36
  const server = new ApolloServer({
49
37
  typeDefs: [...typeDefs, ...additionalTypeDefs],
50
38
  resolvers: [resolvers, ...additionalResolvers],
51
- context,
52
- uploads: false,
53
39
  formatError: (error) => {
54
40
  logGraphQLServerError(error);
55
41
  const {
@@ -57,18 +43,20 @@ export default (expressApp, options) => {
57
43
  path,
58
44
  extensions: { exception, code, ...extensions }, // eslint-disable-line
59
45
  } = error;
60
- const apolloError = new ApolloError(message, code as string, {
61
- code,
62
- ...extensions,
46
+ const apolloError = new GraphQLError(message, {
47
+ extensions: {
48
+ code,
49
+ ...extensions,
50
+ },
63
51
  });
64
52
  // eslint-disable-next-line
65
53
  // @ts-ignore
66
54
  apolloError.path = path;
67
55
  return apolloError;
68
56
  },
69
- engine: APOLLO_ENGINE_KEY
57
+ apollo: APOLLO_ENGINE_KEY
70
58
  ? {
71
- apiKey: APOLLO_ENGINE_KEY,
59
+ key: APOLLO_ENGINE_KEY,
72
60
  privateVariables: ['email', 'plainPassword', 'oldPlainPassword', 'newPlainPassword'],
73
61
  ...engine,
74
62
  }
@@ -76,40 +64,7 @@ export default (expressApp, options) => {
76
64
  ...apolloServerOptions,
77
65
  });
78
66
 
79
- const originFn =
80
- corsOrigins && Array.isArray(corsOrigins)
81
- ? (origin, callback) => {
82
- if (corsOrigins.length === 0 || !origin) {
83
- callback(null, true);
84
- return;
85
- }
86
- if (corsOrigins.indexOf(origin) !== -1) {
87
- callback(null, true);
88
- } else {
89
- callback(new Error('Not allowed by CORS'));
90
- }
91
- }
92
- : corsOrigins;
93
-
94
- // server.start().then(() => {
95
- //
96
- // });
97
-
98
- const middleware = server.getMiddleware({
99
- path: '/graphql',
100
- cors: !originFn
101
- ? undefined
102
- : {
103
- origin: originFn,
104
- credentials: true,
105
- },
106
- bodyParserConfig: {
107
- limit: '5mb',
108
- },
109
- });
110
-
111
- expressApp.use(handleUploads({ maxFileSize: 10000000, maxFiles: 10 }));
112
- expressApp.use(middleware);
67
+ await server.start();
113
68
 
114
69
  return server;
115
70
  };
package/src/errors.ts CHANGED
@@ -1,9 +1,14 @@
1
- import { ApolloError } from 'apollo-server-express';
1
+ import { GraphQLError } from 'graphql';
2
2
 
3
3
  export const createError = (code: string, message: string): any =>
4
- class extends ApolloError {
4
+ class extends GraphQLError {
5
5
  constructor({ message: explicitMessage, ...data }) {
6
- super(explicitMessage || message, code, data);
6
+ super(explicitMessage || message, {
7
+ extensions: {
8
+ code,
9
+ ...data,
10
+ },
11
+ });
7
12
  }
8
13
  };
9
14
 
@@ -0,0 +1,40 @@
1
+ import cors from 'cors';
2
+ import { expressMiddleware } from '@apollo/server/express4';
3
+ import graphqlUploadExpress from 'graphql-upload/graphqlUploadExpress.mjs';
4
+ import e from 'express';
5
+
6
+ export default function createApolloMiddleware(
7
+ contextResolver,
8
+ { apolloGraphQLServer, corsOrigins = undefined },
9
+ ) {
10
+ const originFn =
11
+ corsOrigins && Array.isArray(corsOrigins)
12
+ ? (origin, callback) => {
13
+ if (corsOrigins.length === 0 || !origin) {
14
+ callback(null, true);
15
+ return;
16
+ }
17
+ if (corsOrigins.indexOf(origin) !== -1) {
18
+ callback(null, true);
19
+ } else {
20
+ callback(new Error('Not allowed by CORS'));
21
+ }
22
+ }
23
+ : corsOrigins;
24
+
25
+ return [
26
+ cors(
27
+ !originFn
28
+ ? undefined
29
+ : {
30
+ origin: originFn,
31
+ credentials: true,
32
+ },
33
+ ),
34
+ e.json(),
35
+ graphqlUploadExpress({ maxFileSize: 10000000, maxFiles: 10 }),
36
+ expressMiddleware(apolloGraphQLServer, {
37
+ context: contextResolver,
38
+ }),
39
+ ];
40
+ }
@@ -0,0 +1,90 @@
1
+ import { createLogger } from '@unchainedshop/logger';
2
+ import { UnchainedContextResolver } from '@unchainedshop/types/api';
3
+ import fs from 'fs';
4
+ import { checkAction } from '../acl';
5
+ import { actions } from '../roles';
6
+
7
+ const logger = createLogger('unchained:bulk-import');
8
+
9
+ const { BULK_IMPORT_PAYLOAD_CACHE_DIRECTORY } = process.env;
10
+
11
+ const errorHandler = (res) => (e) => {
12
+ logger.error(e.message);
13
+ res.writeHead(503);
14
+ res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
15
+ };
16
+
17
+ const methodWrongHandler = (res) => () => {
18
+ logger.error('Method not supported, return 404');
19
+ res.writeHead(404);
20
+ res.end();
21
+ };
22
+
23
+ const createWriteStreamToFilesystem = (cacheDirectory) => {
24
+ const date = new Date().toISOString();
25
+ const payloadFilePath = `${cacheDirectory}/${date}.json`;
26
+ const stream = fs.createWriteStream(payloadFilePath, { flags: 'a' });
27
+ return stream;
28
+ };
29
+
30
+ const createWriteStreamToMongoDB = (BulkImportPayloads) => {
31
+ const date = new Date().toISOString();
32
+ const stream = BulkImportPayloads.openUploadStreamWithId(date, `${date}.json`, {
33
+ contentType: 'application/json',
34
+ });
35
+ return stream;
36
+ };
37
+
38
+ export default function bulkImportMiddleware(contextResolver: UnchainedContextResolver) {
39
+ return async (req, res) => {
40
+ try {
41
+ if (req.method !== 'POST') {
42
+ methodWrongHandler(res)();
43
+ return;
44
+ }
45
+
46
+ const context = await contextResolver({ req, res });
47
+ await checkAction(context, (actions as any).bulkImport);
48
+
49
+ const input: any = {
50
+ createShouldUpsertIfIDExists: !!req.query?.createShouldUpsertIfIDExists,
51
+ skipCacheInvalidation: !!req.query?.skipCacheInvalidation,
52
+ fsPayloadCacheDirectory: BULK_IMPORT_PAYLOAD_CACHE_DIRECTORY,
53
+ remoteAddress: context.remoteAddress,
54
+ };
55
+
56
+ const stream = input.fsPayloadCacheDirectory
57
+ ? createWriteStreamToFilesystem(input.fsPayloadCacheDirectory)
58
+ : createWriteStreamToMongoDB(context.bulkImporter.BulkImportPayloads);
59
+
60
+ req
61
+ .pipe(stream)
62
+ .on('error', errorHandler(res))
63
+ .on('finish', async (file) => {
64
+ try {
65
+ if (input.fsPayloadCacheDirectory) {
66
+ input.payloadFilePath = stream.path;
67
+ } else {
68
+ input.payloadId = file._id;
69
+ input.payloadSize = file.length;
70
+ }
71
+ const work = await context.modules.worker.addWork(
72
+ {
73
+ type: 'BULK_IMPORT',
74
+ input: Object.fromEntries(Object.entries(input).filter(([, value]) => Boolean(value))),
75
+ retries: 0,
76
+ priority: 10,
77
+ },
78
+ context.userId,
79
+ );
80
+ res.writeHead(200);
81
+ res.end(JSON.stringify(work));
82
+ } catch (e) {
83
+ errorHandler(res)(e);
84
+ }
85
+ });
86
+ } catch (e) {
87
+ errorHandler(res)(e);
88
+ }
89
+ };
90
+ }
@@ -0,0 +1,72 @@
1
+ import { createLogger } from '@unchainedshop/logger';
2
+ import { UnchainedContextResolver } from '@unchainedshop/types/api';
3
+ import { systemLocale } from '@unchainedshop/utils';
4
+ import { IncomingMessage } from 'http';
5
+ import localePkg from 'locale';
6
+ import path from 'path';
7
+
8
+ const { Locale } = localePkg;
9
+
10
+ const logger = createLogger('unchained:erc-metadata');
11
+
12
+ const errorHandler = (res) => (e) => {
13
+ logger.error(e.message);
14
+ res.writeHead(503);
15
+ res.end(JSON.stringify({ name: e.name, code: e.code, message: e.message }));
16
+ };
17
+
18
+ const methodWrongHandler = (res) => () => {
19
+ logger.error('Method not supported, return 404');
20
+ res.writeHead(404);
21
+ res.end();
22
+ };
23
+
24
+ export default function ercMetadataMiddleware(contextResolver: UnchainedContextResolver) {
25
+ return async (req: IncomingMessage, res) => {
26
+ try {
27
+ if (req.method !== 'GET') {
28
+ methodWrongHandler(res)();
29
+ return;
30
+ }
31
+
32
+ const context = await contextResolver({ req, res });
33
+ const url = new URL(req.url, process.env.ROOT_URL);
34
+ const parsedPath = path.parse(url.pathname);
35
+
36
+ if (parsedPath.ext !== '.json') throw new Error('Invalid ERC Metadata URI');
37
+
38
+ const [, productId, localeOrTokenFilename, tokenFileName] = url.pathname.split('/');
39
+
40
+ const locale = tokenFileName ? localeOrTokenFilename : systemLocale.language;
41
+ const chainTokenId = parsedPath.name;
42
+
43
+ const product = await context.modules.products.findProduct({
44
+ productId,
45
+ });
46
+
47
+ const [token] = await context.modules.warehousing.findTokens({
48
+ chainTokenId,
49
+ contractAddress: product?.tokenization?.contractAddress,
50
+ });
51
+
52
+ const ercMetadata = await context.modules.warehousing.tokenMetadata(
53
+ chainTokenId,
54
+ {
55
+ token,
56
+ product,
57
+ referenceDate: new Date(),
58
+ },
59
+ { ...context, localeContext: new Locale(locale) },
60
+ );
61
+
62
+ const body = JSON.stringify(ercMetadata);
63
+ res.writeHead(200, {
64
+ 'Content-Length': Buffer.byteLength(body),
65
+ 'Content-Type': 'text/plain',
66
+ });
67
+ res.end(body);
68
+ } catch (e) {
69
+ errorHandler(res)(e);
70
+ }
71
+ };
72
+ }
@@ -0,0 +1,83 @@
1
+ /// <reference lib="dom" />
2
+ import { createLogger } from '@unchainedshop/logger';
3
+ import { Context, UnchainedContextResolver } from '@unchainedshop/types/api';
4
+ import { IncomingMessage } from 'http';
5
+ import cookie from 'cookie';
6
+
7
+ const { ROOT_URL, NODE_ENV, UNCHAINED_CLOUD_ENDPOINT } = process.env;
8
+
9
+ const logger = createLogger('unchained:unchained-cloud-sso');
10
+
11
+ const loginWithSingleSignOn = async (remoteToken, context: Context) => {
12
+ const domain = process.env.UNCHAINED_COOKIE_DOMAIN || new URL(ROOT_URL).hostname || 'localhost';
13
+ const result = await fetch(UNCHAINED_CLOUD_ENDPOINT, {
14
+ method: 'POST',
15
+ headers: {
16
+ 'content-type': 'application/json',
17
+ },
18
+ body: JSON.stringify({
19
+ operationName: 'consume',
20
+ variables: {
21
+ token: remoteToken,
22
+ },
23
+ query:
24
+ 'mutation consume($token: ID!) { controlConsumeSingleSignOnToken(token: $token) { domain } }',
25
+ }),
26
+ });
27
+ const json: any = await result.json();
28
+ if (json?.errors?.length > 0) {
29
+ throw new Error(json.errors[0].message);
30
+ }
31
+
32
+ if (domain === 'localhost' || domain === json?.data?.controlConsumeSingleSignOnToken?.domain) {
33
+ // create sso user if not exist and login
34
+ const ssoUserId =
35
+ (await context.modules.users.findUser({ username: 'sso' }))?._id ||
36
+ (await context.modules.accounts.createUser(
37
+ {
38
+ username: 'sso',
39
+ roles: ['admin'],
40
+ email: 'sso@unchained.local',
41
+ password: null,
42
+ guest: false,
43
+ },
44
+ { skipMessaging: true },
45
+ ));
46
+ const { tokenExpires, token } = await context.modules.accounts.createLoginToken(ssoUserId, context);
47
+ const expires = new Date(tokenExpires || new Date().getTime() + 100000);
48
+ const authCookie = cookie.serialize(process.env.UNCHAINED_COOKIE_NAME, token, {
49
+ domain,
50
+ httpOnly: true,
51
+ expires,
52
+ path: '/',
53
+ sameSite: 'strict',
54
+ secure: NODE_ENV === 'production',
55
+ });
56
+
57
+ return authCookie;
58
+ }
59
+ throw new Error('Invalid token/domain pair');
60
+ };
61
+
62
+ export default function singleSignOnMiddleware(contextResolver: UnchainedContextResolver) {
63
+ return async (req: IncomingMessage & { query?: any }, res, next) => {
64
+ try {
65
+ if (req.query?.token) {
66
+ const context = await contextResolver({ req, res });
67
+ const authCookie = await loginWithSingleSignOn(req.query.token, context);
68
+
69
+ if (authCookie) {
70
+ res.writeHead(303, {
71
+ 'Set-Cookie': authCookie,
72
+ Location: '/',
73
+ });
74
+ res.end();
75
+ return;
76
+ }
77
+ }
78
+ } catch (e) {
79
+ logger.error(e.message);
80
+ }
81
+ next();
82
+ };
83
+ }
@@ -0,0 +1,48 @@
1
+ import { UnchainedCore } from '@unchainedshop/types/core';
2
+ import { IncomingMessage, OutgoingMessage } from 'http';
3
+ import { ApolloServer } from '@apollo/server';
4
+ import type e from 'express';
5
+ import { getCurrentContextResolver } from '../context';
6
+ import createBulkImportMiddleware from './createBulkImportMiddleware';
7
+ import createERCMetadataMiddleware from './createERCMetadataMiddleware';
8
+ import createApolloMiddleware from './createApolloMiddleware';
9
+ import createSingleSignOnMiddleware from './createSingleSignOnMiddleware';
10
+
11
+ const {
12
+ BULK_IMPORT_API_PATH = '/bulk-import',
13
+ ERC_METADATA_API_PATH = '/erc-metadata',
14
+ GRAPHQL_API_PATH = '/graphql',
15
+ } = process.env;
16
+
17
+ export const useMiddlewareWithCurrentContext = (expressApp, path, ...middleware) => {
18
+ const context = getCurrentContextResolver();
19
+ const addContext = async function middlewareWithContext(
20
+ req: IncomingMessage & { unchainedContext: UnchainedCore },
21
+ res: OutgoingMessage,
22
+ next,
23
+ ) {
24
+ try {
25
+ req.unchainedContext = await context({ req, res });
26
+ next();
27
+ } catch (error) {
28
+ next(error);
29
+ }
30
+ };
31
+
32
+ expressApp.use(path, addContext, ...middleware);
33
+ };
34
+
35
+ export const connect = (
36
+ expressApp: e.Express,
37
+ { apolloGraphQLServer }: { apolloGraphQLServer: ApolloServer },
38
+ ) => {
39
+ const contextResolver = getCurrentContextResolver();
40
+
41
+ expressApp.use(GRAPHQL_API_PATH, createApolloMiddleware(contextResolver, { apolloGraphQLServer }));
42
+ expressApp.use(ERC_METADATA_API_PATH, createERCMetadataMiddleware(contextResolver));
43
+ expressApp.use(BULK_IMPORT_API_PATH, createBulkImportMiddleware(contextResolver));
44
+ expressApp.use(
45
+ ['/', '/.well-known/unchained/cloud-sso'],
46
+ createSingleSignOnMiddleware(contextResolver),
47
+ );
48
+ };
@@ -3,10 +3,11 @@ import DataLoader from 'dataloader';
3
3
  import { IncomingMessage, OutgoingMessage } from 'http';
4
4
  import { systemLocale } from '@unchainedshop/utils';
5
5
  import localePkg from 'locale';
6
- import { AssortmentText } from '@unchainedshop/types/assortments';
7
- import { FilterText } from '@unchainedshop/types/filters';
8
- import { ProductText } from '@unchainedshop/types/products';
6
+ import { Assortment, AssortmentText } from '@unchainedshop/types/assortments';
7
+ import { Filter, FilterText } from '@unchainedshop/types/filters';
8
+ import { Product, ProductText } from '@unchainedshop/types/products';
9
9
  import { UnchainedCore } from '@unchainedshop/types/core';
10
+ import { ProductStatus } from '@unchainedshop/core-products';
10
11
 
11
12
  const { Locale } = localePkg;
12
13
 
@@ -16,6 +17,28 @@ export default async (
16
17
  unchainedAPI: UnchainedCore,
17
18
  ): Promise<UnchainedLoaders['loaders']> => {
18
19
  return {
20
+ assortmentLoader: new DataLoader<{ assortmentId: string; includeInactive: boolean }, Assortment>(
21
+ async (queries) => {
22
+ const assortmentIds = [...new Set(queries.map((q) => q.assortmentId).filter(Boolean))];
23
+
24
+ const assortments = await unchainedAPI.modules.assortments.findAssortments({
25
+ assortmentIds,
26
+ includeInactive: true,
27
+ includeLeaves: true,
28
+ });
29
+
30
+ return queries.map(({ assortmentId, includeInactive }) => {
31
+ return assortments.find((assortment) => {
32
+ if (assortment._id !== assortmentId) return false;
33
+ if (!includeInactive) {
34
+ return assortment.isActive === true;
35
+ }
36
+ return true;
37
+ });
38
+ });
39
+ },
40
+ ),
41
+
19
42
  assortmentTextLoader: new DataLoader<{ assortmentId: string; locale: string }, AssortmentText>(
20
43
  async (queries) => {
21
44
  const assortmentIds = [...new Set(queries.map((q) => q.assortmentId).filter(Boolean))];
@@ -46,6 +69,22 @@ export default async (
46
69
  },
47
70
  ),
48
71
 
72
+ filterLoader: new DataLoader<{ filterId: string }, Filter>(async (queries) => {
73
+ const filterIds = [...new Set(queries.map((q) => q.filterId).filter(Boolean))];
74
+
75
+ const filters = await unchainedAPI.modules.filters.findFilters({
76
+ filterIds,
77
+ includeInactive: true,
78
+ });
79
+
80
+ return queries.map(({ filterId }) => {
81
+ return filters.find((product) => {
82
+ if (product._id !== filterId) return false;
83
+ return true;
84
+ });
85
+ });
86
+ }),
87
+
49
88
  filterTextLoader: new DataLoader<
50
89
  { filterId: string; filterOptionValue?: string; locale: string },
51
90
  FilterText
@@ -79,6 +118,27 @@ export default async (
79
118
  });
80
119
  }),
81
120
 
121
+ productLoader: new DataLoader<{ productId: string; includeDrafts: boolean }, Product>(
122
+ async (queries) => {
123
+ const productIds = [...new Set(queries.map((q) => q.productId).filter(Boolean))];
124
+
125
+ const products = await unchainedAPI.modules.products.findProducts({
126
+ productIds,
127
+ includeDrafts: true,
128
+ });
129
+
130
+ return queries.map(({ productId, includeDrafts }) => {
131
+ return products.find((product) => {
132
+ if (product._id !== productId) return false;
133
+ if (!includeDrafts) {
134
+ return product.status === ProductStatus.ACTIVE;
135
+ }
136
+ return true;
137
+ });
138
+ });
139
+ },
140
+ ),
141
+
82
142
  productTextLoader: new DataLoader<{ productId: string; locale: string }, ProductText>(
83
143
  async (queries) => {
84
144
  const productIds = [...new Set(queries.map((q) => q.productId).filter(Boolean))];
@@ -1,4 +1,4 @@
1
- import { GraphQLUpload } from 'graphql-upload';
1
+ import GraphQLUpload from 'graphql-upload/GraphQLUpload.mjs';
2
2
  import { JSONResolver, TimestampResolver, DateTimeResolver, DateResolver } from 'graphql-scalars';
3
3
  import Query from './queries';
4
4
  import Mutation from './mutations';