@unchainedshop/core 5.0.0-alpha.1 → 5.0.0-alpha.10

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 (131) hide show
  1. package/README.md +92 -546
  2. package/lib/bulk-exporter/createBulkExporter.js +1 -1
  3. package/lib/bulk-exporter/handlers/exportProductsHandler.js +2 -2
  4. package/lib/bulk-importer/handlers/assortment/create.js +1 -3
  5. package/lib/bulk-importer/handlers/assortment/update.js +1 -1
  6. package/lib/bulk-importer/handlers/product/create.d.ts +150 -35
  7. package/lib/bulk-importer/handlers/product/create.js +35 -16
  8. package/lib/bulk-importer/handlers/product/update.d.ts +78 -36
  9. package/lib/bulk-importer/handlers/product/update.js +8 -48
  10. package/lib/core-index.d.ts +1 -2
  11. package/lib/core-index.js +2 -18
  12. package/lib/directors/BaseDiscountAdapter.d.ts +3 -0
  13. package/lib/directors/BaseDiscountDirector.d.ts +2 -2
  14. package/lib/directors/BaseDiscountDirector.js +7 -9
  15. package/lib/directors/BasePricingDirector.d.ts +2 -2
  16. package/lib/directors/BasePricingDirector.js +3 -6
  17. package/lib/directors/BaseWorker.js +3 -2
  18. package/lib/directors/DeliveryDirector.d.ts +1 -1
  19. package/lib/directors/DeliveryDirector.js +2 -12
  20. package/lib/directors/DeliveryPricingDirector.js +1 -10
  21. package/lib/directors/EnrollmentAdapter.js +0 -1
  22. package/lib/directors/EnrollmentDirector.d.ts +1 -1
  23. package/lib/directors/EnrollmentDirector.js +3 -15
  24. package/lib/directors/FileDirector.d.ts +4 -4
  25. package/lib/directors/FileDirector.js +2 -13
  26. package/lib/directors/FilterDirector.d.ts +1 -1
  27. package/lib/directors/FilterDirector.js +25 -32
  28. package/lib/directors/OrderDiscountDirector.d.ts +1 -15
  29. package/lib/directors/OrderDiscountDirector.js +1 -13
  30. package/lib/directors/OrderPricingDirector.js +1 -10
  31. package/lib/directors/OrderPricingSheet.d.ts +1 -0
  32. package/lib/directors/OrderPricingSheet.js +17 -17
  33. package/lib/directors/PaymentDirector.d.ts +1 -1
  34. package/lib/directors/PaymentDirector.js +2 -12
  35. package/lib/directors/PaymentPricingDirector.js +1 -10
  36. package/lib/directors/ProductDiscountDirector.d.ts +1 -15
  37. package/lib/directors/ProductDiscountDirector.js +1 -13
  38. package/lib/directors/ProductPricingDirector.js +1 -10
  39. package/lib/directors/QuotationDirector.d.ts +1 -1
  40. package/lib/directors/QuotationDirector.js +2 -14
  41. package/lib/directors/WarehousingDirector.js +16 -34
  42. package/lib/directors/WorkerDirector.d.ts +7 -1
  43. package/lib/directors/WorkerDirector.js +29 -29
  44. package/lib/directors/registryDirector.d.ts +2 -0
  45. package/lib/directors/registryDirector.js +6 -0
  46. package/lib/errors.d.ts +1 -0
  47. package/lib/errors.js +5 -0
  48. package/lib/factory/index.d.ts +12 -1
  49. package/lib/factory/index.js +12 -1
  50. package/lib/factory/registerAssortmentSearchFilter.d.ts +2 -1
  51. package/lib/factory/registerAssortmentSearchFilter.js +6 -3
  52. package/lib/factory/registerDeliveryPricing.d.ts +7 -0
  53. package/lib/factory/registerDeliveryPricing.js +30 -0
  54. package/lib/factory/registerDeliveryProvider.d.ts +12 -0
  55. package/lib/factory/registerDeliveryProvider.js +46 -0
  56. package/lib/factory/registerEnrollment.d.ts +18 -0
  57. package/lib/factory/registerEnrollment.js +43 -0
  58. package/lib/factory/registerFileAdapter.d.ts +17 -0
  59. package/lib/factory/registerFileAdapter.js +24 -0
  60. package/lib/factory/registerOrderDiscount.d.ts +13 -0
  61. package/lib/factory/registerOrderDiscount.js +39 -0
  62. package/lib/factory/registerOrderPricing.d.ts +7 -0
  63. package/lib/factory/registerOrderPricing.js +30 -0
  64. package/lib/factory/registerPaymentPricing.d.ts +7 -0
  65. package/lib/factory/registerPaymentPricing.js +30 -0
  66. package/lib/factory/registerPaymentProvider.d.ts +15 -0
  67. package/lib/factory/registerPaymentProvider.js +53 -0
  68. package/lib/factory/registerProductDiscount.d.ts +20 -0
  69. package/lib/factory/registerProductDiscount.js +47 -0
  70. package/lib/factory/registerProductDiscoverabilityFilter.d.ts +2 -1
  71. package/lib/factory/registerProductDiscoverabilityFilter.js +6 -3
  72. package/lib/factory/registerProductPricing.d.ts +7 -0
  73. package/lib/factory/registerProductPricing.js +30 -0
  74. package/lib/factory/registerProductSearchFilter.d.ts +2 -1
  75. package/lib/factory/registerProductSearchFilter.js +4 -3
  76. package/lib/factory/registerQuotation.d.ts +12 -0
  77. package/lib/factory/registerQuotation.js +52 -0
  78. package/lib/factory/registerVirtualWarehousing.js +1 -1
  79. package/lib/factory/registerWorker.js +1 -1
  80. package/lib/plugins/PluginRegistry.d.ts +1 -0
  81. package/lib/plugins/PluginRegistry.js +11 -2
  82. package/lib/services/addMultipleCartProducts.js +3 -2
  83. package/lib/services/bulkAssignProductsToAssortment.d.ts +8 -0
  84. package/lib/services/bulkAssignProductsToAssortment.js +11 -0
  85. package/lib/services/bulkDeleteUsers.d.ts +7 -0
  86. package/lib/services/bulkDeleteUsers.js +11 -0
  87. package/lib/services/bulkRemoveFilters.d.ts +7 -0
  88. package/lib/services/bulkRemoveFilters.js +10 -0
  89. package/lib/services/bulkRemoveProducts.d.ts +7 -0
  90. package/lib/services/bulkRemoveProducts.js +23 -0
  91. package/lib/services/bulkSetFilterActive.d.ts +8 -0
  92. package/lib/services/bulkSetFilterActive.js +12 -0
  93. package/lib/services/checkoutOrder.js +4 -0
  94. package/lib/services/createFilter.d.ts +3 -0
  95. package/lib/services/createFilter.js +6 -0
  96. package/lib/services/createFilterOption.d.ts +5 -0
  97. package/lib/services/createFilterOption.js +8 -0
  98. package/lib/services/createSignedURL.js +2 -1
  99. package/lib/services/deleteCart.d.ts +2 -0
  100. package/lib/services/deleteCart.js +7 -0
  101. package/lib/services/deleteDeadCarts.d.ts +2 -0
  102. package/lib/services/deleteDeadCarts.js +17 -0
  103. package/lib/services/deleteUser.js +2 -5
  104. package/lib/services/index.d.ts +24 -1
  105. package/lib/services/index.js +24 -1
  106. package/lib/services/initCartProviders.js +1 -0
  107. package/lib/services/isTokenInvalidateable.d.ts +3 -1
  108. package/lib/services/isTokenInvalidateable.js +2 -2
  109. package/lib/services/loadFilterOptions.js +3 -3
  110. package/lib/services/processEnrollment.js +2 -1
  111. package/lib/services/processOrder.js +3 -2
  112. package/lib/services/processQuotation.js +11 -13
  113. package/lib/services/proposeQuotation.js +3 -0
  114. package/lib/services/removeFilterOption.d.ts +6 -0
  115. package/lib/services/removeFilterOption.js +8 -0
  116. package/lib/services/removeProduct.js +2 -1
  117. package/lib/services/reserveOrderDiscountsForCheckout.d.ts +5 -0
  118. package/lib/services/reserveOrderDiscountsForCheckout.js +34 -0
  119. package/lib/services/simulateProductDispatching.d.ts +3 -1
  120. package/lib/services/simulateProductDispatching.js +3 -3
  121. package/lib/services/simulateProductInventory.d.ts +3 -1
  122. package/lib/services/simulateProductInventory.js +3 -3
  123. package/lib/services/supportedDeliveryProviders.js +9 -0
  124. package/lib/services/supportedPaymentProviders.js +9 -0
  125. package/lib/services/supportedWarehousingProviders.js +9 -0
  126. package/lib/services/updateCalculation.js +2 -1
  127. package/lib/services/updateFilter.d.ts +3 -0
  128. package/lib/services/updateFilter.js +8 -0
  129. package/lib/services/uploadFileFromStream.js +2 -1
  130. package/lib/services/validateOrder.js +7 -8
  131. package/package.json +29 -23
