@unchainedshop/api 2.0.0-beta5 → 2.0.0-beta7

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 (79) hide show
  1. package/lib/api-index.d.ts +3 -3
  2. package/lib/api-index.js +21 -3
  3. package/lib/api-index.js.map +1 -1
  4. package/lib/context.d.ts +1 -1
  5. package/lib/context.js +5 -4
  6. package/lib/context.js.map +1 -1
  7. package/lib/createERCMetadataServer.js +8 -12
  8. package/lib/createERCMetadataServer.js.map +1 -1
  9. package/lib/createGraphQLServer.d.ts +2 -2
  10. package/lib/createGraphQLServer.js +25 -35
  11. package/lib/createGraphQLServer.js.map +1 -1
  12. package/lib/errors.js +8 -3
  13. package/lib/errors.js.map +1 -1
  14. package/lib/loaders/index.js +50 -0
  15. package/lib/loaders/index.js.map +1 -1
  16. package/lib/resolvers/index.js +1 -1
  17. package/lib/resolvers/index.js.map +1 -1
  18. package/lib/resolvers/mutations/filters/updateFilter.js +2 -1
  19. package/lib/resolvers/mutations/filters/updateFilter.js.map +1 -1
  20. package/lib/resolvers/queries/products/product.js +1 -1
  21. package/lib/resolvers/queries/products/productCatalogPrices.d.ts +1 -1
  22. package/lib/resolvers/queries/products/productCatalogPrices.js +5 -2
  23. package/lib/resolvers/queries/products/productCatalogPrices.js.map +1 -1
  24. package/lib/resolvers/queries/products/products.js +1 -1
  25. package/lib/resolvers/queries/products/products.js.map +1 -1
  26. package/lib/resolvers/scalars/LowerCaseString.d.ts +1 -1
  27. package/lib/resolvers/scalars/index.d.ts +1 -1
  28. package/lib/resolvers/type/assortment/assortment-filter-types.js +13 -6
  29. package/lib/resolvers/type/assortment/assortment-filter-types.js.map +1 -1
  30. package/lib/resolvers/type/assortment/assortment-link-types.js +14 -6
  31. package/lib/resolvers/type/assortment/assortment-link-types.js.map +1 -1
  32. package/lib/resolvers/type/assortment/assortment-product-types.js +14 -6
  33. package/lib/resolvers/type/assortment/assortment-product-types.js.map +1 -1
  34. package/lib/resolvers/type/bookmark-types.js +6 -2
  35. package/lib/resolvers/type/bookmark-types.js.map +1 -1
  36. package/lib/resolvers/type/enrollment/enrollment-plan-tyes.js +6 -2
  37. package/lib/resolvers/type/enrollment/enrollment-plan-tyes.js.map +1 -1
  38. package/lib/resolvers/type/order/order-item-types.js +13 -6
  39. package/lib/resolvers/type/order/order-item-types.js.map +1 -1
  40. package/lib/resolvers/type/product/product-bundle-item-types.js +4 -2
  41. package/lib/resolvers/type/product/product-bundle-item-types.js.map +1 -1
  42. package/lib/resolvers/type/product/product-review-types.js +6 -2
  43. package/lib/resolvers/type/product/product-review-types.js.map +1 -1
  44. package/lib/resolvers/type/product/product-tokenized-types.js +1 -0
  45. package/lib/resolvers/type/product/product-tokenized-types.js.map +1 -1
  46. package/lib/resolvers/type/product/product-variation-assignment-types.js +4 -2
  47. package/lib/resolvers/type/product/product-variation-assignment-types.js.map +1 -1
  48. package/lib/resolvers/type/quotation-types.js +7 -3
  49. package/lib/resolvers/type/quotation-types.js.map +1 -1
  50. package/lib/resolvers/type/token-types.js +2 -1
  51. package/lib/resolvers/type/token-types.js.map +1 -1
  52. package/lib/schema/types/product/tokenized-product.js +2 -0
  53. package/lib/schema/types/product/tokenized-product.js.map +1 -1
  54. package/package.json +16 -17
  55. package/src/api-index.ts +24 -7
  56. package/src/context.ts +15 -16
  57. package/src/createERCMetadataServer.ts +8 -14
  58. package/src/createGraphQLServer.ts +35 -37
  59. package/src/errors.ts +8 -3
  60. package/src/loaders/index.ts +63 -3
  61. package/src/resolvers/index.ts +1 -1
  62. package/src/resolvers/mutations/filters/updateFilter.ts +3 -1
  63. package/src/resolvers/queries/products/product.ts +1 -1
  64. package/src/resolvers/queries/products/productCatalogPrices.ts +5 -2
  65. package/src/resolvers/queries/products/products.ts +1 -1
  66. package/src/resolvers/type/assortment/assortment-filter-types.ts +11 -6
  67. package/src/resolvers/type/assortment/assortment-link-types.ts +12 -6
  68. package/src/resolvers/type/assortment/assortment-product-types.ts +12 -6
  69. package/src/resolvers/type/bookmark-types.ts +7 -2
  70. package/src/resolvers/type/enrollment/enrollment-plan-tyes.ts +6 -2
  71. package/src/resolvers/type/order/order-item-types.ts +13 -6
  72. package/src/resolvers/type/product/product-bundle-item-types.ts +4 -2
  73. package/src/resolvers/type/product/product-review-types.ts +6 -2
  74. package/src/resolvers/type/product/product-tokenized-types.ts +1 -0
  75. package/src/resolvers/type/product/product-variation-assignment-types.ts +4 -2
  76. package/src/resolvers/type/quotation-types.ts +6 -3
  77. package/src/resolvers/type/token-types.ts +2 -1
  78. package/src/schema/types/product/tokenized-product.js +2 -0
  79. package/tsconfig.json +1 -0
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
 
