@unchainedshop/api 3.0.0-rc.11 → 3.0.0-rc.13

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 (68) hide show
  1. package/lib/context.d.ts +2 -1
  2. package/lib/context.d.ts.map +1 -1
  3. package/lib/loaders/index.d.ts +103 -59
  4. package/lib/loaders/index.d.ts.map +1 -1
  5. package/lib/loaders/index.js +74 -45
  6. package/lib/loaders/index.js.map +1 -1
  7. package/lib/resolvers/mutations/assortments/removeAssortmentProduct.js +1 -1
  8. package/lib/resolvers/mutations/assortments/removeAssortmentProduct.js.map +1 -1
  9. package/lib/resolvers/mutations/products/removeProductReviewVote.d.ts +1 -1
  10. package/lib/resolvers/mutations/products/removeProductReviewVote.d.ts.map +1 -1
  11. package/lib/resolvers/queries/index.d.ts +1 -0
  12. package/lib/resolvers/queries/index.d.ts.map +1 -1
  13. package/lib/resolvers/queries/index.js +2 -0
  14. package/lib/resolvers/queries/index.js.map +1 -1
  15. package/lib/resolvers/queries/warehousing/tokens.d.ts +2 -1
  16. package/lib/resolvers/queries/warehousing/tokens.d.ts.map +1 -1
  17. package/lib/resolvers/queries/warehousing/tokens.js +2 -2
  18. package/lib/resolvers/queries/warehousing/tokens.js.map +1 -1
  19. package/lib/resolvers/queries/warehousing/tokensCount.d.ts +5 -0
  20. package/lib/resolvers/queries/warehousing/tokensCount.d.ts.map +1 -0
  21. package/lib/resolvers/queries/warehousing/tokensCount.js +6 -0
  22. package/lib/resolvers/queries/warehousing/tokensCount.js.map +1 -0
  23. package/lib/resolvers/type/assortment/assortment-path-link-types.d.ts +7 -9
  24. package/lib/resolvers/type/assortment/assortment-path-link-types.d.ts.map +1 -1
  25. package/lib/resolvers/type/assortment/assortment-path-link-types.js +9 -7
  26. package/lib/resolvers/type/assortment/assortment-path-link-types.js.map +1 -1
  27. package/lib/resolvers/type/assortment/assortment-types.d.ts +1 -1
  28. package/lib/resolvers/type/assortment/assortment-types.d.ts.map +1 -1
  29. package/lib/resolvers/type/assortment/assortment-types.js +9 -2
  30. package/lib/resolvers/type/assortment/assortment-types.js.map +1 -1
  31. package/lib/resolvers/type/index.d.ts +14 -8
  32. package/lib/resolvers/type/index.d.ts.map +1 -1
  33. package/lib/resolvers/type/product/product-bundle-types.d.ts +1 -1
  34. package/lib/resolvers/type/product/product-bundle-types.d.ts.map +1 -1
  35. package/lib/resolvers/type/product/product-configurable-types.d.ts +1 -1
  36. package/lib/resolvers/type/product/product-configurable-types.d.ts.map +1 -1
  37. package/lib/resolvers/type/product/product-plan-types.d.ts +1 -1
  38. package/lib/resolvers/type/product/product-plan-types.d.ts.map +1 -1
  39. package/lib/resolvers/type/product/product-simple-types.d.ts +1 -1
  40. package/lib/resolvers/type/product/product-simple-types.d.ts.map +1 -1
  41. package/lib/resolvers/type/product/product-tokenized-types.d.ts +1 -1
  42. package/lib/resolvers/type/product/product-tokenized-types.d.ts.map +1 -1
  43. package/lib/resolvers/type/product/product-types.d.ts +1 -1
  44. package/lib/resolvers/type/product/product-types.d.ts.map +1 -1
  45. package/lib/resolvers/type/product/product-types.js +9 -2
  46. package/lib/resolvers/type/product/product-types.js.map +1 -1
  47. package/lib/resolvers/type/product/product-variation-assignment-vector.d.ts.map +1 -1
  48. package/lib/resolvers/type/product/product-variation-assignment-vector.js +4 -1
  49. package/lib/resolvers/type/product/product-variation-assignment-vector.js.map +1 -1
  50. package/lib/resolvers/type/product/product-variation-types.d.ts.map +1 -1
  51. package/lib/resolvers/type/product/product-variation-types.js +5 -2
  52. package/lib/resolvers/type/product/product-variation-types.js.map +1 -1
  53. package/lib/schema/query.d.ts.map +1 -1
  54. package/lib/schema/query.js +6 -1
  55. package/lib/schema/query.js.map +1 -1
  56. package/package.json +6 -6
  57. package/src/context.ts +1 -1
  58. package/src/loaders/index.ts +202 -188
  59. package/src/resolvers/mutations/assortments/removeAssortmentProduct.ts +1 -1
  60. package/src/resolvers/queries/index.ts +2 -0
  61. package/src/resolvers/queries/warehousing/tokens.ts +3 -1
  62. package/src/resolvers/queries/warehousing/tokensCount.ts +12 -0
  63. package/src/resolvers/type/assortment/assortment-path-link-types.ts +14 -19
  64. package/src/resolvers/type/assortment/assortment-types.ts +17 -5
  65. package/src/resolvers/type/product/product-types.ts +17 -5
  66. package/src/resolvers/type/product/product-variation-assignment-vector.ts +4 -1
  67. package/src/resolvers/type/product/product-variation-types.ts +5 -2
  68. package/src/schema/query.ts +6 -1
