@unchainedshop/api 2.8.18 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (82) hide show
  1. package/jest.config.js +2 -2
  2. package/lib/errors.d.ts +1 -0
  3. package/lib/errors.js +1 -0
  4. package/lib/errors.js.map +1 -1
  5. package/lib/resolvers/mutations/index.d.ts +1 -0
  6. package/lib/resolvers/mutations/index.js +2 -0
  7. package/lib/resolvers/mutations/index.js.map +1 -1
  8. package/lib/resolvers/mutations/warehousing/invalidateToken.d.ts +4 -0
  9. package/lib/resolvers/mutations/warehousing/invalidateToken.js +26 -0
  10. package/lib/resolvers/mutations/warehousing/invalidateToken.js.map +1 -0
  11. package/lib/resolvers/queries/index.d.ts +1 -0
  12. package/lib/resolvers/queries/index.js +2 -0
  13. package/lib/resolvers/queries/index.js.map +1 -1
  14. package/lib/resolvers/queries/warehousing/tokens.d.ts +5 -0
  15. package/lib/resolvers/queries/warehousing/tokens.js +6 -0
  16. package/lib/resolvers/queries/warehousing/tokens.js.map +1 -0
  17. package/lib/resolvers/type/index.d.ts +367 -9
  18. package/lib/resolvers/type/order/order-item-types.d.ts +15 -17
  19. package/lib/resolvers/type/order/order-item-types.js +28 -23
  20. package/lib/resolvers/type/order/order-item-types.js.map +1 -1
  21. package/lib/resolvers/type/order/order-types.d.ts +15 -19
  22. package/lib/resolvers/type/order/order-types.js +48 -28
  23. package/lib/resolvers/type/order/order-types.js.map +1 -1
  24. package/lib/resolvers/type/product/product-bundle-types.d.ts +34 -2
  25. package/lib/resolvers/type/product/product-bundle-types.js.map +1 -1
  26. package/lib/resolvers/type/product/product-configurable-types.d.ts +62 -2
  27. package/lib/resolvers/type/product/product-configurable-types.js +10 -10
  28. package/lib/resolvers/type/product/product-configurable-types.js.map +1 -1
  29. package/lib/resolvers/type/product/product-plan-types.d.ts +53 -2
  30. package/lib/resolvers/type/product/product-plan-types.js +9 -9
  31. package/lib/resolvers/type/product/product-plan-types.js.map +1 -1
  32. package/lib/resolvers/type/product/product-simple-types.d.ts +85 -2
  33. package/lib/resolvers/type/product/product-simple-types.js +7 -7
  34. package/lib/resolvers/type/product/product-simple-types.js.map +1 -1
  35. package/lib/resolvers/type/product/product-tokenized-types.d.ts +67 -2
  36. package/lib/resolvers/type/product/product-tokenized-types.js +19 -10
  37. package/lib/resolvers/type/product/product-tokenized-types.js.map +1 -1
  38. package/lib/resolvers/type/product/product-types.d.ts +38 -2
  39. package/lib/resolvers/type/product/product-types.js +15 -15
  40. package/lib/resolvers/type/product/product-types.js.map +1 -1
  41. package/lib/resolvers/type/token-types.d.ts +9 -12
  42. package/lib/resolvers/type/token-types.js +22 -3
  43. package/lib/resolvers/type/token-types.js.map +1 -1
  44. package/lib/roles/all.js +38 -17
  45. package/lib/roles/all.js.map +1 -1
  46. package/lib/roles/index.js +1 -0
  47. package/lib/roles/index.js.map +1 -1
  48. package/lib/roles/loggedIn.js +9 -14
  49. package/lib/roles/loggedIn.js.map +1 -1
  50. package/lib/schema/mutation.js +5 -1
  51. package/lib/schema/mutation.js.map +1 -1
  52. package/lib/schema/query.js +5 -0
  53. package/lib/schema/query.js.map +1 -1
  54. package/lib/schema/types/order/item.js +1 -0
  55. package/lib/schema/types/order/item.js.map +1 -1
  56. package/lib/schema/types/product/tokenized-product.js +2 -0
  57. package/lib/schema/types/product/tokenized-product.js.map +1 -1
  58. package/lib/schema/types/warehousing.js +9 -2
  59. package/lib/schema/types/warehousing.js.map +1 -1
  60. package/package.json +8 -8
  61. package/src/errors.ts +2 -0
  62. package/src/resolvers/mutations/index.ts +2 -0
  63. package/src/resolvers/mutations/warehousing/invalidateToken.ts +42 -0
  64. package/src/resolvers/queries/index.ts +2 -1
  65. package/src/resolvers/queries/warehousing/tokens.ts +18 -0
  66. package/src/resolvers/type/order/order-item-types.ts +59 -49
  67. package/src/resolvers/type/order/order-types.ts +58 -54
  68. package/src/resolvers/type/product/product-bundle-types.ts +3 -3
  69. package/src/resolvers/type/product/product-configurable-types.ts +79 -19
  70. package/src/resolvers/type/product/product-plan-types.ts +34 -15
  71. package/src/resolvers/type/product/product-simple-types.ts +41 -10
  72. package/src/resolvers/type/product/product-tokenized-types.ts +43 -13
  73. package/src/resolvers/type/product/product-types.ts +77 -18
  74. package/src/resolvers/type/token-types.ts +35 -20
  75. package/src/roles/all.ts +46 -17
  76. package/src/roles/index.ts +1 -0
  77. package/src/roles/loggedIn.ts +10 -24
  78. package/src/schema/mutation.ts +5 -1
  79. package/src/schema/query.ts +5 -0
  80. package/src/schema/types/order/item.ts +1 -0
  81. package/src/schema/types/product/tokenized-product.ts +2 -0
  82. package/src/schema/types/warehousing.ts +9 -2
