@unchainedshop/api 2.12.2 → 2.13.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 (71) hide show
  1. package/lib/express/createBulkImportMiddleware.d.ts.map +1 -1
  2. package/lib/express/createBulkImportMiddleware.js +1 -0
  3. package/lib/express/createBulkImportMiddleware.js.map +1 -1
  4. package/lib/locale-context.d.ts +1 -0
  5. package/lib/locale-context.d.ts.map +1 -1
  6. package/lib/locale-context.js +23 -22
  7. package/lib/locale-context.js.map +1 -1
  8. package/lib/resolvers/mutations/accounts/logout.js +1 -1
  9. package/lib/resolvers/mutations/accounts/logout.js.map +1 -1
  10. package/lib/resolvers/mutations/accounts/logoutAllSessions.js +1 -1
  11. package/lib/resolvers/mutations/accounts/logoutAllSessions.js.map +1 -1
  12. package/lib/resolvers/mutations/countries/updateCountry.d.ts +3 -1
  13. package/lib/resolvers/mutations/countries/updateCountry.d.ts.map +1 -1
  14. package/lib/resolvers/mutations/countries/updateCountry.js +5 -1
  15. package/lib/resolvers/mutations/countries/updateCountry.js.map +1 -1
  16. package/lib/resolvers/mutations/enrollments/createEnrollment.d.ts.map +1 -1
  17. package/lib/resolvers/mutations/enrollments/createEnrollment.js +2 -1
  18. package/lib/resolvers/mutations/enrollments/createEnrollment.js.map +1 -1
  19. package/lib/resolvers/mutations/orders/confirmOrder.d.ts +1 -0
  20. package/lib/resolvers/mutations/orders/confirmOrder.d.ts.map +1 -1
  21. package/lib/resolvers/mutations/orders/confirmOrder.js.map +1 -1
  22. package/lib/resolvers/mutations/orders/rejectOrder.d.ts +1 -0
  23. package/lib/resolvers/mutations/orders/rejectOrder.d.ts.map +1 -1
  24. package/lib/resolvers/mutations/orders/rejectOrder.js.map +1 -1
  25. package/lib/resolvers/type/country-types.js +2 -2
  26. package/lib/resolvers/type/country-types.js.map +1 -1
  27. package/lib/resolvers/type/delivery-provider-types.d.ts.map +1 -1
  28. package/lib/resolvers/type/delivery-provider-types.js +2 -5
  29. package/lib/resolvers/type/delivery-provider-types.js.map +1 -1
  30. package/lib/resolvers/type/index.d.ts +1 -1
  31. package/lib/resolvers/type/index.d.ts.map +1 -1
  32. package/lib/resolvers/type/login-method-response-types.d.ts +1 -1
  33. package/lib/resolvers/type/login-method-response-types.d.ts.map +1 -1
  34. package/lib/resolvers/type/login-method-response-types.js +2 -2
  35. package/lib/resolvers/type/login-method-response-types.js.map +1 -1
  36. package/lib/resolvers/type/payment/payment-provider-types.d.ts.map +1 -1
  37. package/lib/resolvers/type/payment/payment-provider-types.js +2 -5
  38. package/lib/resolvers/type/payment/payment-provider-types.js.map +1 -1
  39. package/lib/resolvers/type/product/product-configurable-types.d.ts.map +1 -1
  40. package/lib/resolvers/type/product/product-configurable-types.js +2 -8
  41. package/lib/resolvers/type/product/product-configurable-types.js.map +1 -1
  42. package/lib/resolvers/type/product/product-plan-types.d.ts.map +1 -1
  43. package/lib/resolvers/type/product/product-plan-types.js +4 -13
  44. package/lib/resolvers/type/product/product-plan-types.js.map +1 -1
  45. package/lib/resolvers/type/product/product-simple-types.d.ts.map +1 -1
  46. package/lib/resolvers/type/product/product-tokenized-types.d.ts.map +1 -1
  47. package/lib/schema/inputTypes.d.ts.map +1 -1
  48. package/lib/schema/inputTypes.js +2 -1
  49. package/lib/schema/inputTypes.js.map +1 -1
  50. package/lib/schema/mutation.js +2 -2
  51. package/lib/user-context.d.ts.map +1 -1
  52. package/lib/user-context.js +20 -16
  53. package/lib/user-context.js.map +1 -1
  54. package/package.json +13 -13
  55. package/src/express/createBulkImportMiddleware.ts +1 -0
  56. package/src/locale-context.ts +53 -49
  57. package/src/resolvers/mutations/accounts/logout.ts +1 -1
  58. package/src/resolvers/mutations/accounts/logoutAllSessions.ts +1 -1
  59. package/src/resolvers/mutations/countries/updateCountry.ts +7 -2
  60. package/src/resolvers/mutations/enrollments/createEnrollment.ts +2 -1
  61. package/src/resolvers/mutations/orders/confirmOrder.ts +1 -0
  62. package/src/resolvers/mutations/orders/rejectOrder.ts +2 -0
  63. package/src/resolvers/type/country-types.ts +2 -2
  64. package/src/resolvers/type/delivery-provider-types.ts +2 -10
  65. package/src/resolvers/type/login-method-response-types.ts +2 -2
  66. package/src/resolvers/type/payment/payment-provider-types.ts +2 -9
  67. package/src/resolvers/type/product/product-configurable-types.ts +3 -16
  68. package/src/resolvers/type/product/product-plan-types.ts +5 -25
  69. package/src/schema/inputTypes.ts +2 -1
  70. package/src/schema/mutation.ts +2 -2
  71. package/src/user-context.ts +24 -17