@@ -13,48 +13,6 @@ import {
13
13
  } from '@unchainedshop/core-assortments';
14
14
  import { File } from '@unchainedshop/core-files';
15
15
 
16
- export interface UnchainedLoaders {
17
- loaders: {
18
- productLoader: InstanceType<typeof DataLoader<{ productId: string }, Product>>;
19
- productLoaderBySKU: InstanceType<typeof DataLoader<{ sku: string }, Product>>;
20
- productTextLoader: InstanceType<
21
- typeof DataLoader<{ productId: string; locale: string }, ProductText>
22
- >;
23
- productMediaTextLoader: InstanceType<
24
- typeof DataLoader<{ productMediaId: string; locale: string }, ProductMediaText>
25
- >;
26
-
27
- fileLoader: InstanceType<typeof DataLoader<{ fileId: string }, File>>;
28
-
29
- filterLoader: InstanceType<typeof DataLoader<{ filterId: string }, Filter>>;
30
- filterTextLoader: InstanceType<
31
- typeof DataLoader<{ filterId: string; filterOptionValue?: string; locale: string }, FilterText>
32
- >;
33
-
34
- assortmentLoader: InstanceType<typeof DataLoader<{ assortmentId: string }, Assortment>>;
35
- assortmentTextLoader: InstanceType<
36
- typeof DataLoader<{ assortmentId: string; locale: string }, AssortmentText>
37
- >;
38
- assortmentLinkLoader: InstanceType<
39
- typeof DataLoader<{ parentAssortmentId: string; childAssortmentId: string }, AssortmentLink>
40
- >;
41
- assortmentLinksLoader: InstanceType<
42
- typeof DataLoader<{ parentAssortmentId?: string; assortmentId?: string }, AssortmentLink[]>
43
- >;
44
- assortmentProductLoader: InstanceType<
45
- typeof DataLoader<{ assortmentId: string; productId: string }, AssortmentProduct>
46
- >;
47
- assortmentMediaTextLoader: InstanceType<
48
- typeof DataLoader<{ assortmentMediaId: string; locale: string }, AssortmentMediaText>
49
- >;
50
-
51
- productMediasLoader: InstanceType<typeof DataLoader<{ productId?: string }, ProductMedia[]>>;
52
- assortmentMediasLoader: InstanceType<
53
- typeof DataLoader<{ assortmentId?: string }, AssortmentMediaType[]>
54
- >;
55
- };
56
- }
57
-
58
16
  function getLocaleStrings(locale: string) {
59
17
  const localeObj = new Intl.Locale(locale);
60
18
  return [
@@ -67,9 +25,9 @@ function getLocaleStrings(locale: string) {
67
25
  ];
68
26
  }
69
27
 
70
- const loaders = async (unchainedAPI: UnchainedCore): Promise<UnchainedLoaders['loaders']> => {
28
+ const loaders = async (unchainedAPI: UnchainedCore) => {
71
29
  return {
72
- assortmentLoader: new DataLoader(async (queries) => {
30
+ assortmentLoader: new DataLoader<{ assortmentId: string }, Assortment>(async (queries) => {
73
31
  const assortmentIds = [...new Set(queries.map((q) => q.assortmentId).filter(Boolean))];
74
32
 
75
33
  const assortments = await unchainedAPI.modules.assortments.findAssortments({
@@ -85,33 +43,38 @@ const loaders = async (unchainedAPI: UnchainedCore): Promise<UnchainedLoaders['l
85
43
  return queries.map((q) => assortmentMap[q.assortmentId]);
86
44
  }),
87
45
 
88
- assortmentTextLoader: new DataLoader(async (queries) => {
89
- const assortmentIds = [...new Set(queries.map((q) => q.assortmentId).filter(Boolean))];
46
+ assortmentTextLoader: new DataLoader<{ assortmentId: string; locale: string }, AssortmentText>(
47
+ async (queries) => {
48
+ const assortmentIds = [...new Set(queries.map((q) => q.assortmentId).filter(Boolean))];
90
49
 
91
- const texts = await unchainedAPI.modules.assortments.texts.findTexts(
92
- { assortmentId: { $in: assortmentIds } },
93
- {
94
- sort: {
95
- assortmentId: 1,
50
+ const texts = await unchainedAPI.modules.assortments.texts.findTexts(
51
+ { assortmentId: { $in: assortmentIds } },
52
+ {
53
+ sort: {
54
+ assortmentId: 1,
55
+ },
96
56
  },
97
- },
98
- );
99
-
100
- const queryLocales = [...new Set(queries.map((q) => q.locale.toLowerCase()))];
101
- const textsMap = {};
102
- const localeMap = Object.fromEntries(
103
- queryLocales.flatMap((queryLocale) => {
104
- return getLocaleStrings(queryLocale).map((locale) => [locale, queryLocale]);
105
- }),
106
- );
107
- for (const text of texts) {
108
- const locale = localeMap[text.locale.toLowerCase()];
109
- textsMap[`${locale}:${text.assortmentId}`] = text;
110
- }
111
- return queries.map((q) => textsMap[`${q.locale.toLowerCase()}:${q.assortmentId}`]);
112
- }),
113
-
114
- assortmentMediaTextLoader: new DataLoader(async (queries) => {
57
+ );
58
+
59
+ const queryLocales = [...new Set(queries.map((q) => q.locale.toLowerCase()))];
60
+ const textsMap = {};
61
+ const localeMap = Object.fromEntries(
62
+ queryLocales.flatMap((queryLocale) => {
63
+ return getLocaleStrings(queryLocale).map((locale) => [locale, queryLocale]);
64
+ }),
65
+ );
66
+ for (const text of texts) {
67
+ const locale = localeMap[text.locale.toLowerCase()];
68
+ textsMap[locale + text.assortmentId] = text;
69
+ }
70
+ return queries.map((q) => textsMap[q.locale.toLowerCase() + q.assortmentId]);
71
+ },
72
+ ),
73
+
74
+ assortmentMediaTextLoader: new DataLoader<
75
+ { assortmentMediaId: string; locale: string },
76
+ AssortmentMediaText
77
+ >(async (queries) => {
115
78
  const assortmentMediaIds = [...new Set(queries.map((q) => q.assortmentMediaId).filter(Boolean))];
116
79
 
117
80
  const texts = await unchainedAPI.modules.assortments.media.texts.findMediaTexts(
@@ -132,97 +95,141 @@ const loaders = async (unchainedAPI: UnchainedCore): Promise<UnchainedLoaders['l
132
95
  );
133
96
  for (const text of texts) {
134
97
  const locale = localeMap[text.locale.toLowerCase()];
135
- textsMap[`${locale}:${text.assortmentMediaId}`] = text;
98
+ textsMap[locale + text.assortmentMediaId] = text;
136
99
  }
137
- return queries.map((q) => textsMap[`${q.locale.toLowerCase()}:${q.assortmentMediaId}`]);
100
+ return queries.map((q) => textsMap[q.locale.toLowerCase() + q.assortmentMediaId]);
138
101
  }),
139
102
 
140
- assortmentMediasLoader: new DataLoader(async (queries) => {
141
- const assortmentIds = [...new Set(queries.map((q) => q.assortmentId).filter(Boolean))];
142
- const assortmentMediaItems = await unchainedAPI.modules.assortments.media.findAssortmentMedias({
143
- assortmentId: { $in: assortmentIds },
144
- });
103
+ assortmentMediasLoader: new DataLoader<{ assortmentId?: string }, AssortmentMediaType[]>(
104
+ async (queries) => {
105
+ const assortmentIds = [...new Set(queries.map((q) => q.assortmentId).filter(Boolean))];
106
+ const assortmentMediaItems = await unchainedAPI.modules.assortments.media.findAssortmentMedias({
107
+ assortmentId: { $in: assortmentIds },
108
+ });
145
109
 
146
- const assortmentMediaMap = {};
147
- for (const assortmentMedia of assortmentMediaItems) {
148
- if (!assortmentMediaMap[assortmentMedia.assortmentId]) {
149
- assortmentMediaMap[assortmentMedia.assortmentId] = [assortmentMedia];
150
- } else {
151
- assortmentMediaMap[assortmentMedia.assortmentId].push(assortmentMedia);
110
+ const assortmentMediaMap = {};
111
+ for (const assortmentMedia of assortmentMediaItems) {
112
+ if (!assortmentMediaMap[assortmentMedia.assortmentId]) {
113
+ assortmentMediaMap[assortmentMedia.assortmentId] = [assortmentMedia];
114
+ } else {
115
+ assortmentMediaMap[assortmentMedia.assortmentId].push(assortmentMedia);
116
+ }
152
117
  }
153
- }
154
- return queries.map((q) => assortmentMediaMap[q.assortmentId] || []);
155
- }),
156
-
157
- assortmentLinkLoader: new DataLoader(async (queries) => {
118
+ return queries.map((q) => assortmentMediaMap[q.assortmentId] || []);
119
+ },
120
+ ),
121
+
122
+ assortmentLinkLoader: new DataLoader<
123
+ { parentAssortmentId: string; childAssortmentId: string },
124
+ AssortmentLink
125
+ >(async (queries) => {
158
126
  const parentAssortmentIds = [...new Set(queries.map((q) => q.parentAssortmentId).filter(Boolean))];
159
127
 
160
128
  const links = await unchainedAPI.modules.assortments.links.findLinks({
161
129
  parentAssortmentIds,
162
130
  });
163
131
 
164
- // TODO: Optimize
132
+ const assortmentLinkMap = {};
133
+ for (const link of links) {
134
+ if (!assortmentLinkMap[link.parentAssortmentId]) {
135
+ assortmentLinkMap[link.parentAssortmentId] = [link];
136
+ } else {
137
+ assortmentLinkMap[link.parentAssortmentId].push(link);
138
+ }
139
+ }
140
+
165
141
  return queries.map((q) => {
166
- return links.find((link) => {
167
- if (link.parentAssortmentId !== q.parentAssortmentId) return false;
168
- if (q.childAssortmentId && link.childAssortmentId !== q.childAssortmentId) return false;
169
- return true;
170
- });
142
+ if (q.childAssortmentId) {
143
+ return assortmentLinkMap[q.parentAssortmentId].find(
144
+ (link) => link.childAssortmentId === q.childAssortmentId,
145
+ );
146
+ }
147
+ return assortmentLinkMap[q.parentAssortmentId][0];
171
148
  });
172
149
  }),
173
150
 
174
- assortmentLinksLoader: new DataLoader(async (queries) => {
175
- const parentAssortmentIds = [
176
- ...new Set(queries.flatMap((q) => q.parentAssortmentId).filter(Boolean)),
177
- ];
178
- const assortmentIds = [...new Set(queries.flatMap((q) => q.assortmentId).filter(Boolean))];
179
-
180
- const linksByParentAssortmentId =
181
- parentAssortmentIds?.length &&
182
- (await unchainedAPI.modules.assortments.links.findLinks({
183
- parentAssortmentIds,
184
- }));
185
- const linksByAssortmentId =
186
- assortmentIds?.length &&
187
- (await unchainedAPI.modules.assortments.links.findLinks({
188
- assortmentIds,
189
- }));
190
-
191
- // TODO: Optimize
151
+ assortmentLinksLoader: new DataLoader<
152
+ { parentAssortmentId?: string; childAssortmentId?: string; assortmentId?: string },
153
+ AssortmentLink[]
154
+ >(async (queries) => {
155
+ const parentAssortmentIds = queries.flatMap((q) => q.parentAssortmentId).filter(Boolean);
156
+ const childAssortmentIds = queries.flatMap((q) => q.childAssortmentId).filter(Boolean);
157
+ const assortmentIds = queries.flatMap((q) => q.assortmentId).filter(Boolean);
158
+
159
+ const allLinks = await unchainedAPI.modules.assortments.links.findLinks({
160
+ assortmentIds: [...new Set([...parentAssortmentIds, ...childAssortmentIds, ...assortmentIds])],
161
+ });
162
+
163
+ const parentAssortmentLinkMap = {};
164
+ const childAssortmentLinkMap = {};
165
+
166
+ for (const link of allLinks) {
167
+ if (!parentAssortmentLinkMap[link.parentAssortmentId]) {
168
+ parentAssortmentLinkMap[link.parentAssortmentId] = [link];
169
+ } else {
170
+ parentAssortmentLinkMap[link.parentAssortmentId].push(link);
171
+ }
172
+
173
+ if (!childAssortmentLinkMap[link.childAssortmentId]) {
174
+ childAssortmentLinkMap[link.childAssortmentId] = [link];
175
+ } else {
176
+ childAssortmentLinkMap[link.childAssortmentId].push(link);
177
+ }
178
+ }
179
+
192
180
  return queries.map((q) => {
193
181
  if (q.parentAssortmentId) {
194
- return linksByParentAssortmentId.filter(
195
- (link) => link.parentAssortmentId === q.parentAssortmentId,
196
- );
197
- }
198
- if (q.assortmentId) {
199
- return linksByAssortmentId.filter(
200
- (link) =>
201
- link.parentAssortmentId === q.assortmentId || link.childAssortmentId === q.assortmentId,
202
- );
182
+ return parentAssortmentLinkMap[q.parentAssortmentId] || [];
183
+ } else if (q.childAssortmentId) {
184
+ return childAssortmentLinkMap[q.childAssortmentId] || [];
203
185
  }
204
- return [];
186
+ return [
187
+ ...(parentAssortmentLinkMap[q.assortmentId] || []),
188
+ ...(childAssortmentLinkMap[q.assortmentId] || []),
189
+ ];
205
190
  });
206
191
  }),
207
192
 
208
- assortmentProductLoader: new DataLoader(async (queries) => {
193
+ assortmentProductLoader: new DataLoader<
194
+ { assortmentId: string; productId: string },
195
+ AssortmentProduct
196
+ >(async (queries) => {
209
197
  const assortmentIds = [...new Set(queries.map((q) => q.assortmentId).filter(Boolean))];
210
198
 
211
- const assortmentProducts = await unchainedAPI.modules.assortments.products.findProducts({
199
+ const assortmentProducts = await unchainedAPI.modules.assortments.products.findAssortmentProducts({
212
200
  assortmentIds,
213
201
  });
214
202
 
215
- // TODO: Optimize
216
- return queries.map((q) => {
217
- return assortmentProducts.find((assortmentProduct) => {
218
- if (assortmentProduct.assortmentId !== q.assortmentId) return false;
219
- if (assortmentProduct.productId !== q.productId) return false;
220
- return true;
221
- });
222
- });
203
+ const assortmentProductMap = {};
204
+ for (const assortmentProduct of assortmentProducts) {
205
+ assortmentProductMap[assortmentProduct.assortmentId + assortmentProduct.productId] =
206
+ assortmentProduct;
207
+ }
208
+ return queries.map((q) => assortmentProductMap[q.assortmentId + q.productId]);
223
209
  }),
224
210
 
225
- filterLoader: new DataLoader(async (queries) => {
211
+ assortmentProductsLoader: new DataLoader<{ productId: string }, AssortmentProduct[]>(
212
+ async (queries) => {
213
+ const productIds = [...new Set(queries.map((q) => q.productId).filter(Boolean))];
214
+
215
+ const assortmentProducts =
216
+ await unchainedAPI.modules.assortments.products.findAssortmentProducts({
217
+ productIds,
218
+ });
219
+
220
+ const assortmentProductsMap = {};
221
+ for (const assortmentProduct of assortmentProducts) {
222
+ if (!assortmentProductsMap[assortmentProduct.productId]) {
223
+ assortmentProductsMap[assortmentProduct.productId] = [assortmentProduct];
224
+ } else {
225
+ assortmentProductsMap[assortmentProduct.productId].push(assortmentProduct);
226
+ }
227
+ }
228
+ return queries.map((q) => assortmentProductsMap[q.productId] || []);
229
+ },
230
+ ),
231
+
232
+ filterLoader: new DataLoader<{ filterId: string }, Filter>(async (queries) => {
226
233
  const filterIds = [...new Set(queries.map((q) => q.filterId).filter(Boolean))];
227
234
 
228
235
  const filters = await unchainedAPI.modules.filters.findFilters({
@@ -238,7 +245,10 @@ const loaders = async (unchainedAPI: UnchainedCore): Promise<UnchainedLoaders['l
238
245
  return queries.map((q) => filterMap[q.filterId]);
239
246
  }),
240
247
 
241
- filterTextLoader: new DataLoader(async (queries) => {
248
+ filterTextLoader: new DataLoader<
249
+ { filterId: string; filterOptionValue?: string; locale: string },
250
+ FilterText
251
+ >(async (queries) => {
242
252
  const filterIds = [...new Set(queries.map((q) => q.filterId).filter(Boolean))];
243
253
 
244
254
  const texts = await unchainedAPI.modules.filters.texts.findTexts(
@@ -259,14 +269,12 @@ const loaders = async (unchainedAPI: UnchainedCore): Promise<UnchainedLoaders['l
259
269
  );
260
270
  for (const text of texts) {
261
271
  const locale = localeMap[text.locale.toLowerCase()];
262
- textsMap[`${locale}:${text.filterId}:${text.filterOptionValue}`] = text;
272
+ textsMap[locale + text.filterId + text.filterOptionValue] = text;
263
273
  }
264
- return queries.map(
265
- (q) => textsMap[`${q.locale.toLowerCase()}:${q.filterId}:${q.filterOptionValue}`],
266
- );
274
+ return queries.map((q) => textsMap[q.locale.toLowerCase() + q.filterId + q.filterOptionValue]);
267
275
  }),
268
276
 
269
- productLoader: new DataLoader(async (queries) => {
277
+ productLoader: new DataLoader<{ productId: string }, Product>(async (queries) => {
270
278
  const productIds = [...new Set(queries.map((q) => q.productId).filter(Boolean))]; // you don't need lodash, _.unique my ass
271
279
 
272
280
  const products = await unchainedAPI.modules.products.findProducts({
@@ -284,7 +292,7 @@ const loaders = async (unchainedAPI: UnchainedCore): Promise<UnchainedLoaders['l
284
292
  return queries.map((q) => productMap[q.productId]);
285
293
  }),
286
294
 
287
- productLoaderBySKU: new DataLoader(async (queries) => {
295
+ productLoaderBySKU: new DataLoader<{ sku: string }, Product>(async (queries) => {
288
296
  const skus = [...new Set(queries.map((q) => q.sku).filter(Boolean))]; // you don't need lodash, _.unique my ass
289
297
 
290
298
  const products = await unchainedAPI.modules.products.findProducts({
@@ -302,57 +310,61 @@ const loaders = async (unchainedAPI: UnchainedCore): Promise<UnchainedLoaders['l
302
310
  return queries.map((q) => productMap[q.sku]);
303
311
  }),
304
312
 
305
- productTextLoader: new DataLoader(async (queries) => {
306
- const productIds = [...new Set(queries.map((q) => q.productId))].filter(Boolean);
307
- const texts = await unchainedAPI.modules.products.texts.findTexts(
308
- { productId: { $in: productIds } },
309
- {
310
- sort: {
311
- productId: 1,
313
+ productTextLoader: new DataLoader<{ productId: string; locale: string }, ProductText>(
314
+ async (queries) => {
315
+ const productIds = [...new Set(queries.map((q) => q.productId))].filter(Boolean);
316
+ const texts = await unchainedAPI.modules.products.texts.findTexts(
317
+ { productId: { $in: productIds } },
318
+ {
319
+ sort: {
320
+ productId: 1,
321
+ },
312
322
  },
313
- },
314
- );
315
- const queryLocales = [...new Set(queries.map((q) => q.locale.toLowerCase()))];
316
- const textsMap = {};
317
- const localeMap = Object.fromEntries(
318
- queryLocales.flatMap((queryLocale) => {
319
- return getLocaleStrings(queryLocale).map((locale) => [locale, queryLocale]);
320
- }),
321
- );
322
- for (const text of texts) {
323
- const locale = localeMap[text.locale.toLowerCase()];
324
- textsMap[`${locale}:${text.productId}`] = text;
325
- }
326
- return queries.map((q) => textsMap[`${q.locale.toLowerCase()}:${q.productId}`]);
327
- }),
328
-
329
- productMediaTextLoader: new DataLoader(async (queries) => {
330
- const productMediaIds = [...new Set(queries.map((q) => q.productMediaId).filter(Boolean))];
331
-
332
- const texts = await unchainedAPI.modules.products.media.texts.findMediaTexts(
333
- { productMediaId: { $in: productMediaIds } },
334
- {
335
- sort: {
336
- productMediaId: 1,
323
+ );
324
+ const queryLocales = [...new Set(queries.map((q) => q.locale.toLowerCase()))];
325
+ const textsMap = {};
326
+ const localeMap = Object.fromEntries(
327
+ queryLocales.flatMap((queryLocale) => {
328
+ return getLocaleStrings(queryLocale).map((locale) => [locale, queryLocale]);
329
+ }),
330
+ );
331
+ for (const text of texts) {
332
+ const locale = localeMap[text.locale.toLowerCase()];
333
+ textsMap[locale + text.productId] = text;
334
+ }
335
+ return queries.map((q) => textsMap[q.locale.toLowerCase() + q.productId]);
336
+ },
337
+ ),
338
+
339
+ productMediaTextLoader: new DataLoader<{ productMediaId: string; locale: string }, ProductMediaText>(
340
+ async (queries) => {
341
+ const productMediaIds = [...new Set(queries.map((q) => q.productMediaId).filter(Boolean))];
342
+
343
+ const texts = await unchainedAPI.modules.products.media.texts.findMediaTexts(
344
+ { productMediaId: { $in: productMediaIds } },
345
+ {
346
+ sort: {
347
+ productMediaId: 1,
348
+ },
337
349
  },
338
- },
339
- );
340
-
341
- const queryLocales = [...new Set(queries.map((q) => q.locale.toLowerCase()))];
342
- const textsMap = {};
343
- const localeMap = Object.fromEntries(
344
- queryLocales.flatMap((queryLocale) => {
345
- return getLocaleStrings(queryLocale).map((locale) => [locale, queryLocale]);
346
- }),
347
- );
348
- for (const text of texts) {
349
- const locale = localeMap[text.locale.toLowerCase()];
350
- textsMap[`${locale}:${text.productMediaId}`] = text;
351
- }
352
- return queries.map((q) => textsMap[`${q.locale.toLowerCase()}:${q.productMediaId}`]);
353
- }),
350
+ );
351
+
352
+ const queryLocales = [...new Set(queries.map((q) => q.locale.toLowerCase()))];
353
+ const textsMap = {};
354
+ const localeMap = Object.fromEntries(
355
+ queryLocales.flatMap((queryLocale) => {
356
+ return getLocaleStrings(queryLocale).map((locale) => [locale, queryLocale]);
357
+ }),
358
+ );
359
+ for (const text of texts) {
360
+ const locale = localeMap[text.locale.toLowerCase()];
361
+ textsMap[locale + text.productMediaId] = text;
362
+ }
363
+ return queries.map((q) => textsMap[q.locale.toLowerCase() + q.productMediaId]);
364
+ },
365
+ ),
354
366
 
355
- productMediasLoader: new DataLoader(async (queries) => {
367
+ productMediasLoader: new DataLoader<{ productId?: string }, ProductMedia[]>(async (queries) => {
356
368
  const productIds = [...new Set(queries.map((q) => q.productId).filter(Boolean))];
357
369
  const productMediaItems = await unchainedAPI.modules.products.media.findProductMedias({
358
370
  productId: { $in: productIds },
@@ -369,7 +381,7 @@ const loaders = async (unchainedAPI: UnchainedCore): Promise<UnchainedLoaders['l
369
381
  return queries.map((q) => productMediaMap[q.productId] || []);
370
382
  }),
371
383
 
372
- fileLoader: new DataLoader(async (queries) => {
384
+ fileLoader: new DataLoader<{ fileId: string }, File>(async (queries) => {
373
385
  const fileIds = [...new Set(queries.map((q) => q.fileId).filter(Boolean))]; // you don't need lodash, _.unique my ass
374
386
 
375
387
  const files = await unchainedAPI.modules.files.findFiles({
@@ -386,4 +398,6 @@ const loaders = async (unchainedAPI: UnchainedCore): Promise<UnchainedLoaders['l
386
398
  };
387
399
  };
388
400
 
401
+ export type UnchainedLoaders = Awaited<ReturnType<typeof loaders>>;
402
+
389
403
  export default loaders;
@@ -13,7 +13,7 @@ export default async function removeAssortmentProduct(
13
13
 
14
14
  if (!assortmentProductId) throw new InvalidIdError({ assortmentProductId });
15
15
 
16
- const assortmentProduct = await modules.assortments.products.findProduct({
16
+ const assortmentProduct = await modules.assortments.products.findAssortmentProduct({
17
17
  assortmentProductId,
18
18
  });
19
19
  if (!assortmentProduct) throw new AssortmentProductNotFoundError({ assortmentProductId });
@@ -63,6 +63,7 @@ import warehousingProviders from './warehousing/warehousingProviders.js';
63
63
  import warehousingProvidersCount from './warehousing/warehousingProvidersCount.js';
64
64
  import token from './warehousing/token.js';
65
65
  import tokens from './warehousing/tokens.js';
66
+ import tokensCount from './warehousing/tokensCount.js';
66
67
  import work from './worker/work.js';
67
68
  import workQueue from './worker/workQueue.js';
68
69
  import workStatistics from './worker/workStatistics.js';
@@ -104,6 +105,7 @@ export default {
104
105
  warehousingInterfaces: acl(actions.viewWarehousingInterfaces)(warehousingInterfaces),
105
106
  token: acl(actions.viewToken)(token),
106
107
  tokens: acl(actions.viewTokens)(tokens),
108
+ tokensCount: acl(actions.viewTokens)(tokensCount),
107
109
  translatedProductTexts: acl(actions.viewTranslations)(translatedProductTexts),
108
110
  translatedProductMediaTexts: acl(actions.viewTranslations)(translatedProductMediaTexts),
109
111
  translatedProductVariationTexts: acl(actions.viewTranslations)(translatedProductVariationTexts),
@@ -4,15 +4,17 @@ import { Context } from '../../../context.js';
4
4
  export default async function tokens(
5
5
  root: never,
6
6
  {
7
+ queryString = null,
7
8
  limit = 10,
8
9
  offset = 0,
9
10
  }: {
10
11
  limit: number;
11
12
  offset: number;
13
+ queryString?: string;
12
14
  },
13
15
  { modules, userId }: Context,
14
16
  ) {
15
17
  log(`query tokens`, { userId });
16
18
 
17
- return modules.warehousing.findTokens({}, { limit, skip: offset });
19
+ return modules.warehousing.findTokens({ queryString }, { limit, skip: offset });
18
20
  }
@@ -0,0 +1,12 @@
1
+ import { log } from '@unchainedshop/logger';
2
+ import { Context } from '../../../context.js';
3
+
4
+ export default async function tokensCount(
5
+ root: never,
6
+ { queryString = null },
7
+ { modules, userId }: Context,
8
+ ) {
9
+ log(`query tokensCount`, { userId });
10
+
11
+ return modules.warehousing.tokensCount({ queryString });
12
+ }
@@ -1,28 +1,23 @@
1
+ import { AssortmentLink } from '@unchainedshop/core-assortments';
1
2
  import { Context } from '../../../context.js';
2
- import {
3
- AssortmentPathLink as AssortmentPathLinkType,
4
- AssortmentLink as AssortmentLinkType,
5
- AssortmentText,
6
- } from '@unchainedshop/core-assortments';
7
3
 
8
- type HelperType<P, T> = (assortmentPathLink: AssortmentPathLinkType, params: P, context: Context) => T;
9
-
10
- export interface AssortmentPathLinkHelperTypes {
11
- link: HelperType<never, Promise<AssortmentLinkType>>;
12
- assortmentTexts: HelperType<{ forceLocale?: string }, Promise<AssortmentText>>;
13
- }
4
+ export const AssortmentPathLink = {
5
+ link(linkObj) {
6
+ if (linkObj._id) return linkObj;
7
+ return null;
8
+ },
14
9
 
15
- export const AssortmentPathLink: AssortmentPathLinkHelperTypes = {
16
- link: async ({ assortmentId, childAssortmentId }, _, { loaders }) => {
17
- return loaders.assortmentLinkLoader.load({
18
- parentAssortmentId: assortmentId,
19
- childAssortmentId,
20
- });
10
+ assortmentId(linkObj) {
11
+ return linkObj.childAssortmentId;
21
12
  },
22
13
 
23
- assortmentTexts: async ({ assortmentId }, params, { loaders, localeContext }) => {
14
+ assortmentTexts: async (
15
+ { childAssortmentId }: AssortmentLink,
16
+ params: { forceLocale?: string },
17
+ { loaders, localeContext }: Context,
18
+ ) => {
24
19
  const text = await loaders.assortmentTextLoader.load({
25
- assortmentId,
20
+ assortmentId: childAssortmentId,
26
21
  locale: params.forceLocale || localeContext.baseName,
27
22
  });
28
23
  return text;
@@ -3,10 +3,22 @@ import { Assortment } from '@unchainedshop/core-assortments';
3
3
  import { SearchFilterQuery } from '@unchainedshop/core-filters';
4
4
 
5
5
  export const AssortmentTypes = {
6
- assortmentPaths: (obj: Assortment, _, { modules }: Context) => {
7
- return modules.assortments.breadcrumbs({
8
- assortmentId: obj._id,
9
- });
6
+ assortmentPaths(obj: Assortment, _, { modules, loaders }: Context) {
7
+ return modules.assortments.breadcrumbs(
8
+ {
9
+ assortmentId: obj._id,
10
+ },
11
+ {
12
+ resolveAssortmentProducts: async (productId) =>
13
+ loaders.assortmentProductsLoader.load({
14
+ productId,
15
+ }),
16
+ resolveAssortmentLinks: async (childAssortmentId) =>
17
+ loaders.assortmentLinksLoader.load({
18
+ childAssortmentId,
19
+ }),
20
+ },
21
+ );
10
22
  },
11
23
 
12
24
  children: async (
@@ -79,7 +91,7 @@ export const AssortmentTypes = {
79
91
 
80
92
  async productAssignments(obj: Assortment, _, { modules }: Context) {
81
93
  // TODO: Loader & move default sort to core module
82
- return modules.assortments.products.findProducts(
94
+ return modules.assortments.products.findAssortmentProducts(
83
95
  {
84
96
  assortmentId: obj._id,
85
97
  },