@@ -1,24 +1,62 @@
1
- import { ConfigurableProductHelperTypes } from '@unchainedshop/types/products.js';
1
+ import {
2
+ Product as ProductType,
3
+ ProductAssignment,
4
+ ProductConfiguration,
5
+ ProductPriceRange,
6
+ } from '@unchainedshop/types/products.js';
7
+ import { Context } from '@unchainedshop/types/api.js';
8
+ import { ProductVariation } from '@unchainedshop/types/products.variations.js';
2
9
  import { Product } from './product-types.js';
3
10
 
4
- export const ConfigurableProduct: ConfigurableProductHelperTypes = {
11
+ export const ConfigurableProduct = {
5
12
  ...Product,
6
13
 
7
- assignments: async (obj, params, { modules }) => {
8
- return modules.products.proxyAssignments(obj, params);
14
+ async assignments(
15
+ product: ProductType,
16
+ params: {
17
+ includeInactive: boolean;
18
+ },
19
+ { modules }: Context,
20
+ ): Promise<
21
+ Array<{
22
+ assignment: ProductAssignment;
23
+ product: typeof product;
24
+ }>
25
+ > {
26
+ return modules.products.proxyAssignments(product, params);
9
27
  },
10
28
 
11
- products: async (obj, { vectors, includeInactive }, { modules }) => {
12
- return modules.products.proxyProducts(obj, vectors, {
29
+ async products(
30
+ product: ProductType,
31
+ {
32
+ vectors,
33
+ includeInactive,
34
+ }: {
35
+ vectors: Array<ProductConfiguration>;
36
+ includeInactive: boolean;
37
+ },
38
+ { modules }: Context,
39
+ ): Promise<Array<typeof product>> {
40
+ return modules.products.proxyProducts(product, vectors, {
13
41
  includeInactive,
14
42
  });
15
43
  },
16
44
 
17
- catalogPriceRange: async (
18
- obj,
19
- { quantity, vectors, currency: forcedCurrencyCode, includeInactive },
20
- requestContext,
21
- ) => {
45
+ async catalogPriceRange(
46
+ product: ProductType,
47
+ {
48
+ quantity,
49
+ vectors,
50
+ currency: forcedCurrencyCode,
51
+ includeInactive,
52
+ }: {
53
+ currency?: string;
54
+ includeInactive: boolean;
55
+ quantity: number;
56
+ vectors: Array<ProductConfiguration>;
57
+ },
58
+ requestContext: Context,
59
+ ): Promise<ProductPriceRange> {
22
60
  const { countryContext, modules } = requestContext;
23
61
  const currencyCode =
24
62
  forcedCurrencyCode ||
@@ -28,7 +66,7 @@ export const ConfigurableProduct: ConfigurableProductHelperTypes = {
28
66
  },
29
67
  requestContext,
30
68
  ));
31
- return modules.products.prices.catalogPriceRange(obj, {
69
+ return modules.products.prices.catalogPriceRange(product, {
32
70
  quantity,
33
71
  vectors,
34
72
  includeInactive,
@@ -37,19 +75,41 @@ export const ConfigurableProduct: ConfigurableProductHelperTypes = {
37
75
  });
38
76
  },
39
77
 
40
- variations: async (obj, { limit = 10, offset = 0 }, { modules }) => {
78
+ async variations(
79
+ product: ProductType,
80
+ {
81
+ limit = 10,
82
+ offset = 0,
83
+ }: {
84
+ limit: number;
85
+ offset: number;
86
+ },
87
+ { modules }: Context,
88
+ ): Promise<Array<ProductVariation>> {
41
89
  return modules.products.variations.findProductVariations({
42
- productId: obj._id,
90
+ productId: product._id,
43
91
  limit,
44
92
  offset,
45
93
  });
46
94
  },
47
95
 
48
96
  async simulatedPriceRange(
49
- obj,
50
- { currency: forcedCurrencyCode, quantity, useNetPrice, vectors, includeInactive },
51
- requestContext,
52
- ) {
97
+ product: ProductType,
98
+ {
99
+ currency: forcedCurrencyCode,
100
+ quantity,
101
+ useNetPrice,
102
+ vectors,
103
+ includeInactive,
104
+ }: {
105
+ currency?: string;
106
+ includeInactive: boolean;
107
+ quantity?: number;
108
+ vectors: Array<ProductConfiguration>;
109
+ useNetPrice: boolean;
110
+ },
111
+ requestContext: Context,
112
+ ): Promise<ProductPriceRange> {
53
113
  const { countryContext, modules } = requestContext;
54
114
  const currency =
55
115
  forcedCurrencyCode ||
@@ -60,7 +120,7 @@ export const ConfigurableProduct: ConfigurableProductHelperTypes = {
60
120
  requestContext,
61
121
  ));
62
122
  return modules.products.prices.simulatedPriceRange(
63
- obj,
123
+ product,
64
124
  {
65
125
  quantity,
66
126
  currency,
@@ -1,10 +1,15 @@
1
- import { PlanProductHelperTypes } from '@unchainedshop/types/products.js';
1
+ import { ProductPrice, Product as ProductType } from '@unchainedshop/types/products.js';
2
+ import { Context } from '@unchainedshop/types/api.js';
2
3
  import { Product } from './product-types.js';
3
4
 
4
- export const PlanProduct: PlanProductHelperTypes = {
5
+ export const PlanProduct = {
5
6
  ...Product,
6
7
 
7
- catalogPrice: async (product, { quantity, currency: forcedCurrencyCode }, requestContext) => {
8
+ async catalogPrice(
9
+ product: ProductType,
10
+ { quantity, currency: forcedCurrencyCode }: { quantity?: number; currency?: string },
11
+ requestContext: Context,
12
+ ): Promise<ProductPrice> {
8
13
  const { modules, countryContext } = requestContext;
9
14
  const currencyCode =
10
15
  forcedCurrencyCode ||
@@ -21,11 +26,15 @@ export const PlanProduct: PlanProductHelperTypes = {
21
26
  });
22
27
  },
23
28
 
24
- simulatedPrice: async (
25
- obj,
26
- { currency: forcedCurrencyCode, quantity, useNetPrice },
27
- requestContext,
28
- ) => {
29
+ async simulatedPrice(
30
+ obj: ProductType,
31
+ {
32
+ currency: forcedCurrencyCode,
33
+ quantity,
34
+ useNetPrice,
35
+ }: { quantity?: number; currency?: string; useNetPrice?: boolean },
36
+ requestContext: Context,
37
+ ): Promise<ProductPrice> {
29
38
  const { countryContext, modules } = requestContext;
30
39
  const currency =
31
40
  forcedCurrencyCode ||
@@ -42,7 +51,17 @@ export const PlanProduct: PlanProductHelperTypes = {
42
51
  );
43
52
  },
44
53
 
45
- leveledCatalogPrices: async (obj, { currency: forcedCurrencyCode }, requestContext) => {
54
+ async leveledCatalogPrices(
55
+ obj: ProductType,
56
+ { currency: forcedCurrencyCode }: { currency?: string },
57
+ requestContext: Context,
58
+ ): Promise<
59
+ Array<{
60
+ minQuantity: number;
61
+ maxQuantity: number;
62
+ price: ProductPrice;
63
+ }>
64
+ > {
46
65
  const { countryContext, modules } = requestContext;
47
66
  const currency =
48
67
  forcedCurrencyCode ||
@@ -55,13 +74,13 @@ export const PlanProduct: PlanProductHelperTypes = {
55
74
  return modules.products.prices.catalogPricesLeveled(obj, { currency, country: countryContext });
56
75
  },
57
76
 
58
- salesUnit(obj) {
59
- return obj.commerce && obj.commerce.salesUnit;
77
+ salesUnit({ commerce }: ProductType): string {
78
+ return commerce?.salesUnit;
60
79
  },
61
- salesQuantityPerUnit(obj) {
62
- return obj.commerce && obj.commerce.salesQuantityPerUnit;
80
+ salesQuantityPerUnit({ commerce }: ProductType): string {
81
+ return commerce?.salesQuantityPerUnit;
63
82
  },
64
- defaultOrderQuantity(obj) {
65
- return obj.commerce && obj.commerce.defaultOrderQuantity;
83
+ defaultOrderQuantity({ commerce }: ProductType): number {
84
+ return commerce?.defaultOrderQuantity;
66
85
  },
67
86
  };
@@ -1,11 +1,26 @@
1
- import { SimpleProductHelperTypes } from '@unchainedshop/types/products.js';
2
- import { WarehousingContext } from '@unchainedshop/types/warehousing.js';
1
+ import { Product, ProductSupply } from '@unchainedshop/types/products.js';
2
+ import { WarehousingContext, WarehousingProvider } from '@unchainedshop/types/warehousing.js';
3
+ import { Context } from '@unchainedshop/types/api.js';
4
+ import { DeliveryProviderType } from '@unchainedshop/core-delivery';
5
+ import { DeliveryProvider } from '@unchainedshop/types/delivery.js';
3
6
  import { PlanProduct } from './product-plan-types.js';
4
7
 
5
- export const SimpleProduct: SimpleProductHelperTypes = {
8
+ export const SimpleProduct = {
6
9
  ...PlanProduct,
7
10
 
8
- simulatedDispatches: async (obj, params, requestContext) => {
11
+ async simulatedDispatches(
12
+ obj: Product,
13
+ params: { referenceDate: Date; quantity: number; deliveryProviderType: DeliveryProviderType },
14
+ requestContext: Context,
15
+ ): Promise<
16
+ Array<{
17
+ _id: string;
18
+ deliveryProvider?: DeliveryProvider;
19
+ warehousingProvider?: WarehousingProvider;
20
+ shipping?: Date;
21
+ earliestDelivery?: Date;
22
+ }>
23
+ > {
9
24
  const { deliveryProviderType, referenceDate, quantity } = params;
10
25
  const { modules } = requestContext;
11
26
 
@@ -51,7 +66,21 @@ export const SimpleProduct: SimpleProductHelperTypes = {
51
66
  }, Promise.resolve([]));
52
67
  },
53
68
 
54
- simulatedStocks: async (obj, params, requestContext) => {
69
+ async simulatedStocks(
70
+ obj: Product,
71
+ params: {
72
+ referenceDate: Date;
73
+ deliveryProviderType: DeliveryProviderType;
74
+ },
75
+ requestContext: Context,
76
+ ): Promise<
77
+ Array<{
78
+ _id: string;
79
+ deliveryProvider?: DeliveryProvider;
80
+ warehousingProvider?: WarehousingProvider;
81
+ quantity?: number;
82
+ }>
83
+ > {
55
84
  const { modules } = requestContext;
56
85
  const { referenceDate, deliveryProviderType } = params;
57
86
 
@@ -96,13 +125,15 @@ export const SimpleProduct: SimpleProductHelperTypes = {
96
125
  }, Promise.resolve([]));
97
126
  },
98
127
 
99
- baseUnit: (obj) => {
100
- return obj.warehousing && obj.warehousing.baseUnit;
128
+ baseUnit({ warehousing }): string {
129
+ return warehousing?.baseUnit;
101
130
  },
102
- sku: (obj) => {
103
- return obj.warehousing && obj.warehousing.sku;
131
+
132
+ sku({ warehousing }): string {
133
+ return warehousing?.sku;
104
134
  },
105
- dimensions: ({ supply }) => {
135
+
136
+ dimensions({ supply }): ProductSupply {
106
137
  if (!supply) return null;
107
138
  const { weightInGram, heightInMillimeters, lengthInMillimeters, widthInMillimeters } = supply;
108
139
  return {
@@ -1,28 +1,49 @@
1
- import { TokenizedProductHelperTypes } from '@unchainedshop/types/products.js';
2
- import { WarehousingContext } from '@unchainedshop/types/warehousing.js';
1
+ import {
2
+ Product,
3
+ ProductContractConfiguration,
4
+ ProductContractStandard,
5
+ } from '@unchainedshop/types/products.js';
6
+ import { WarehousingContext, WarehousingProvider } from '@unchainedshop/types/warehousing.js';
7
+ import { Context } from '@unchainedshop/types/api.js';
8
+ import { DeliveryProvider } from '@unchainedshop/types/delivery.js';
3
9
  import { PlanProduct } from './product-plan-types.js';
10
+ import { checkAction } from '../../../acl.js';
11
+ import { actions } from '../../../roles/index.js';
4
12
 
5
- export const TokenizedProduct: TokenizedProductHelperTypes = {
13
+ export const TokenizedProduct = {
6
14
  ...PlanProduct,
7
15
 
8
- contractAddress(product) {
9
- return product.tokenization?.contractAddress;
16
+ contractAddress({ tokenization }: Product): string {
17
+ return tokenization?.contractAddress;
10
18
  },
11
19
 
12
- contractConfiguration(product) {
13
- if (!product.tokenization) return null;
20
+ contractConfiguration({ tokenization }: Product): ProductContractConfiguration {
21
+ if (!tokenization) return null;
14
22
  return {
15
- supply: product.tokenization.supply,
16
- tokenId: product.tokenization.tokenId,
17
- ercMetadataProperties: product.tokenization.ercMetadataProperties,
23
+ supply: tokenization.supply,
24
+ tokenId: tokenization.tokenId,
25
+ ercMetadataProperties: tokenization.ercMetadataProperties,
18
26
  };
19
27
  },
20
28
 
21
- contractStandard(product) {
22
- return product.tokenization?.contractStandard;
29
+ contractStandard({ tokenization }: Product): ProductContractStandard {
30
+ return tokenization?.contractStandard;
23
31
  },
24
32
 
25
- simulatedStocks: async (obj, params, requestContext) => {
33
+ async simulatedStocks(
34
+ obj: Product,
35
+ params: {
36
+ referenceDate: Date;
37
+ },
38
+ requestContext: Context,
39
+ ): Promise<
40
+ Array<{
41
+ _id: string;
42
+ deliveryProvider?: DeliveryProvider;
43
+ warehousingProvider?: WarehousingProvider;
44
+ quantity?: number;
45
+ }>
46
+ > {
26
47
  const { modules } = requestContext;
27
48
  const { referenceDate } = params;
28
49
 
@@ -64,6 +85,15 @@ export const TokenizedProduct: TokenizedProductHelperTypes = {
64
85
  return result.concat(result, mappedWarehousingProviders);
65
86
  }, Promise.resolve([]));
66
87
  },
88
+
89
+ async tokens(product: Product, params: never, requestContext: Context) {
90
+ await checkAction(requestContext, actions.viewTokens, [undefined, params]);
91
+
92
+ const tokens = await requestContext.modules.warehousing.findTokens({
93
+ productId: product._id,
94
+ });
95
+ return tokens;
96
+ },
67
97
  };
68
98
 
69
99
  delete TokenizedProduct.salesUnit;
@@ -1,40 +1,91 @@
1
- import { ProductHelperTypes } from '@unchainedshop/types/products.js';
2
- import { ProductTypes } from '@unchainedshop/core-products';
1
+ import { ProductText, Product as ProductType } from '@unchainedshop/types/products.js';
2
+ import { ProductStatus, ProductTypes } from '@unchainedshop/core-products';
3
3
  import { objectInvert } from '@unchainedshop/utils';
4
+ import { Context, SortOption } from '@unchainedshop/types/api.js';
5
+ import { AssortmentPathLink } from '@unchainedshop/types/assortments.js';
6
+ import { ProductMedia } from '@unchainedshop/types/products.media.js';
7
+ import { ProductReview } from '@unchainedshop/types/products.reviews.js';
4
8
 
5
- export const Product: ProductHelperTypes = {
6
- __resolveType: (obj) => {
9
+ export const Product = {
10
+ __resolveType: (product: ProductType): string => {
7
11
  const invertedProductTypes = objectInvert(ProductTypes);
8
- return invertedProductTypes[obj.type];
12
+ return invertedProductTypes[product.type];
9
13
  },
10
14
 
11
- assortmentPaths: async (obj, _, { modules }) => {
15
+ async assortmentPaths(
16
+ product: ProductType,
17
+ params: {
18
+ forceLocale?: string;
19
+ },
20
+ { modules }: Context,
21
+ ): Promise<
22
+ Array<{
23
+ links: Array<AssortmentPathLink>;
24
+ }>
25
+ > {
12
26
  return modules.assortments.breadcrumbs({
13
- productId: obj._id,
27
+ productId: product._id,
14
28
  });
15
29
  },
16
30
 
17
- media: async (obj, params, { modules }) => {
31
+ async media(
32
+ product: ProductType,
33
+ params: {
34
+ limit: number;
35
+ offset: number;
36
+ tags?: Array<string>;
37
+ },
38
+ { modules }: Context,
39
+ ): Promise<Array<ProductMedia>> {
18
40
  return modules.products.media.findProductMedias({
19
- productId: obj._id,
41
+ productId: product._id,
20
42
  ...params,
21
43
  });
22
44
  },
23
45
 
24
- reviews: async (obj, { limit = 10, offset = 0, sort, queryString }, { modules }) => {
46
+ async reviews(
47
+ product: ProductType,
48
+ {
49
+ limit = 10,
50
+ offset = 0,
51
+ sort,
52
+ queryString,
53
+ }: {
54
+ queryString?: string;
55
+ limit?: number;
56
+ offset?: number;
57
+ sort?: Array<SortOption>;
58
+ },
59
+ { modules }: Context,
60
+ ): Promise<Array<ProductReview>> {
25
61
  return modules.products.reviews.findProductReviews({
26
- productId: obj._id,
62
+ productId: product._id,
27
63
  limit,
28
64
  offset,
29
65
  sort,
30
66
  queryString,
31
67
  });
32
68
  },
33
- reviewsCount: async (obj, params, { modules }) => {
34
- return modules.products.reviews.count({ ...params, productId: obj._id });
69
+ async reviewsCount(
70
+ product: ProductType,
71
+ params: {
72
+ queryString?: string;
73
+ },
74
+ { modules }: Context,
75
+ ): Promise<number> {
76
+ return modules.products.reviews.count({ ...params, productId: product._id });
35
77
  },
36
78
 
37
- siblings: async (product, params, { modules }) => {
79
+ async siblings(
80
+ product: ProductType,
81
+ params: {
82
+ assortmentId?: string;
83
+ limit: number;
84
+ offset: number;
85
+ includeInactive: boolean;
86
+ },
87
+ { modules }: Context,
88
+ ): Promise<Array<typeof product>> {
38
89
  const { assortmentId, limit, offset, includeInactive = false } = params;
39
90
 
40
91
  const productId = product._id;
@@ -57,14 +108,22 @@ export const Product: ProductHelperTypes = {
57
108
  });
58
109
  },
59
110
 
60
- status(obj, _, { modules }) {
61
- return modules.products.normalizedStatus(obj);
111
+ status(product: ProductType, _, { modules }: Context): ProductStatus {
112
+ return modules.products.normalizedStatus(product);
62
113
  },
63
114
 
64
- async texts(obj, { forceLocale }, requestContext) {
115
+ async texts(
116
+ product: ProductType,
117
+ {
118
+ forceLocale,
119
+ }: {
120
+ forceLocale?: string;
121
+ },
122
+ requestContext: Context,
123
+ ): Promise<ProductText> {
65
124
  const { localeContext, loaders } = requestContext;
66
125
  return loaders.productTextLoader.load({
67
- productId: obj._id,
126
+ productId: product._id,
68
127
  locale: forceLocale || localeContext.normalized,
69
128
  });
70
129
  },
@@ -1,36 +1,23 @@
1
1
  import { Context } from '@unchainedshop/types/api.js';
2
- import { Product } from '@unchainedshop/types/products.js';
3
- import { User } from '@unchainedshop/types/user.js';
4
2
  import { TokenStatus, TokenSurrogate } from '@unchainedshop/types/warehousing.js';
5
3
  import { WorkStatus } from '@unchainedshop/types/worker.js';
6
4
  import localePkg from 'locale';
5
+ import { checkAction } from '../../acl.js';
6
+ import { actions } from '../../roles/index.js';
7
7
 
8
8
  const { Locale } = localePkg;
9
9
 
10
- type HelperType<T> = (root: TokenSurrogate, params: never, context: Context) => Promise<T>;
11
-
12
- export interface TokenHelperTypes {
13
- product: HelperType<Product>;
14
- status: HelperType<TokenStatus>;
15
- ercMetadata: (
16
- root: TokenSurrogate,
17
- params: { forceLocale?: string },
18
- context: Context,
19
- ) => Promise<any>;
20
- user: HelperType<User>;
21
- }
22
-
23
- export const Token: TokenHelperTypes = {
24
- product: async (token, _params, { modules }) => {
10
+ export const Token = {
11
+ product: async (token: TokenSurrogate, params: never, { modules }: Context) => {
25
12
  return modules.products.findProduct({ productId: token.productId });
26
13
  },
27
14
 
28
- user: async (token, _params, { modules }) => {
15
+ user: async (token: TokenSurrogate, params: never, { modules }: Context) => {
29
16
  if (!token.userId) return null;
30
17
  return modules.users.findUserById(token.userId);
31
18
  },
32
19
 
33
- status: async (token, _params, { modules }) => {
20
+ status: async (token: TokenSurrogate, params: never, { modules }: Context) => {
34
21
  if (token.walletAddress && !token.userId) {
35
22
  return TokenStatus.DECENTRALIZED;
36
23
  }
@@ -42,7 +29,11 @@ export const Token: TokenHelperTypes = {
42
29
  return TokenStatus.CENTRALIZED;
43
30
  },
44
31
 
45
- ercMetadata: async (token, { forceLocale }, context) => {
32
+ ercMetadata: async (
33
+ token: TokenSurrogate,
34
+ { forceLocale }: { forceLocale: string },
35
+ context: Context,
36
+ ) => {
46
37
  const { modules } = context;
47
38
  const product = await modules.products.findProduct({ productId: token.productId });
48
39
  const ercMetadata = await modules.warehousing.tokenMetadata(
@@ -58,4 +49,28 @@ export const Token: TokenHelperTypes = {
58
49
 
59
50
  return ercMetadata;
60
51
  },
52
+
53
+ isInvalidateable: async (token: TokenSurrogate, _params: never, context: Context) => {
54
+ const { modules } = context;
55
+ const product = await modules.products.findProduct({ productId: token.productId });
56
+ const isInvalidateable = await modules.warehousing.isInvalidateable(
57
+ token.chainTokenId,
58
+ {
59
+ token,
60
+ product,
61
+ referenceDate: new Date(),
62
+ },
63
+ context,
64
+ );
65
+
66
+ return isInvalidateable;
67
+ },
68
+
69
+ accessKey: async (token: TokenSurrogate, params: never, requestContext: Context) => {
70
+ const { modules } = requestContext;
71
+ await checkAction(requestContext, actions.updateToken, [undefined, { tokenId: token._id }]);
72
+ // This generates a hash that is stable until ownership is changed and allows accessing token
73
+ // data and operations
74
+ return modules.warehousing.buildAccessKeyForToken(token._id);
75
+ },
61
76
  };