@@ -304,12 +304,12 @@ export default [
304
304
  """
305
305
  Manually confirm an order which is in progress
306
306
  """
307
- confirmOrder(orderId: ID!, paymentContext: JSON, deliveryContext: JSON): Order!
307
+ confirmOrder(orderId: ID!, paymentContext: JSON, deliveryContext: JSON, comment: String): Order!
308
308
 
309
309
  """
310
310
  Manually reject an order which is in progress
311
311
  """
312
- rejectOrder(orderId: ID!, paymentContext: JSON, deliveryContext: JSON): Order!
312
+ rejectOrder(orderId: ID!, paymentContext: JSON, deliveryContext: JSON, comment: String): Order!
313
313
 
314
314
  """
315
315
  Manually mark an unpaid/partially paid order as fully paid
@@ -1 +1 @@
1
- {"version":3,"file":"user-context.d.ts","sourceRoot":"","sources":["../src/user-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAc7D,eAAO,MAAM,cAAc,QACpB,eAAe,GAAG;IAAE,OAAO,CAAC,EAAE,GAAG,CAAA;CAAE,OACnC,eAAe,gBACN,aAAa,KAC1B,OAAO,CAAC,oBAAoB,CAkE9B,CAAC"}
1
+ {"version":3,"file":"user-context.d.ts","sourceRoot":"","sources":["../src/user-context.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,MAAM,CAAC;AACxD,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAiC7D,eAAO,MAAM,cAAc,QACpB,eAAe,GAAG;IAAE,OAAO,CAAC,EAAE,GAAG,CAAA;CAAE,OACnC,eAAe,gBACN,aAAa,KAC1B,OAAO,CAAC,oBAAoB,CAsD9B,CAAC"}
@@ -3,26 +3,27 @@ function isString(input) {
3
3
  return typeof input === 'string' && Object.prototype.toString.call(input) === '[object String]';
4
4
  }
5
5
  const { UNCHAINED_COOKIE_NAME = 'unchained_token', UNCHAINED_COOKIE_PATH = '/', UNCHAINED_COOKIE_DOMAIN, NODE_ENV, } = process.env;
6
- export const getUserContext = async (req, res, unchainedAPI) => {
7
- // there is a possible current user connected!
6
+ function setLoginToken(res, token, expires) {
8
7
  const cookieName = UNCHAINED_COOKIE_NAME;
9
8
  const domain = UNCHAINED_COOKIE_DOMAIN;
10
9
  const path = UNCHAINED_COOKIE_PATH;
10
+ if (!domain)
11
+ return;
12
+ const authCookie = cookie.serialize(cookieName, token || null, {
13
+ domain,
14
+ httpOnly: true,
15
+ path,
16
+ expires: token && expires ? expires : undefined,
17
+ maxAge: token ? undefined : -1,
18
+ sameSite: 'lax',
19
+ secure: NODE_ENV === 'production',
20
+ });
21
+ res.setHeader('Set-Cookie', authCookie);
22
+ }
23
+ export const getUserContext = async (req, res, unchainedAPI) => {
24
+ // there is a possible current user connected!
25
+ const cookieName = UNCHAINED_COOKIE_NAME;
11
26
  let loginToken = req.cookies?.[cookieName];
12
- function setLoginToken(token, expires) {
13
- if (!domain)
14
- return;
15
- const authCookie = cookie.serialize(cookieName, token || null, {
16
- domain,
17
- httpOnly: true,
18
- path,
19
- expires: token ? expires : undefined,
20
- maxAge: token ? undefined : -1,
21
- sameSite: 'lax',
22
- secure: NODE_ENV === 'production',
23
- });
24
- res.setHeader('Set-Cookie', authCookie);
25
- }
26
27
  if (req.headers.authorization) {
27
28
  const [type, token] = req.headers.authorization.split(' ');
28
29
  if (type === 'Bearer') {
@@ -57,6 +58,9 @@ export const getUserContext = async (req, res, unchainedAPI) => {
57
58
  };
58
59
  }
59
60
  }
61
+ // If there is no user with this token or the token is expires/invalid,
62
+ // we should remove that cookie from the client
63
+ setLoginToken(res, null);
60
64
  return { loginToken: loginToken, setLoginToken };
61
65
  }
62
66
  return { setLoginToken };
@@ -1 +1 @@
1
- {"version":3,"file":"user-context.js","sourceRoot":"","sources":["../src/user-context.ts"],"names":[],"mappings":"AAGA,OAAO,MAAM,MAAM,QAAQ,CAAC;AAE5B,SAAS,QAAQ,CAAC,KAAK;IACrB,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,iBAAiB,CAAC;AAClG,CAAC;AAED,MAAM,EACJ,qBAAqB,GAAG,iBAAiB,EACzC,qBAAqB,GAAG,GAAG,EAC3B,uBAAuB,EACvB,QAAQ,GACT,GAAG,OAAO,CAAC,GAAG,CAAC;AAEhB,MAAM,CAAC,MAAM,cAAc,GAAG,KAAK,EACjC,GAAwC,EACxC,GAAoB,EACpB,YAA2B,EACI,EAAE;IACjC,8CAA8C;IAC9C,MAAM,UAAU,GAAG,qBAAqB,CAAC;IACzC,MAAM,MAAM,GAAG,uBAAuB,CAAC;IACvC,MAAM,IAAI,GAAG,qBAAqB,CAAC;IAEnC,IAAI,UAAU,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,CAAC;IAE3C,SAAS,aAAa,CAAC,KAAa,EAAE,OAAa;QACjD,IAAI,CAAC,MAAM;YAAE,OAAO;QACpB,MAAM,UAAU,GAAG,MAAM,CAAC,SAAS,CAAC,UAAU,EAAE,KAAK,IAAI,IAAI,EAAE;YAC7D,MAAM;YACN,QAAQ,EAAE,IAAI;YACd,IAAI;YACJ,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;YACpC,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;YAC9B,QAAQ,EAAE,KAAK;YACf,MAAM,EAAE,QAAQ,KAAK,YAAY;SAClC,CAAC,CAAC;QACH,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,UAAU,CAAC,CAAC;IAC1C,CAAC;IAED,IAAI,GAAG,CAAC,OAAO,CAAC,aAAa,EAAE,CAAC;QAC9B,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,CAAC,aAAa,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC3D,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;YACtB,UAAU,GAAG,KAAK,CAAC;QACrB,CAAC;IACH,CAAC;IACD,IAAI,UAAU,EAAE,CAAC;QACf,8CAA8C;QAC9C,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC;YAAE,MAAM,IAAI,KAAK,CAAC,8BAA8B,CAAC,CAAC;QAE3E,0EAA0E;QAC1E,MAAM,WAAW,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAAC,UAAoB,CAAC,CAAC;QAE7F,MAAM,WAAW,GAAG,MAAM,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,eAAe,CAAC;YACnE,WAAW;SACZ,CAAC,CAAC;QAEH,0BAA0B;QAC1B,IAAI,WAAW,EAAE,CAAC;YAChB,sEAAsE;YACtE,4DAA4D;YAC5D,MAAM,gBAAgB,GAAG,WAAW,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,IAAI,CACnE,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,WAAW,KAAK,WAAW,CACrD,CAAC,CAAC,sBAAsB;YAEzB,+BAA+B;YAC/B,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,GAAG,IAAI,IAAI,EAAE,CAAC;YAE/D,+DAA+D;YAC/D,uCAAuC;YACvC,IAAI,CAAC,SAAS,EAAE,CAAC;gBACf,6DAA6D;gBAC7D,OAAO;oBACL,IAAI,EAAE,WAAW;oBACjB,MAAM,EAAE,WAAW,CAAC,GAAG;oBACvB,UAAU,EAAE,UAAoB;oBAChC,aAAa;iBACd,CAAC;YACJ,CAAC;QACH,CAAC;QACD,OAAO,EAAE,UAAU,EAAE,UAAoB,EAAE,aAAa,EAAE,CAAC;IAC7D,CAAC;IAED,OAAO,EAAE,aAAa,EAAE,CAAC;AAC3B,CAAC,CAAC"}
1
+ {"version":3,"file":"user-context.js","sourceRoot":"","sources":["../src/user-context.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@unchainedshop/api",
3
- "version": "2.12.2",
3
+ "version": "2.13.1",
4
4
  "main": "lib/api-index.js",
5
5
  "exports": {
6
6
  ".": "./lib/api-index.js",
@@ -40,35 +40,35 @@
40
40
  },
41
41
  "homepage": "https://github.com/unchainedshop/unchained#readme",
42
42
  "peerDependencies": {
43
- "@apollo/server": "^4.10.4",
43
+ "@apollo/server": "^4.10.5",
44
44
  "cookie": "~0.6"
45
45
  },
46
46
  "optionalDependencies": {
47
47
  "express": "~4"
48
48
  },
49
49
  "dependencies": {
50
- "@metamask/eth-sig-util": "^7.0.2",
51
- "@unchainedshop/core": "^2.12.2",
52
- "@unchainedshop/events": "^2.12.2",
53
- "@unchainedshop/logger": "^2.12.2",
54
- "@unchainedshop/roles": "^2.12.2",
55
- "@unchainedshop/utils": "^2.12.2",
50
+ "@metamask/eth-sig-util": "^7.0.3",
51
+ "@unchainedshop/core": "^2.13.0",
52
+ "@unchainedshop/events": "^2.13.0",
53
+ "@unchainedshop/logger": "^2.13.0",
54
+ "@unchainedshop/roles": "^2.13.0",
55
+ "@unchainedshop/utils": "^2.13.0",
56
56
  "accounting": "0.4.1",
57
57
  "dataloader": "^2.2.2",
58
58
  "graphql-scalars": "^1.23.0",
59
59
  "graphql-upload": "^16.0.2",
60
60
  "locale": "0.1.0",
61
61
  "lodash.isnumber": "3.0.3",
62
- "lru-cache": "^11.0.0"
62
+ "memoizee": "^0.4.17"
63
63
  },
64
64
  "devDependencies": {
65
65
  "@types/graphql-upload": "^16.0.7",
66
66
  "@types/locale": "^0.1.4",
67
- "@types/node": "^20.14.10",
68
- "@unchainedshop/types": "^2.12.2",
67
+ "@types/node": "^20.14.12",
68
+ "@unchainedshop/types": "^2.13.0",
69
69
  "express": "^4.19.2",
70
70
  "jest": "^29.7.0",
71
- "ts-jest": "^29.2.2",
72
- "typescript": "^5.5.3"
71
+ "ts-jest": "^29.2.3",
72
+ "typescript": "^5.5.4"
73
73
  }
74
74
  }
@@ -30,6 +30,7 @@ export default async function bulkImportMiddleware(req, res) {
30
30
 
31
31
  const input: any = {
32
32
  createShouldUpsertIfIDExists: !!req.query?.createShouldUpsertIfIDExists,
33
+ updateShouldUpsertIfIDNotExists: !!req.query?.updateShouldUpsertIfIDNotExists,
33
34
  skipCacheInvalidation: !!req.query?.skipCacheInvalidation,
34
35
  remoteAddress: context.remoteAddress,
35
36
  };
@@ -6,73 +6,77 @@ import { log, LogLevel } from '@unchainedshop/logger';
6
6
  import {
7
7
  resolveBestCountry,
8
8
  resolveBestSupported,
9
+ resolveBestCurrency,
9
10
  resolveUserRemoteAddress,
10
11
  systemLocale,
11
12
  } from '@unchainedshop/utils';
12
13
  import { UnchainedCore } from '@unchainedshop/types/core.js';
13
- import * as lruCache from 'lru-cache';
14
+ import memoizee from 'memoizee';
14
15
 
15
16
  const { Locales } = localePkg;
16
17
 
17
18
  const { NODE_ENV } = process.env;
18
19
 
19
- const ttl = NODE_ENV === 'production' ? 1000 * 60 : 0; // minute or second
20
+ export const resolveDefaultContext = memoizee(
21
+ async ({ acceptLang, acceptCountry }, unchainedAPI) => {
22
+ const languages = await unchainedAPI.modules.languages.findLanguages(
23
+ { includeInactive: false },
24
+ { projection: { isoCode: 1, isActive: 1 } },
25
+ );
20
26
 
21
- const localeContextCache = new lruCache.LRUCache({
22
- max: 500,
23
- ttl,
24
- });
27
+ const countries = await unchainedAPI.modules.countries.findCountries(
28
+ { includeInactive: false },
29
+ { projection: { isoCode: 1, isActive: 1 } },
30
+ );
25
31
 
26
- export const getLocaleContext = async (
27
- req: IncomingMessage,
28
- res: OutgoingMessage,
29
- unchainedAPI: UnchainedCore,
30
- ): Promise<UnchainedLocaleContext> => {
31
- const cacheKey = `${req.headers['accept-language']}:${req.headers['x-shop-country']}`;
32
- const cachedContext = localeContextCache.get(cacheKey) as UnchainedLocaleContext;
32
+ const currencies = await unchainedAPI.modules.currencies.findCurrencies({ includeInactive: false });
33
33
 
34
- const userAgent = req.headers['user-agent'];
35
- const { remoteAddress, remotePort } = resolveUserRemoteAddress(req);
34
+ const supportedLocaleStrings = languages.reduce((accumulator, language) => {
35
+ const added = countries.map((country) => {
36
+ return `${language.isoCode}-${country.isoCode}`;
37
+ });
38
+ return accumulator.concat(added);
39
+ }, []);
36
40
 
37
- if (cachedContext) return { remoteAddress, remotePort, userAgent, ...cachedContext };
41
+ const supportedLocales = new Locales(supportedLocaleStrings, systemLocale.code);
38
42
 
39
- // return the parsed locale by bcp47 and
40
- // return the best resolved normalized locale by locale according to system-wide configuration
41
- // else fallback to base language & base country
43
+ const localeContext = resolveBestSupported(acceptLang, supportedLocales);
44
+ const countryContext = resolveBestCountry(localeContext.country, acceptCountry, countries);
42
45
 
43
- const languages = await unchainedAPI.modules.languages.findLanguages(
44
- { includeInactive: false },
45
- { projection: { isoCode: 1, isActive: 1 } },
46
- );
47
-
48
- const countries = await unchainedAPI.modules.countries.findCountries(
49
- { includeInactive: false },
50
- { projection: { isoCode: 1, isActive: 1 } },
51
- );
46
+ const countryObject = countries.find((country) => country.isoCode === countryContext);
47
+ const currencyContext = resolveBestCurrency(countryObject.defaultCurrencyCode, currencies);
52
48
 
53
- const supportedLocaleStrings = languages.reduce((accumulator, language) => {
54
- const added = countries.map((country) => {
55
- return `${language.isoCode}-${country.isoCode}`;
49
+ log(`Locale Context: Resolved ${localeContext.normalized} ${countryContext} ${currencyContext}`, {
50
+ level: LogLevel.Debug,
56
51
  });
57
- return accumulator.concat(added);
58
- }, []);
59
52
 
60
- const supportedLocales = new Locales(supportedLocaleStrings, systemLocale.code);
53
+ const newContext: UnchainedLocaleContext = {
54
+ localeContext,
55
+ countryContext,
56
+ currencyContext,
57
+ };
61
58
 
62
- const localeContext = resolveBestSupported(req.headers['accept-language'], supportedLocales);
63
- const countryContext = resolveBestCountry(
64
- localeContext.country,
65
- req.headers['x-shop-country'],
66
- countries,
67
- );
68
- log(`Locale Context: Resolved ${localeContext.normalized} ${countryContext}`, {
69
- level: LogLevel.Debug,
70
- });
71
- const newContext: UnchainedLocaleContext = {
72
- localeContext,
73
- countryContext,
74
- };
75
- localeContextCache.set(cacheKey, newContext);
59
+ return newContext;
60
+ },
61
+ {
62
+ maxAge: NODE_ENV === 'production' ? 1000 * 60 : 100, // minute or 100ms
63
+ promise: true,
64
+ normalizer(args) {
65
+ return `${args[0].acceptLang}-${args[0].acceptCountry}`;
66
+ },
67
+ },
68
+ );
76
69
 
77
- return { remoteAddress, remotePort, userAgent, ...newContext };
70
+ export const getLocaleContext = async (
71
+ req: IncomingMessage,
72
+ res: OutgoingMessage,
73
+ unchainedAPI: UnchainedCore,
74
+ ): Promise<UnchainedLocaleContext> => {
75
+ const userAgent = req.headers['user-agent'];
76
+ const { remoteAddress, remotePort } = resolveUserRemoteAddress(req);
77
+ const context = await resolveDefaultContext(
78
+ { acceptLang: req.headers['accept-language'], acceptCountry: req.headers['x-shop-country'] },
79
+ unchainedAPI,
80
+ );
81
+ return { remoteAddress, remotePort, userAgent, ...context };
78
82
  };
@@ -21,7 +21,7 @@ export default async function logout(root: Root, { token }: { token: string }, c
21
21
  ...loggedOut.error,
22
22
  });
23
23
  } else {
24
- setLoginToken(null);
24
+ setLoginToken(context.res, null);
25
25
  }
26
26
 
27
27
  return { success: loggedOut.success };
@@ -20,7 +20,7 @@ export default async function logoutAllSessions(root: Root, _: any, context: Con
20
20
  ...loggedOut.error,
21
21
  });
22
22
  } else {
23
- setLoginToken(null);
23
+ setLoginToken(context.res, null);
24
24
  }
25
25
 
26
26
  return { success: loggedOut.success };
@@ -5,7 +5,7 @@ import { CountryNotFoundError, InvalidIdError } from '../../../errors.js';
5
5
 
6
6
  export default async function updateCountry(
7
7
  root: Root,
8
- { country, countryId }: { country: Country; countryId: string },
8
+ { country, countryId }: { country: Country & { defaultCurrencyId: string }; countryId: string },
9
9
  { userId, modules }: Context,
10
10
  ) {
11
11
  log(`mutation updateCountry ${countryId}`, { userId });
@@ -15,7 +15,12 @@ export default async function updateCountry(
15
15
  if (!(await modules.countries.countryExists({ countryId })))
16
16
  throw new CountryNotFoundError({ countryId });
17
17
 
18
- await modules.countries.update(countryId, country);
18
+ const currencyObject = await modules.currencies.findCurrency({
19
+ currencyId: country.defaultCurrencyId,
20
+ });
21
+ const defaultCurrencyCode = country?.defaultCurrencyCode || currencyObject?.isoCode;
22
+
23
+ await modules.countries.update(countryId, { ...country, defaultCurrencyCode });
19
24
 
20
25
  return modules.countries.findCountry({ countryId });
21
26
  }
@@ -13,7 +13,7 @@ export default async function createEnrollment(
13
13
  { contact, plan, billingAddress, payment, delivery, meta },
14
14
  context: Context,
15
15
  ) {
16
- const { countryContext, modules, userId } = context;
16
+ const { countryContext, currencyContext, modules, userId } = context;
17
17
 
18
18
  log('mutation createEnrollment', { userId });
19
19
 
@@ -40,6 +40,7 @@ export default async function createEnrollment(
40
40
  configuration,
41
41
  contact,
42
42
  countryCode: countryContext,
43
+ currencyCode: currencyContext,
43
44
  delivery,
44
45
  meta,
45
46
  payment,
@@ -9,6 +9,7 @@ export default async function confirmOrder(
9
9
  orderId: string;
10
10
  paymentContext?: any;
11
11
  deliveryContext?: any;
12
+ comment?: string;
12
13
  },
13
14
  context: Context,
14
15
  ) {
@@ -9,6 +9,7 @@ export default async function rejectOrder(
9
9
  orderId: string;
10
10
  paymentContext?: any;
11
11
  deliveryContext?: any;
12
+ comment?: string;
12
13
  },
13
14
  context: Context,
14
15
  ) {
@@ -16,6 +17,7 @@ export default async function rejectOrder(
16
17
  const { orderId, ...transactionContext } = params;
17
18
 
18
19
  log('mutation rejectOrder', { orderId, userId });
20
+
19
21
  if (!orderId) throw new InvalidIdError({ orderId });
20
22
 
21
23
  const order = await modules.orders.findOrder({ orderId });
@@ -13,9 +13,9 @@ export interface CountryHelperTypes {
13
13
 
14
14
  export const Country: CountryHelperTypes = {
15
15
  defaultCurrency: async (country, _, { modules }) => {
16
- if (country.defaultCurrencyId) {
16
+ if (country.defaultCurrencyCode) {
17
17
  return modules.currencies.findCurrency({
18
- currencyId: country.defaultCurrencyId,
18
+ isoCode: country.defaultCurrencyCode,
19
19
  });
20
20
  }
21
21
  return null;
@@ -59,17 +59,9 @@ export const DeliveryProvider: DeliveryProviderHelperTypes = {
59
59
  { currency: currencyCode, orderId, useNetPrice, context: providerContext },
60
60
  requestContext,
61
61
  ) {
62
- const { modules, services, countryContext: country, user } = requestContext;
62
+ const { modules, countryContext: country, user } = requestContext;
63
63
  const order = await modules.orders.findOrder({ orderId });
64
-
65
- const currency =
66
- currencyCode ||
67
- (await services.countries.resolveDefaultCurrencyCode(
68
- {
69
- isoCode: country,
70
- },
71
- requestContext,
72
- ));
64
+ const currency = currencyCode || requestContext.currencyContext;
73
65
 
74
66
  const pricingDirector = await DeliveryPricingDirector.actions(
75
67
  {
@@ -10,8 +10,8 @@ export const LoginMethodResponse = {
10
10
 
11
11
  return user;
12
12
  },
13
- token({ token, tokenExpires }, _, { setLoginToken }: Context) {
14
- setLoginToken(token, tokenExpires);
13
+ token({ token, tokenExpires }, _, { res, setLoginToken }: Context) {
14
+ setLoginToken(res, token, tokenExpires);
15
15
  return token;
16
16
  },
17
17
  };
@@ -59,17 +59,10 @@ export const PaymentProvider: PaymentProviderHelperTypes = {
59
59
  { currency: currencyCode, orderId, useNetPrice, context: providerContext },
60
60
  requestContext,
61
61
  ) {
62
- const { modules, services, countryContext: country, user } = requestContext;
62
+ const { modules, countryContext: country, user } = requestContext;
63
63
  const order = await modules.orders.findOrder({ orderId });
64
64
 
65
- const currency =
66
- currencyCode ||
67
- (await services.countries.resolveDefaultCurrencyCode(
68
- {
69
- isoCode: country,
70
- },
71
- requestContext,
72
- ));
65
+ const currency = currencyCode || requestContext.currencyContext;
73
66
 
74
67
  const pricingDirector = await PaymentPricingDirector.actions(
75
68
  {
@@ -58,14 +58,7 @@ export const ConfigurableProduct = {
58
58
  requestContext: Context,
59
59
  ): Promise<ProductPriceRange> {
60
60
  const { countryContext, modules } = requestContext;
61
- const currencyCode =
62
- forcedCurrencyCode ||
63
- (await requestContext.services.countries.resolveDefaultCurrencyCode(
64
- {
65
- isoCode: countryContext,
66
- },
67
- requestContext,
68
- ));
61
+ const currencyCode = forcedCurrencyCode || requestContext.currencyContext;
69
62
  return modules.products.prices.catalogPriceRange(product, {
70
63
  quantity,
71
64
  vectors,
@@ -111,14 +104,8 @@ export const ConfigurableProduct = {
111
104
  requestContext: Context,
112
105
  ): Promise<ProductPriceRange> {
113
106
  const { countryContext, modules } = requestContext;
114
- const currency =
115
- forcedCurrencyCode ||
116
- (await requestContext.services.countries.resolveDefaultCurrencyCode(
117
- {
118
- isoCode: countryContext,
119
- },
120
- requestContext,
121
- ));
107
+ const currency = forcedCurrencyCode || requestContext.currencyContext;
108
+
122
109
  return modules.products.prices.simulatedPriceRange(
123
110
  product,
124
111
  {
@@ -11,17 +11,10 @@ export const PlanProduct = {
11
11
  requestContext: Context,
12
12
  ): Promise<ProductPrice> {
13
13
  const { modules, countryContext } = requestContext;
14
- const currencyCode =
15
- forcedCurrencyCode ||
16
- (await requestContext.services.countries.resolveDefaultCurrencyCode(
17
- {
18
- isoCode: countryContext,
19
- },
20
- requestContext,
21
- ));
14
+ const currency = forcedCurrencyCode || requestContext.currencyContext;
22
15
  return modules.products.prices.price(product, {
23
16
  country: countryContext,
24
- currency: currencyCode,
17
+ currency,
25
18
  quantity,
26
19
  });
27
20
  },
@@ -36,14 +29,8 @@ export const PlanProduct = {
36
29
  requestContext: Context,
37
30
  ): Promise<ProductPrice> {
38
31
  const { countryContext, modules } = requestContext;
39
- const currency =
40
- forcedCurrencyCode ||
41
- (await requestContext.services.countries.resolveDefaultCurrencyCode(
42
- {
43
- isoCode: countryContext,
44
- },
45
- requestContext,
46
- ));
32
+ const currency = forcedCurrencyCode || requestContext.currencyContext;
33
+
47
34
  return modules.products.prices.userPrice(
48
35
  obj,
49
36
  { quantity, userId: requestContext.userId, currency, country: countryContext, useNetPrice },
@@ -63,14 +50,7 @@ export const PlanProduct = {
63
50
  }>
64
51
  > {
65
52
  const { countryContext, modules } = requestContext;
66
- const currency =
67
- forcedCurrencyCode ||
68
- (await requestContext.services.countries.resolveDefaultCurrencyCode(
69
- {
70
- isoCode: countryContext,
71
- },
72
- requestContext,
73
- ));
53
+ const currency = forcedCurrencyCode || requestContext.currencyContext;
74
54
  return modules.products.prices.catalogPricesLeveled(obj, { currency, country: countryContext });
75
55
  },
76
56
 
@@ -44,7 +44,8 @@ export default [
44
44
  input UpdateCountryInput {
45
45
  isoCode: String!
46
46
  isActive: Boolean
47
- defaultCurrencyId: String
47
+ defaultCurrencyCode: String
48
+ defaultCurrencyId: String @deprecated(reason: "Use defaultCurrencyCode instead")
48
49
  }
49
50
 
50
51
  input CreateCurrencyInput {
@@ -304,12 +304,12 @@ export default [
304
304
  """
305
305
  Manually confirm an order which is in progress
306
306
  """
307
- confirmOrder(orderId: ID!, paymentContext: JSON, deliveryContext: JSON): Order!
307
+ confirmOrder(orderId: ID!, paymentContext: JSON, deliveryContext: JSON, comment: String): Order!
308
308
 
309
309
  """
310
310
  Manually reject an order which is in progress
311
311
  """
312
- rejectOrder(orderId: ID!, paymentContext: JSON, deliveryContext: JSON): Order!
312
+ rejectOrder(orderId: ID!, paymentContext: JSON, deliveryContext: JSON, comment: String): Order!
313
313
 
314
314
  """
315
315
  Manually mark an unpaid/partially paid order as fully paid
@@ -14,6 +14,25 @@ const {
14
14
  NODE_ENV,
15
15
  } = process.env;
16
16
 
17
+ function setLoginToken(res: OutgoingMessage, token: string | null, expires?: Date) {
18
+ const cookieName = UNCHAINED_COOKIE_NAME;
19
+ const domain = UNCHAINED_COOKIE_DOMAIN;
20
+ const path = UNCHAINED_COOKIE_PATH;
21
+
22
+ if (!domain) return;
23
+
24
+ const authCookie = cookie.serialize(cookieName, token || null, {
25
+ domain,
26
+ httpOnly: true,
27
+ path,
28
+ expires: token && expires ? expires : undefined,
29
+ maxAge: token ? undefined : -1,
30
+ sameSite: 'lax',
31
+ secure: NODE_ENV === 'production',
32
+ });
33
+ res.setHeader('Set-Cookie', authCookie);
34
+ }
35
+
17
36
  export const getUserContext = async (
18
37
  req: IncomingMessage & { cookies?: any },
19
38
  res: OutgoingMessage,
@@ -21,25 +40,8 @@ export const getUserContext = async (
21
40
  ): Promise<UnchainedUserContext> => {
22
41
  // there is a possible current user connected!
23
42
  const cookieName = UNCHAINED_COOKIE_NAME;
24
- const domain = UNCHAINED_COOKIE_DOMAIN;
25
- const path = UNCHAINED_COOKIE_PATH;
26
-
27
43
  let loginToken = req.cookies?.[cookieName];
28
44
 
29
- function setLoginToken(token: string, expires: Date) {
30
- if (!domain) return;
31
- const authCookie = cookie.serialize(cookieName, token || null, {
32
- domain,
33
- httpOnly: true,
34
- path,
35
- expires: token ? expires : undefined,
36
- maxAge: token ? undefined : -1,
37
- sameSite: 'lax',
38
- secure: NODE_ENV === 'production',
39
- });
40
- res.setHeader('Set-Cookie', authCookie);
41
- }
42
-
43
45
  if (req.headers.authorization) {
44
46
  const [type, token] = req.headers.authorization.split(' ');
45
47
  if (type === 'Bearer') {
@@ -80,6 +82,11 @@ export const getUserContext = async (
80
82
  };
81
83
  }
82
84
  }
85
+
86
+ // If there is no user with this token or the token is expires/invalid,
87
+ // we should remove that cookie from the client
88
+ setLoginToken(res, null);
89
+
83
90
  return { loginToken: loginToken as string, setLoginToken };
84
91
  }
85
92