@@ -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';
@@ -16,5 +16,7 @@ export default async function updateFilter(
16
16
 
17
17
  if (!(await modules.filters.filterExists({ filterId }))) throw new FilterNotFoundError({ filterId });
18
18
 
19
- return modules.filters.update(filterId, filter, context, { skipInvalidation: false }, userId);
19
+ await modules.filters.update(filterId, filter, context, { skipInvalidation: false }, userId);
20
+
21
+ return modules.filters.findFilter({ filterId });
20
22
  }
@@ -7,7 +7,7 @@ export default async function product(
7
7
  { productId, slug }: { productId?: string; slug?: string },
8
8
  { modules, userId }: Context,
9
9
  ) {
10
- log(`query product ${productId} ${slug}`, { userId });
10
+ log(`query product ${productId || slug}`, { userId });
11
11
 
12
12
  if (!productId === !slug) throw new InvalidIdError({ productId, slug });
13
13
 
@@ -5,13 +5,16 @@ import { InvalidIdError } from '../../../errors';
5
5
  export default async function productCatalogPrices(
6
6
  root: Root,
7
7
  { productId }: { productId: string },
8
- { modules, userId }: Context,
8
+ { modules, loaders, userId }: Context,
9
9
  ) {
10
10
  log(`query productCatalogPrices ${productId}`, { userId });
11
11
 
12
12
  if (!productId) throw new InvalidIdError({ productId });
13
13
 
14
- const product = await modules.products.findProduct({ productId });
14
+ const product = await loaders.productLoader.load({
15
+ productId,
16
+ includeDrafts: true,
17
+ });
15
18
  if (!product) return null;
16
19
 
17
20
  return modules.products.prices.catalogPrices(product);
@@ -12,7 +12,7 @@ export default async function products(
12
12
  { modules, userId }: Context,
13
13
  ) {
14
14
  log(
15
- `query products: ${params.limit} ${params.offset} ${
15
+ `query products: ${params.limit || 0} ${params.offset || 0} ${
16
16
  params.includeDrafts ? 'includeDrafts' : ''
17
17
  } ${params.slugs?.join(',')}`,
18
18
  { userId },
@@ -10,13 +10,18 @@ export type AssortmentFilterHelperTypes = {
10
10
  };
11
11
 
12
12
  export const AssortmentFilter: AssortmentFilterHelperTypes = {
13
- assortment: (obj, _, { modules }) =>
14
- modules.assortments.findAssortment({
13
+ assortment: async (obj, _, { loaders }) => {
14
+ const assortment = await loaders.assortmentLoader.load({
15
15
  assortmentId: obj.assortmentId,
16
- }),
16
+ includeInactive: true,
17
+ });
18
+ return assortment;
19
+ },
17
20
 
18
- filter: (obj, _, { modules }) =>
19
- modules.filters.findFilter({
21
+ filter: async (obj, _, { loaders }) => {
22
+ const filter = await loaders.filterLoader.load({
20
23
  filterId: obj.filterId,
21
- }),
24
+ });
25
+ return filter;
26
+ },
22
27
  };
@@ -9,13 +9,19 @@ export type AssortmentLinkHelperTypes = {
9
9
  };
10
10
 
11
11
  export const AssortmentLink: AssortmentLinkHelperTypes = {
12
- child: (obj, _, { modules }) =>
13
- modules.assortments.findAssortment({
12
+ child: async (obj, _, { loaders }) => {
13
+ const assortment = await loaders.assortmentLoader.load({
14
14
  assortmentId: obj.childAssortmentId,
15
- }),
15
+ includeInactive: true,
16
+ });
17
+ return assortment;
18
+ },
16
19
 
17
- parent: (obj, _, { modules }) =>
18
- modules.assortments.findAssortment({
20
+ parent: async (obj, _, { loaders }) => {
21
+ const assortment = await loaders.assortmentLoader.load({
19
22
  assortmentId: obj.parentAssortmentId,
20
- }),
23
+ includeInactive: true,
24
+ });
25
+ return assortment;
26
+ },
21
27
  };
@@ -13,13 +13,19 @@ export type AssortmentProductHelperTypes = {
13
13
  };
14
14
 
15
15
  export const AssortmentProduct: AssortmentProductHelperTypes = {
16
- assortment: (obj, _, { modules }) =>
17
- modules.assortments.findAssortment({
16
+ assortment: async (obj, _, { loaders }) => {
17
+ const assortment = await loaders.assortmentLoader.load({
18
18
  assortmentId: obj.assortmentId,
19
- }),
19
+ includeInactive: true,
20
+ });
21
+ return assortment;
22
+ },
20
23
 
21
- product: (obj, _, { modules }) =>
22
- modules.products.findProduct({
24
+ product: async (obj, _, { loaders }) => {
25
+ const product = await loaders.productLoader.load({
23
26
  productId: obj.productId,
24
- }),
27
+ includeDrafts: true,
28
+ });
29
+ return product;
30
+ },
25
31
  };
@@ -11,9 +11,14 @@ export interface BookmarkHelperTypes {
11
11
  }
12
12
 
13
13
  export const Bookmark: BookmarkHelperTypes = {
14
- product: async (obj, _, { modules }) => {
15
- return modules.products.findProduct({ productId: obj.productId });
14
+ product: async (obj, _, { loaders }) => {
15
+ const product = await loaders.productLoader.load({
16
+ productId: obj.productId,
17
+ includeDrafts: true,
18
+ });
19
+ return product;
16
20
  },
21
+
17
22
  user: async (obj, _, { modules }) => {
18
23
  return modules.users.findUserById(obj.userId);
19
24
  },
@@ -9,7 +9,11 @@ type EnrollmentPlanHelperTypes = {
9
9
  };
10
10
 
11
11
  export const EnrollmentPlan: EnrollmentPlanHelperTypes = {
12
- product: async (plan, _, { modules }) => {
13
- return modules.products.findProduct({ productId: plan.productId });
12
+ product: async (plan, _, { loaders }) => {
13
+ const product = await loaders.productLoader.load({
14
+ productId: plan.productId,
15
+ includeDrafts: true,
16
+ });
17
+ return product;
14
18
  },
15
19
  };
@@ -57,7 +57,7 @@ export const OrderItem: OrderItemHelperTypes = {
57
57
  return [];
58
58
  },
59
59
 
60
- dispatches: async (obj, _, { modules }) => {
60
+ dispatches: async (obj, _, { modules, loaders }) => {
61
61
  const scheduling = obj.scheduling || [];
62
62
  const order = await modules.orders.findOrder({ orderId: obj.orderId });
63
63
  const { countryCode, userId } = order;
@@ -68,8 +68,9 @@ export const OrderItem: OrderItemHelperTypes = {
68
68
  const deliveryProvider = await modules.delivery.findProvider({
69
69
  deliveryProviderId: orderDelivery.deliveryProviderId,
70
70
  });
71
- const product = await modules.products.findProduct({
71
+ const product = await loaders.productLoader.load({
72
72
  productId: obj.productId,
73
+ includeDrafts: true,
73
74
  });
74
75
 
75
76
  return Promise.all(
@@ -99,14 +100,20 @@ export const OrderItem: OrderItemHelperTypes = {
99
100
  return modules.orders.findOrder({ orderId: obj.orderId });
100
101
  },
101
102
 
102
- originalProduct: async (obj, _, { modules }) => {
103
- return modules.products.findProduct({
103
+ originalProduct: async (obj, _, { loaders }) => {
104
+ const product = await loaders.productLoader.load({
104
105
  productId: obj.originalProductId,
106
+ includeDrafts: true,
105
107
  });
108
+ return product;
106
109
  },
107
110
 
108
- product: async (obj, _, { modules }) => {
109
- return modules.products.findProduct({ productId: obj.productId });
111
+ product: async (obj, _, { loaders }) => {
112
+ const product = await loaders.productLoader.load({
113
+ productId: obj.productId,
114
+ includeDrafts: true,
115
+ });
116
+ return product;
110
117
  },
111
118
 
112
119
  quotation: async (obj, _, { modules }) => {
@@ -1,9 +1,11 @@
1
1
  import { ProductBundleItemHelperTypes } from '@unchainedshop/types/products';
2
2
 
3
3
  export const ProductBundleItem: ProductBundleItemHelperTypes = {
4
- product: async (productItem, _, { modules }) => {
5
- return modules.products.findProduct({
4
+ product: async (productItem, _, { loaders }) => {
5
+ const product = await loaders.productLoader.load({
6
6
  productId: productItem.productId,
7
+ includeDrafts: true,
7
8
  });
9
+ return product;
8
10
  },
9
11
  };
@@ -20,8 +20,12 @@ export const ProductReview: ProductReviewHelperTypes = {
20
20
  return modules.users.findUserById(obj.authorId);
21
21
  },
22
22
 
23
- product: async (obj, _, { modules }) => {
24
- return modules.products.findProduct({ productId: obj.productId });
23
+ product: async (review, _, { loaders }) => {
24
+ const product = await loaders.productLoader.load({
25
+ productId: review.productId,
26
+ includeDrafts: true,
27
+ });
28
+ return product;
25
29
  },
26
30
 
27
31
  ownVotes: async (obj, _, { modules, userId }) => {
@@ -14,6 +14,7 @@ export const TokenizedProduct: TokenizedProductHelperTypes = {
14
14
  return {
15
15
  supply: product.tokenization.supply,
16
16
  tokenId: product.tokenization.tokenId,
17
+ ercMetadataProperties: product.tokenization.ercMetadataProperties,
17
18
  };
18
19
  },
19
20
 
@@ -11,9 +11,11 @@ export const ProductVariationAssignment: ProductVariationAssignmentHelperTypes =
11
11
  product,
12
12
  }));
13
13
  },
14
- product: async ({ assignment }, _, { modules }) => {
15
- return modules.products.findProduct({
14
+ product: async ({ assignment }, _, { loaders }) => {
15
+ const product = await loaders.productLoader.load({
16
16
  productId: assignment.productId,
17
+ includeDrafts: true,
17
18
  });
19
+ return product;
18
20
  },
19
21
  };
@@ -24,10 +24,13 @@ export const Quotation: QuotationHelperTypes = {
24
24
  isExpired: (obj, { referenceDate }, { modules }) =>
25
25
  modules.quotations.isExpired(obj, { referenceDate }),
26
26
 
27
- product: (obj, _, { modules }) =>
28
- modules.products.findProduct({
27
+ product: async (obj, _, { loaders }) => {
28
+ const product = await loaders.productLoader.load({
29
29
  productId: obj.productId,
30
- }),
30
+ includeDrafts: true,
31
+ });
32
+ return product;
33
+ },
31
34
 
32
35
  status: (obj, _, { modules }) => modules.quotations.normalizedStatus(obj),
33
36
 
@@ -46,8 +46,9 @@ export const Token: TokenHelperTypes = {
46
46
  const { modules } = context;
47
47
  const product = await modules.products.findProduct({ productId: token.productId });
48
48
  const ercMetadata = await modules.warehousing.tokenMetadata(
49
- token,
49
+ token.chainTokenId,
50
50
  {
51
+ token,
51
52
  product,
52
53
  referenceDate: new Date(),
53
54
  },
@@ -5,6 +5,7 @@ export default [
5
5
  contractStandard: SmartContractStandard!
6
6
  tokenId: String
7
7
  supply: Int
8
+ ercMetadataProperties: JSON
8
9
  }
9
10
 
10
11
  enum SmartContractStandard {
@@ -15,6 +16,7 @@ export default [
15
16
  type ContractConfiguration {
16
17
  tokenId: String
17
18
  supply: Int
19
+ ercMetadataProperties: JSON
18
20
  }
19
21
 
20
22
  """
package/tsconfig.json CHANGED
@@ -4,6 +4,7 @@
4
4
  "allowSyntheticDefaultImports": true,
5
5
  "declaration": true,
6
6
  "esModuleInterop": true,
7
+ "resolveJsonModule": true,
7
8
  "experimentalDecorators": true,
8
9
  "forceConsistentCasingInFileNames": true,
9
10
  "lib": [