@@ -1,8 +1,7 @@
1
- import { BaseDirector } from '@unchainedshop/utils';
2
1
  import { createLogger } from '@unchainedshop/logger';
3
2
  import { PaymentError, PaymentAdapter, } from "./PaymentAdapter.js";
4
3
  import { OrderPaymentStatus } from '@unchainedshop/core-orders';
5
- import { pluginRegistry } from "../plugins/PluginRegistry.js";
4
+ import { registryDirector } from "./registryDirector.js";
6
5
  const buildPaymentProviderActionsContext = (orderPayment, { transactionContext, ...rest }) => ({
7
6
  ...rest,
8
7
  orderPayment,
@@ -12,17 +11,8 @@ const buildPaymentProviderActionsContext = (orderPayment, { transactionContext,
12
11
  },
13
12
  });
14
13
  const logger = createLogger('unchained:core:payment');
15
- const baseDirector = BaseDirector('PaymentDirector');
16
14
  export const PaymentDirector = {
17
- ...baseDirector,
18
- getAdapter: (key) => {
19
- const adapters = pluginRegistry.getAdapters(PaymentAdapter.adapterType);
20
- return adapters.find((adapter) => adapter.key === key) || null;
21
- },
22
- getAdapters: ({ adapterFilter } = {}) => {
23
- const adapters = pluginRegistry.getAdapters(PaymentAdapter.adapterType);
24
- return adapters.filter(adapterFilter || (() => true));
25
- },
15
+ ...registryDirector(PaymentAdapter.adapterType),
26
16
  actions: async (paymentProvider, paymentContext, unchainedAPI) => {
27
17
  const Adapter = PaymentDirector.getAdapter(paymentProvider.adapterKey);
28
18
  if (!Adapter) {
@@ -1,18 +1,9 @@
1
1
  import { BasePricingDirector } from "./BasePricingDirector.js";
2
2
  import { PaymentPricingAdapter, } from "./PaymentPricingAdapter.js";
3
3
  import { PaymentPricingSheet } from "./PaymentPricingSheet.js";
4
- import { pluginRegistry } from "../plugins/PluginRegistry.js";
5
- const baseDirector = BasePricingDirector('PaymentPricingDirector');
4
+ const baseDirector = BasePricingDirector(PaymentPricingAdapter.adapterType);
6
5
  export const PaymentPricingDirector = {
7
6
  ...baseDirector,
8
- getAdapter: (key) => {
9
- const adapters = pluginRegistry.getAdapters(PaymentPricingAdapter.adapterType);
10
- return adapters.find((adapter) => adapter.key === key) || null;
11
- },
12
- getAdapters: ({ adapterFilter } = {}) => {
13
- const adapters = pluginRegistry.getAdapters(PaymentPricingAdapter.adapterType);
14
- return adapters.filter(adapterFilter || (() => true));
15
- },
16
7
  async buildPricingContext(context, unchainedAPI) {
17
8
  const { modules } = unchainedAPI;
18
9
  if ('item' in context) {
@@ -1,16 +1,2 @@
1
1
  import type { ProductDiscountConfiguration } from './ProductDiscountConfiguration.ts';
2
- import type { IDiscountAdapter } from './BaseDiscountAdapter.ts';
3
- export declare const ProductDiscountDirector: {
4
- getAdapter: (key: string) => IDiscountAdapter<ProductDiscountConfiguration> | null;
5
- getAdapters: (options?: {
6
- adapterFilter?: (adapter: any) => boolean;
7
- }) => IDiscountAdapter<ProductDiscountConfiguration>[];
8
- actions: (discountContext: import("./BaseDiscountAdapter.ts").DiscountContext, unchainedAPI: {
9
- modules: import("../modules.ts").Modules;
10
- }) => Promise<{
11
- resolveDiscountAdapterFromStaticCode: (params: {
12
- code: string;
13
- }) => Promise<IDiscountAdapter<ProductDiscountConfiguration> | null>;
14
- findSystemDiscounts: () => Promise<string[]>;
15
- }>;
16
- };
2
+ export declare const ProductDiscountDirector: import("./BaseDiscountDirector.ts").IDiscountDirector<ProductDiscountConfiguration>;
@@ -1,15 +1,3 @@
1
1
  import { BaseDiscountDirector } from "./BaseDiscountDirector.js";
2
2
  import { ProductDiscountAdapter } from "./ProductDiscountAdapter.js";
3
- import { pluginRegistry } from "../plugins/PluginRegistry.js";
4
- const baseDirector = BaseDiscountDirector('ProductDiscountDirector');
5
- export const ProductDiscountDirector = {
6
- ...baseDirector,
7
- getAdapter: (key) => {
8
- const adapters = pluginRegistry.getAdapters(ProductDiscountAdapter.adapterType);
9
- return adapters.find((adapter) => adapter.key === key) || null;
10
- },
11
- getAdapters: (options) => {
12
- const adapters = pluginRegistry.getAdapters(ProductDiscountAdapter.adapterType);
13
- return adapters.filter(options?.adapterFilter || (() => true));
14
- },
15
- };
3
+ export const ProductDiscountDirector = BaseDiscountDirector(ProductDiscountAdapter.adapterType);
@@ -1,18 +1,9 @@
1
1
  import { ProductPricingSheet, } from "./ProductPricingSheet.js";
2
2
  import { ProductPricingAdapter, } from "./ProductPricingAdapter.js";
3
3
  import { BasePricingDirector } from "./BasePricingDirector.js";
4
- import { pluginRegistry } from "../plugins/PluginRegistry.js";
5
- const baseDirector = BasePricingDirector('ProductPricingDirector');
4
+ const baseDirector = BasePricingDirector(ProductPricingAdapter.adapterType);
6
5
  export const ProductPricingDirector = {
7
6
  ...baseDirector,
8
- getAdapter: (key) => {
9
- const adapters = pluginRegistry.getAdapters(ProductPricingAdapter.adapterType);
10
- return adapters.find((adapter) => adapter.key === key) || null;
11
- },
12
- getAdapters: ({ adapterFilter } = {}) => {
13
- const adapters = pluginRegistry.getAdapters(ProductPricingAdapter.adapterType);
14
- return adapters.filter(adapterFilter || (() => true));
15
- },
16
7
  async buildPricingContext(context, unchainedAPI) {
17
8
  const { modules } = unchainedAPI;
18
9
  const { quantity = 1, currencyCode } = context;
@@ -1,4 +1,4 @@
1
- import { type IBaseDirector } from '@unchainedshop/utils';
1
+ import type { IBaseDirector } from '@unchainedshop/utils';
2
2
  import { type IQuotationAdapter, type QuotationAdapterActions, type QuotationContext } from './QuotationAdapter.ts';
3
3
  export type IQuotationDirector = IBaseDirector<IQuotationAdapter> & {
4
4
  actions: (quotationContext: QuotationContext, unchainedAPI: any) => Promise<QuotationAdapterActions>;
@@ -1,11 +1,7 @@
1
- import { BaseDirector } from '@unchainedshop/utils';
2
1
  import { QuotationError, QuotationAdapter, } from "./QuotationAdapter.js";
3
2
  import { createLogger } from '@unchainedshop/logger';
4
- import { pluginRegistry } from "../plugins/PluginRegistry.js";
3
+ import { registryDirector } from "./registryDirector.js";
5
4
  const logger = createLogger('unchained:core');
6
- const baseDirector = BaseDirector('QuotationDirector', {
7
- adapterSortKey: 'orderIndex',
8
- });
9
5
  const findAppropriateAdapters = (quotationContext, unchainedAPI) => QuotationDirector.getAdapters({
10
6
  adapterFilter: (Adapter) => {
11
7
  const activated = Adapter.isActivatedFor(quotationContext, unchainedAPI);
@@ -16,15 +12,7 @@ const findAppropriateAdapters = (quotationContext, unchainedAPI) => QuotationDir
16
12
  },
17
13
  });
18
14
  export const QuotationDirector = {
19
- ...baseDirector,
20
- getAdapter: (key) => {
21
- const adapters = pluginRegistry.getAdapters(QuotationAdapter.adapterType);
22
- return adapters.find((adapter) => adapter.key === key) || null;
23
- },
24
- getAdapters: ({ adapterFilter } = {}) => {
25
- const adapters = pluginRegistry.getAdapters(QuotationAdapter.adapterType);
26
- return adapters.filter(adapterFilter || (() => true));
27
- },
15
+ ...registryDirector(QuotationAdapter.adapterType),
28
16
  actions: async (quotationContext, unchainedAPI) => {
29
17
  const context = { ...quotationContext, ...unchainedAPI };
30
18
  const Adapter = findAppropriateAdapters(quotationContext, unchainedAPI)?.shift();
@@ -1,25 +1,13 @@
1
- import { BaseDirector } from '@unchainedshop/utils';
2
1
  import { createLogger } from '@unchainedshop/logger';
3
2
  const logger = createLogger('unchained:core');
4
3
  import { DeliveryDirector } from "./DeliveryDirector.js";
5
4
  import { WarehousingError, WarehousingAdapter, } from "./WarehousingAdapter.js";
6
- import { pluginRegistry } from "../plugins/PluginRegistry.js";
5
+ import { registryDirector } from "./registryDirector.js";
7
6
  const getReferenceDate = (context) => {
8
7
  return context && context.referenceDate ? context.referenceDate : new Date();
9
8
  };
10
- const baseDirector = BaseDirector('WarehousingDirector', {
11
- adapterSortKey: 'orderIndex',
12
- });
13
9
  export const WarehousingDirector = {
14
- ...baseDirector,
15
- getAdapter: (key) => {
16
- const adapters = pluginRegistry.getAdapters(WarehousingAdapter.adapterType);
17
- return adapters.find((adapter) => adapter.key === key) || null;
18
- },
19
- getAdapters: ({ adapterFilter } = {}) => {
20
- const adapters = pluginRegistry.getAdapters(WarehousingAdapter.adapterType);
21
- return adapters.filter(adapterFilter || (() => true));
22
- },
10
+ ...registryDirector(WarehousingAdapter.adapterType),
23
11
  actions: async (warehousingProvider, warehousingContext, unchainedAPI) => {
24
12
  const Adapter = WarehousingDirector.getAdapter(warehousingProvider.adapterKey);
25
13
  if (!Adapter) {
@@ -145,29 +133,23 @@ export const WarehousingDirector = {
145
133
  };
146
134
  },
147
135
  async tokenMetadata(virtualProviders, warehousingContext, unchainedAPI) {
148
- return virtualProviders.reduce(async (lastPromise, provider) => {
149
- const last = await lastPromise;
150
- if (last)
151
- return last;
152
- const currentDirector = await WarehousingDirector.actions(provider, warehousingContext, unchainedAPI);
153
- const isActive = await currentDirector.isActive();
154
- if (isActive) {
155
- return currentDirector.tokenMetadata(warehousingContext.token.tokenSerialNumber);
156
- }
136
+ const activeActions = await findFirstActiveActions(virtualProviders, warehousingContext, unchainedAPI);
137
+ if (!activeActions)
157
138
  return null;
158
- }, Promise.resolve(null));
139
+ return activeActions.tokenMetadata(warehousingContext.token.tokenSerialNumber);
159
140
  },
160
141
  async isInvalidateable(virtualProviders, warehousingContext, unchainedAPI) {
161
- return virtualProviders.reduce(async (lastPromise, provider) => {
162
- const last = await lastPromise;
163
- if (last)
164
- return last;
165
- const currentDirector = await WarehousingDirector.actions(provider, warehousingContext, unchainedAPI);
166
- const isActive = await currentDirector.isActive();
167
- if (isActive) {
168
- return currentDirector.isInvalidateable(warehousingContext.token.tokenSerialNumber);
169
- }
142
+ const activeActions = await findFirstActiveActions(virtualProviders, warehousingContext, unchainedAPI);
143
+ if (!activeActions)
170
144
  return null;
171
- }, Promise.resolve(null));
145
+ return activeActions.isInvalidateable(warehousingContext.token.tokenSerialNumber);
172
146
  },
173
147
  };
148
+ async function findFirstActiveActions(virtualProviders, warehousingContext, unchainedAPI) {
149
+ for (const provider of virtualProviders) {
150
+ const currentActions = await WarehousingDirector.actions(provider, warehousingContext, unchainedAPI);
151
+ if (currentActions.isActive())
152
+ return currentActions;
153
+ }
154
+ return null;
155
+ }
@@ -1,5 +1,5 @@
1
1
  import type { Work, WorkData, WorkResult } from '@unchainedshop/core-worker';
2
- import { type IBaseDirector } from '@unchainedshop/utils';
2
+ import type { IBaseDirector } from '@unchainedshop/utils';
3
3
  import type { ScheduleData } from '../utils/schedule.ts';
4
4
  import { type IWorkerAdapter } from './WorkerAdapter.ts';
5
5
  import type { Modules } from '../modules.ts';
@@ -18,6 +18,12 @@ export type IWorkerDirector = IBaseDirector<IWorkerAdapter<any, any>> & {
18
18
  configureAutoscheduling: (workScheduleConfiguration: WorkScheduleConfiguration) => void;
19
19
  getAutoSchedules: () => [string, WorkScheduleConfiguration][];
20
20
  doWork: (work: Work, unchainedAPI: any) => Promise<WorkResult>;
21
+ allocateWork: (unchainedAPI: {
22
+ modules: Modules;
23
+ }, options?: {
24
+ types?: string[] | null;
25
+ worker?: string;
26
+ }) => Promise<Work | null>;
21
27
  processNextWork: (unchainedAPI: {
22
28
  modules: Modules;
23
29
  }, workerId?: string) => Promise<Work | null>;
@@ -1,22 +1,10 @@
1
- import { BaseDirector } from '@unchainedshop/utils';
2
1
  import { WorkerAdapter } from "./WorkerAdapter.js";
3
2
  import { createLogger } from '@unchainedshop/logger';
4
- import { pluginRegistry } from "../plugins/PluginRegistry.js";
3
+ import { registryDirector } from "./registryDirector.js";
5
4
  const logger = createLogger('unchained:core');
6
5
  const AutoScheduleMap = new Map();
7
- const baseDirector = BaseDirector('WorkerDirector', {
8
- adapterKeyField: 'key',
9
- });
10
6
  export const WorkerDirector = {
11
- ...baseDirector,
12
- getAdapter: (key) => {
13
- const adapters = pluginRegistry.getAdapters(WorkerAdapter.adapterType);
14
- return adapters.find((adapter) => adapter.key === key) || null;
15
- },
16
- getAdapters: ({ adapterFilter } = {}) => {
17
- const adapters = pluginRegistry.getAdapters(WorkerAdapter.adapterType);
18
- return adapters.filter(adapterFilter || (() => true));
19
- },
7
+ ...registryDirector(WorkerAdapter.adapterType),
20
8
  getActivePluginTypes: ({ external } = {}) => {
21
9
  return WorkerDirector.getAdapters()
22
10
  .filter((adapter) => {
@@ -47,7 +35,7 @@ export const WorkerDirector = {
47
35
  logger.warn(`WorkerDirector: No registered adapter for type: ${type}`);
48
36
  }
49
37
  try {
50
- const output = await adapter.doWork(input, unchainedAPI, workId);
38
+ const output = await adapter.doWork(input ?? {}, unchainedAPI, workId);
51
39
  return output;
52
40
  }
53
41
  catch (error) {
@@ -57,22 +45,34 @@ export const WorkerDirector = {
57
45
  return errorOutput;
58
46
  }
59
47
  },
48
+ allocateWork: async (unchainedAPI, { types: requestedTypes, worker = unchainedAPI.modules.worker.workerId } = {}) => {
49
+ const lock = await unchainedAPI.modules.orders.acquireLock('allocation', 'worker');
50
+ try {
51
+ const adapters = WorkerDirector.getAdapters();
52
+ const allocationMap = await unchainedAPI.modules.worker.allocationMap();
53
+ const types = adapters
54
+ .filter((adapter) => {
55
+ if (requestedTypes && !requestedTypes.includes(adapter.type))
56
+ return false;
57
+ if (adapter.maxParallelAllocations &&
58
+ adapter.maxParallelAllocations <= allocationMap[adapter.type])
59
+ return false;
60
+ return true;
61
+ })
62
+ .map((adapter) => adapter.type);
63
+ return await unchainedAPI.modules.worker.allocateWork({
64
+ types,
65
+ worker,
66
+ });
67
+ }
68
+ finally {
69
+ await lock.release();
70
+ }
71
+ },
60
72
  processNextWork: async (unchainedAPI, workerId) => {
61
- const adapters = WorkerDirector.getAdapters();
62
- const allocationMap = await unchainedAPI.modules.worker.allocationMap();
63
- const types = adapters
64
- .filter((adapter) => {
65
- if (adapter.external)
66
- return false;
67
- if (adapter.maxParallelAllocations &&
68
- adapter.maxParallelAllocations <= allocationMap[adapter.type])
69
- return false;
70
- return true;
71
- })
72
- .map((adapter) => adapter.type);
73
73
  const worker = workerId ?? unchainedAPI.modules.worker.workerId;
74
- const work = await unchainedAPI.modules.worker.allocateWork({
75
- types,
74
+ const work = await WorkerDirector.allocateWork(unchainedAPI, {
75
+ types: WorkerDirector.getActivePluginTypes({ external: false }),
76
76
  worker,
77
77
  });
78
78
  if (work) {
@@ -0,0 +1,2 @@
1
+ import type { IBaseAdapter, IBaseDirector } from '@unchainedshop/utils';
2
+ export declare const registryDirector: <Adapter extends IBaseAdapter>(adapterType: symbol) => IBaseDirector<Adapter>;
@@ -0,0 +1,6 @@
1
+ import { pluginRegistry } from "../plugins/PluginRegistry.js";
2
+ export const registryDirector = (adapterType) => ({
3
+ getAdapter: (key) => pluginRegistry.getAdapters(adapterType).find((adapter) => adapter.key === key) ||
4
+ null,
5
+ getAdapters: ({ adapterFilter } = {}) => pluginRegistry.getAdapters(adapterType).filter(adapterFilter || (() => true)),
6
+ });
@@ -0,0 +1 @@
1
+ export declare const createServiceError: (name: string, message: string) => Error;
package/lib/errors.js ADDED
@@ -0,0 +1,5 @@
1
+ export const createServiceError = (name, message) => {
2
+ const error = new Error(message);
3
+ error.name = name;
4
+ return error;
5
+ };
@@ -7,4 +7,15 @@ import registerVirtualWarehousing from './registerVirtualWarehousing.ts';
7
7
  import registerProductSearchFilter from './registerProductSearchFilter.ts';
8
8
  import registerAssortmentSearchFilter from './registerAssortmentSearchFilter.ts';
9
9
  import registerInvoicePayment from './registerInvoicePayment.ts';
10
- export { registerProductDiscoverabilityFilter, registerPickUpDelivery, registerShippingDelivery, registerInvoicePayment, registerWorker, registerPhysicalWarehousing, registerVirtualWarehousing, registerProductSearchFilter, registerAssortmentSearchFilter, };
10
+ import registerPaymentProvider from './registerPaymentProvider.ts';
11
+ import registerDeliveryProvider from './registerDeliveryProvider.ts';
12
+ import registerProductPricing from './registerProductPricing.ts';
13
+ import registerOrderPricing from './registerOrderPricing.ts';
14
+ import registerPaymentPricing from './registerPaymentPricing.ts';
15
+ import registerDeliveryPricing from './registerDeliveryPricing.ts';
16
+ import registerProductDiscount from './registerProductDiscount.ts';
17
+ import registerOrderDiscount from './registerOrderDiscount.ts';
18
+ import registerFileAdapter from './registerFileAdapter.ts';
19
+ import registerQuotation from './registerQuotation.ts';
20
+ import registerEnrollment from './registerEnrollment.ts';
21
+ export { registerProductDiscoverabilityFilter, registerPickUpDelivery, registerShippingDelivery, registerInvoicePayment, registerWorker, registerPhysicalWarehousing, registerVirtualWarehousing, registerProductSearchFilter, registerAssortmentSearchFilter, registerPaymentProvider, registerDeliveryProvider, registerProductPricing, registerOrderPricing, registerPaymentPricing, registerDeliveryPricing, registerProductDiscount, registerOrderDiscount, registerFileAdapter, registerQuotation, registerEnrollment, };
@@ -7,4 +7,15 @@ import registerVirtualWarehousing from "./registerVirtualWarehousing.js";
7
7
  import registerProductSearchFilter from "./registerProductSearchFilter.js";
8
8
  import registerAssortmentSearchFilter from "./registerAssortmentSearchFilter.js";
9
9
  import registerInvoicePayment from "./registerInvoicePayment.js";
10
- export { registerProductDiscoverabilityFilter, registerPickUpDelivery, registerShippingDelivery, registerInvoicePayment, registerWorker, registerPhysicalWarehousing, registerVirtualWarehousing, registerProductSearchFilter, registerAssortmentSearchFilter, };
10
+ import registerPaymentProvider from "./registerPaymentProvider.js";
11
+ import registerDeliveryProvider from "./registerDeliveryProvider.js";
12
+ import registerProductPricing from "./registerProductPricing.js";
13
+ import registerOrderPricing from "./registerOrderPricing.js";
14
+ import registerPaymentPricing from "./registerPaymentPricing.js";
15
+ import registerDeliveryPricing from "./registerDeliveryPricing.js";
16
+ import registerProductDiscount from "./registerProductDiscount.js";
17
+ import registerOrderDiscount from "./registerOrderDiscount.js";
18
+ import registerFileAdapter from "./registerFileAdapter.js";
19
+ import registerQuotation from "./registerQuotation.js";
20
+ import registerEnrollment from "./registerEnrollment.js";
21
+ export { registerProductDiscoverabilityFilter, registerPickUpDelivery, registerShippingDelivery, registerInvoicePayment, registerWorker, registerPhysicalWarehousing, registerVirtualWarehousing, registerProductSearchFilter, registerAssortmentSearchFilter, registerPaymentProvider, registerDeliveryProvider, registerProductPricing, registerOrderPricing, registerPaymentPricing, registerDeliveryPricing, registerProductDiscount, registerOrderDiscount, registerFileAdapter, registerQuotation, registerEnrollment, };
@@ -1,6 +1,7 @@
1
1
  import type { SearchQuery } from '@unchainedshop/core-filters';
2
2
  import { type IPlugin } from '../core-index.ts';
3
- export default function registerAssortmentSearchFilter({ orderIndex, search, }: {
3
+ export default function registerAssortmentSearchFilter({ adapterId, orderIndex, search, }: {
4
+ adapterId?: string;
4
5
  orderIndex?: number;
5
6
  search: (params: SearchQuery & {
6
7
  queryString: string;
@@ -1,10 +1,13 @@
1
1
  import { FilterAdapter } from "../core-index.js";
2
2
  import { pluginRegistry } from "../plugins/PluginRegistry.js";
3
- export default function registerAssortmentSearchFilter({ orderIndex = 0, search, }) {
3
+ export default function registerAssortmentSearchFilter({ adapterId, orderIndex = 0, search, }) {
4
+ const id = adapterId ?? crypto.randomUUID();
4
5
  const adapter = {
5
6
  ...FilterAdapter,
6
- key: `shop.unchained.filters.assortment-search-${crypto.randomUUID()}`,
7
- label: 'Assortment Search Filter (auto-generated)',
7
+ key: `shop.unchained.filters.assortment-search-${id}`,
8
+ label: adapterId
9
+ ? `Assortment Search Filter: ${adapterId}`
10
+ : 'Assortment Search Filter (auto-generated)',
8
11
  version: '1.0.0',
9
12
  orderIndex,
10
13
  actions: (params) => {
@@ -0,0 +1,7 @@
1
+ import { type IPlugin, type IDeliveryPricingSheet, type DeliveryPricingAdapterContext } from '../core-index.ts';
2
+ export default function registerDeliveryPricing({ adapterId, orderIndex, isActivatedFor, calculate, }: {
3
+ adapterId: string;
4
+ orderIndex?: number;
5
+ isActivatedFor?: (context: DeliveryPricingAdapterContext) => boolean;
6
+ calculate: (sheet: IDeliveryPricingSheet, context: DeliveryPricingAdapterContext) => Promise<void>;
7
+ }): IPlugin;
@@ -0,0 +1,30 @@
1
+ import { DeliveryPricingAdapter, } from "../core-index.js";
2
+ import { pluginRegistry } from "../plugins/PluginRegistry.js";
3
+ export default function registerDeliveryPricing({ adapterId, orderIndex, isActivatedFor, calculate, }) {
4
+ const adapter = {
5
+ ...DeliveryPricingAdapter,
6
+ key: `shop.unchained.pricing.delivery-${adapterId}`,
7
+ label: 'Delivery Pricing: ' + adapterId,
8
+ version: '1.0.0',
9
+ orderIndex: orderIndex ?? 0,
10
+ isActivatedFor: (context) => (isActivatedFor ? isActivatedFor(context) : true),
11
+ actions: (params) => {
12
+ const pricingAdapter = DeliveryPricingAdapter.actions(params);
13
+ return {
14
+ ...pricingAdapter,
15
+ calculate: async () => {
16
+ await calculate(pricingAdapter.resultSheet(), params.context);
17
+ return pricingAdapter.calculate();
18
+ },
19
+ };
20
+ },
21
+ };
22
+ const plugin = {
23
+ key: adapter.key,
24
+ label: adapter.label,
25
+ version: adapter.version,
26
+ adapters: [adapter],
27
+ };
28
+ pluginRegistry.register(plugin);
29
+ return plugin;
30
+ }
@@ -0,0 +1,12 @@
1
+ import type { DeliveryConfiguration } from '@unchainedshop/core-delivery';
2
+ import { DeliveryProviderType } from '@unchainedshop/core-delivery';
3
+ import { type DeliveryContext, type IPlugin } from '../core-index.ts';
4
+ import type { Work } from '@unchainedshop/core-worker';
5
+ export default function registerDeliveryProvider({ adapterId, type, active, autoReleaseAllowed, estimatedDeliveryThroughput, send, }: {
6
+ adapterId: string;
7
+ type?: DeliveryProviderType;
8
+ active?: boolean;
9
+ autoReleaseAllowed?: boolean;
10
+ estimatedDeliveryThroughput?: (warehousingThroughputTime: number, context: DeliveryContext) => Promise<number | null>;
11
+ send: boolean | ((configuration: DeliveryConfiguration, context: DeliveryContext) => Promise<boolean | Work>);
12
+ }): IPlugin;
@@ -0,0 +1,46 @@
1
+ import { DeliveryProviderType } from '@unchainedshop/core-delivery';
2
+ import { DeliveryAdapter, } from "../core-index.js";
3
+ import { pluginRegistry } from "../plugins/PluginRegistry.js";
4
+ export default function registerDeliveryProvider({ adapterId, type = DeliveryProviderType.SHIPPING, active, autoReleaseAllowed, estimatedDeliveryThroughput, send, }) {
5
+ const adapter = {
6
+ ...DeliveryAdapter,
7
+ key: `shop.unchained.delivery.${adapterId}`,
8
+ label: 'Delivery: ' + adapterId,
9
+ version: '1.0.0',
10
+ initialConfiguration: [],
11
+ typeSupported: (deliveryType) => {
12
+ return deliveryType === type;
13
+ },
14
+ actions: (config, context) => {
15
+ return {
16
+ ...DeliveryAdapter.actions(config, context),
17
+ isActive: () => {
18
+ return active ?? true;
19
+ },
20
+ isAutoReleaseAllowed: () => {
21
+ return autoReleaseAllowed ?? true;
22
+ },
23
+ configurationError: () => {
24
+ return null;
25
+ },
26
+ estimatedDeliveryThroughput: async (warehousingThroughputTime) => {
27
+ if (estimatedDeliveryThroughput) {
28
+ return estimatedDeliveryThroughput(warehousingThroughputTime, context);
29
+ }
30
+ return 0;
31
+ },
32
+ send: async () => {
33
+ return typeof send === 'function' ? await send(config, context) : send;
34
+ },
35
+ };
36
+ },
37
+ };
38
+ const plugin = {
39
+ key: adapter.key,
40
+ label: adapter.label,
41
+ version: adapter.version,
42
+ adapters: [adapter],
43
+ };
44
+ pluginRegistry.register(plugin);
45
+ return plugin;
46
+ }
@@ -0,0 +1,18 @@
1
+ import type { EnrollmentOrderPositionTemplate, EnrollmentPeriod, EnrollmentPlan } from '@unchainedshop/core-enrollments';
2
+ import type { ProductPlan } from '@unchainedshop/core-products';
3
+ import type { OrderPosition } from '@unchainedshop/core-orders';
4
+ import { type EnrollmentContext, type IPlugin } from '../core-index.ts';
5
+ export default function registerEnrollment({ adapterId, isActivatedFor, transformOrderItem, configurationForOrder, isOverdue, isValidForActivation, nextPeriod, }: {
6
+ adapterId: string;
7
+ isActivatedFor?: (productPlan?: ProductPlan) => boolean;
8
+ transformOrderItem?: (orderPosition: OrderPosition, unchainedAPI: any) => Promise<EnrollmentPlan>;
9
+ configurationForOrder: (params: {
10
+ period: EnrollmentPeriod;
11
+ }, context: EnrollmentContext) => Promise<{
12
+ orderContext?: Record<string, any>;
13
+ orderPositionTemplates: EnrollmentOrderPositionTemplate[];
14
+ } | null>;
15
+ isOverdue?: (context: EnrollmentContext) => Promise<boolean>;
16
+ isValidForActivation?: (context: EnrollmentContext) => Promise<boolean>;
17
+ nextPeriod?: (context: EnrollmentContext) => Promise<EnrollmentPeriod | null>;
18
+ }): IPlugin;
@@ -0,0 +1,43 @@
1
+ import { EnrollmentAdapter, } from "../core-index.js";
2
+ import { pluginRegistry } from "../plugins/PluginRegistry.js";
3
+ export default function registerEnrollment({ adapterId, isActivatedFor, transformOrderItem, configurationForOrder, isOverdue, isValidForActivation, nextPeriod, }) {
4
+ const adapter = {
5
+ ...EnrollmentAdapter,
6
+ key: `shop.unchained.enrollment.${adapterId}`,
7
+ label: 'Enrollment: ' + adapterId,
8
+ version: '1.0.0',
9
+ isActivatedFor: (productPlan) => {
10
+ return isActivatedFor ? isActivatedFor(productPlan) : true;
11
+ },
12
+ transformOrderItemToEnrollmentPlan: async (orderPosition, unchainedAPI) => {
13
+ return transformOrderItem
14
+ ? transformOrderItem(orderPosition, unchainedAPI)
15
+ : EnrollmentAdapter.transformOrderItemToEnrollmentPlan(orderPosition, unchainedAPI);
16
+ },
17
+ actions: (context) => {
18
+ return {
19
+ ...EnrollmentAdapter.actions(context),
20
+ configurationForOrder: async (params) => {
21
+ return configurationForOrder(params, context);
22
+ },
23
+ isOverdue: async () => {
24
+ return isOverdue ? isOverdue(context) : false;
25
+ },
26
+ isValidForActivation: async () => {
27
+ return isValidForActivation ? isValidForActivation(context) : false;
28
+ },
29
+ nextPeriod: async () => {
30
+ return nextPeriod ? nextPeriod(context) : EnrollmentAdapter.actions(context).nextPeriod();
31
+ },
32
+ };
33
+ },
34
+ };
35
+ const plugin = {
36
+ key: adapter.key,
37
+ label: adapter.label,
38
+ version: adapter.version,
39
+ adapters: [adapter],
40
+ };
41
+ pluginRegistry.register(plugin);
42
+ return plugin;
43
+ }
@@ -0,0 +1,17 @@
1
+ import { type UploadedFile, type UploadFileData } from '@unchainedshop/core-files';
2
+ import { type IPlugin } from '../core-index.ts';
3
+ export default function registerFileAdapter<Context = unknown>({ adapterId, createSignedURL, uploadFileFromStream, createDownloadURL, removeFiles, uploadFileFromURL, }: {
4
+ adapterId: string;
5
+ createSignedURL: (directoryName: string, fileName: string, unchainedAPI: Context) => Promise<(UploadFileData & {
6
+ putURL: string;
7
+ }) | null>;
8
+ uploadFileFromStream: (directoryName: string, rawFile: any, unchainedAPI: Context, options?: Record<string, any>) => Promise<UploadFileData>;
9
+ createDownloadURL?: (file: UploadedFile, expiry?: number) => Promise<string | null>;
10
+ removeFiles?: (files: UploadedFile[], unchainedContext: Context) => Promise<void>;
11
+ uploadFileFromURL?: (directoryName: string, fileInput: {
12
+ fileLink: string;
13
+ fileName: string;
14
+ fileId?: string;
15
+ headers?: Record<string, unknown>;
16
+ }, unchainedAPI: Context) => Promise<UploadFileData>;
17
+ }): IPlugin;
@@ -0,0 +1,24 @@
1
+ import { FileAdapter, } from '@unchainedshop/core-files';
2
+ import {} from "../core-index.js";
3
+ import { pluginRegistry } from "../plugins/PluginRegistry.js";
4
+ export default function registerFileAdapter({ adapterId, createSignedURL, uploadFileFromStream, createDownloadURL, removeFiles, uploadFileFromURL, }) {
5
+ const adapter = {
6
+ ...FileAdapter,
7
+ key: `shop.unchained.file-upload.${adapterId}`,
8
+ label: 'File Adapter: ' + adapterId,
9
+ version: '1.0.0',
10
+ createSignedURL,
11
+ uploadFileFromStream,
12
+ ...(createDownloadURL ? { createDownloadURL } : {}),
13
+ ...(removeFiles ? { removeFiles } : {}),
14
+ ...(uploadFileFromURL ? { uploadFileFromURL } : {}),
15
+ };
16
+ const plugin = {
17
+ key: adapter.key,
18
+ label: adapter.label,
19
+ version: adapter.version,
20
+ adapters: [adapter],
21
+ };
22
+ pluginRegistry.register(plugin);
23
+ return plugin;
24
+ }
@@ -0,0 +1,13 @@
1
+ import type { PricingCalculation } from '@unchainedshop/utils';
2
+ import { type DiscountContext, type IPricingSheet, type OrderDiscountConfiguration, type IPlugin } from '../core-index.ts';
3
+ export default function registerOrderDiscount({ adapterId, isValidForSystemTriggering, isValidForCodeTriggering, discountForPricingAdapterKey, reserve, release, }: {
4
+ adapterId: string;
5
+ isValidForSystemTriggering?: (context: DiscountContext) => Promise<boolean>;
6
+ isValidForCodeTriggering?: (code: string, context: DiscountContext) => Promise<boolean>;
7
+ discountForPricingAdapterKey: (params: {
8
+ pricingAdapterKey: string;
9
+ calculationSheet: IPricingSheet<PricingCalculation>;
10
+ }, context: DiscountContext) => OrderDiscountConfiguration | null;
11
+ reserve?: (code: string | undefined, context: DiscountContext) => Promise<any>;
12
+ release?: (context: DiscountContext) => Promise<void>;
13
+ }): IPlugin;