@sixtyninecommerce/admin 0.9.0 → 0.11.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 (258) hide show
  1. package/README.md +4598 -128
  2. package/dist/catalog/assets.d.ts +120 -8
  3. package/dist/catalog/assets.js +98 -12
  4. package/dist/catalog/collections.d.ts +279 -14
  5. package/dist/catalog/collections.js +246 -15
  6. package/dist/catalog/index.d.ts +9 -2
  7. package/dist/catalog/index.js +4 -0
  8. package/dist/catalog/products.d.ts +318 -17
  9. package/dist/catalog/products.js +182 -14
  10. package/dist/catalog/properties.d.ts +102 -14
  11. package/dist/catalog/properties.js +13 -0
  12. package/dist/catalog/recommendations.d.ts +261 -0
  13. package/dist/catalog/recommendations.js +145 -0
  14. package/dist/catalog/reviews.d.ts +368 -0
  15. package/dist/catalog/reviews.js +318 -0
  16. package/dist/catalog/types.d.ts +17 -1
  17. package/dist/catalog/types.js +10 -0
  18. package/dist/catalog/variant-find.d.ts +136 -0
  19. package/dist/catalog/variant-find.js +239 -0
  20. package/dist/catalog/variants.d.ts +282 -25
  21. package/dist/catalog/variants.js +173 -25
  22. package/dist/catalog/visibility.d.ts +20 -5
  23. package/dist/catalog/visibility.js +19 -1
  24. package/dist/client.d.ts +116 -9
  25. package/dist/client.js +41 -7
  26. package/dist/content/assets.d.ts +286 -0
  27. package/dist/content/assets.js +181 -0
  28. package/dist/content/items.d.ts +269 -0
  29. package/dist/content/items.js +170 -0
  30. package/dist/content/types.d.ts +282 -0
  31. package/dist/content/types.js +100 -0
  32. package/dist/customers/age-verification.d.ts +66 -0
  33. package/dist/customers/age-verification.js +79 -0
  34. package/dist/customers/credit.d.ts +263 -0
  35. package/dist/customers/credit.js +244 -0
  36. package/dist/customers/delivery-preferences.d.ts +120 -0
  37. package/dist/customers/delivery-preferences.js +97 -0
  38. package/dist/customers/groups.d.ts +207 -0
  39. package/dist/customers/groups.js +438 -0
  40. package/dist/customers/index.d.ts +447 -37
  41. package/dist/customers/index.js +313 -40
  42. package/dist/customers/invitation-status.d.ts +57 -0
  43. package/dist/customers/invitation-status.js +21 -0
  44. package/dist/customers/notes.d.ts +67 -0
  45. package/dist/customers/notes.js +51 -0
  46. package/dist/customers/notification-recipients.d.ts +97 -0
  47. package/dist/customers/notification-recipients.js +84 -0
  48. package/dist/customers/saved-lists.d.ts +42 -0
  49. package/dist/customers/saved-lists.js +61 -0
  50. package/dist/customers/vat.d.ts +83 -0
  51. package/dist/customers/vat.js +46 -0
  52. package/dist/customers/wire.d.ts +20 -0
  53. package/dist/customers/wire.js +35 -0
  54. package/dist/documents/ar.d.ts +307 -0
  55. package/dist/documents/ar.js +254 -0
  56. package/dist/documents/index.d.ts +731 -21
  57. package/dist/documents/index.js +436 -24
  58. package/dist/documents/pdf.d.ts +2 -0
  59. package/dist/documents/pdf.js +11 -0
  60. package/dist/fulfillments/create.d.ts +167 -0
  61. package/dist/fulfillments/create.js +216 -0
  62. package/dist/fulfillments/index.d.ts +121 -10
  63. package/dist/fulfillments/index.js +120 -2
  64. package/dist/fulfillments/payment-policy.d.ts +64 -0
  65. package/dist/fulfillments/payment-policy.js +140 -0
  66. package/dist/fulfillments/warehouse.d.ts +724 -0
  67. package/dist/fulfillments/warehouse.js +914 -0
  68. package/dist/geo/index.d.ts +119 -0
  69. package/dist/geo/index.js +107 -0
  70. package/dist/index.d.ts +129 -30
  71. package/dist/index.js +47 -9
  72. package/dist/integrations/afas-actions.d.ts +234 -0
  73. package/dist/integrations/afas-actions.js +310 -0
  74. package/dist/integrations/afas-types.d.ts +483 -0
  75. package/dist/integrations/afas-types.js +5 -0
  76. package/dist/integrations/afas.d.ts +234 -0
  77. package/dist/integrations/afas.js +290 -0
  78. package/dist/integrations/connections.d.ts +103 -0
  79. package/dist/integrations/connections.js +55 -0
  80. package/dist/integrations/esp.d.ts +313 -0
  81. package/dist/integrations/esp.js +169 -0
  82. package/dist/integrations/exact-online-types.d.ts +423 -0
  83. package/dist/integrations/exact-online-types.js +6 -0
  84. package/dist/integrations/exact-online.d.ts +248 -0
  85. package/dist/integrations/exact-online.js +376 -0
  86. package/dist/integrations/index.d.ts +40 -0
  87. package/dist/integrations/index.js +24 -0
  88. package/dist/integrations/pipeline-keys.d.ts +13 -0
  89. package/dist/integrations/pipeline-keys.js +22 -0
  90. package/dist/integrations/pipelines.d.ts +114 -0
  91. package/dist/integrations/pipelines.js +46 -0
  92. package/dist/integrations/types.d.ts +322 -0
  93. package/dist/integrations/types.js +8 -0
  94. package/dist/jobs/bulk-action-run.d.ts +11 -2
  95. package/dist/jobs/bulk-action-run.js +4 -5
  96. package/dist/locations/index.d.ts +66 -0
  97. package/dist/locations/index.js +31 -0
  98. package/dist/meta/index.d.ts +162 -0
  99. package/dist/orders/bulk.d.ts +75 -0
  100. package/dist/orders/bulk.js +150 -0
  101. package/dist/orders/cancel-with-money.d.ts +227 -0
  102. package/dist/orders/cancel-with-money.js +153 -0
  103. package/dist/orders/commit-edit.d.ts +7 -1
  104. package/dist/orders/commit-edit.js +5 -1
  105. package/dist/orders/deposit-policy.d.ts +103 -0
  106. package/dist/orders/deposit-policy.js +202 -0
  107. package/dist/orders/drafts.d.ts +800 -0
  108. package/dist/orders/drafts.js +771 -0
  109. package/dist/orders/fields.d.ts +245 -0
  110. package/dist/orders/fields.js +188 -0
  111. package/dist/orders/get.d.ts +29 -19
  112. package/dist/orders/get.js +17 -8
  113. package/dist/orders/index.d.ts +125 -5
  114. package/dist/orders/index.js +35 -2
  115. package/dist/orders/lifecycle.d.ts +128 -0
  116. package/dist/orders/lifecycle.js +158 -0
  117. package/dist/orders/line-price-preview.d.ts +7 -2
  118. package/dist/orders/list.d.ts +222 -0
  119. package/dist/orders/list.js +377 -0
  120. package/dist/orders/manual-discounts.d.ts +11 -2
  121. package/dist/orders/manual-discounts.js +2 -0
  122. package/dist/orders/manual-pricing.d.ts +5 -0
  123. package/dist/orders/order-entry.d.ts +20 -7
  124. package/dist/orders/plan-edit.d.ts +1 -1
  125. package/dist/orders/plan-edit.js +4 -1
  126. package/dist/orders/settings.d.ts +201 -0
  127. package/dist/orders/settings.js +325 -0
  128. package/dist/orders/status.d.ts +159 -13
  129. package/dist/orders/status.js +21 -0
  130. package/dist/orders/surcharges.d.ts +8 -1
  131. package/dist/orders/surcharges.js +3 -2
  132. package/dist/payments/account-credit.d.ts +30 -0
  133. package/dist/payments/account-credit.js +19 -0
  134. package/dist/payments/ar.d.ts +292 -0
  135. package/dist/payments/ar.js +223 -0
  136. package/dist/payments/connected-account.d.ts +47 -0
  137. package/dist/payments/connected-account.js +61 -0
  138. package/dist/payments/credit-noted-fields.d.ts +12 -0
  139. package/dist/payments/credit-noted-fields.js +37 -0
  140. package/dist/payments/index.d.ts +263 -10
  141. package/dist/payments/index.js +133 -1
  142. package/dist/payments/methods.d.ts +332 -0
  143. package/dist/payments/methods.js +363 -0
  144. package/dist/payments/mollie-methods.d.ts +159 -0
  145. package/dist/payments/mollie-methods.js +141 -0
  146. package/dist/payments/payment-links.d.ts +180 -0
  147. package/dist/payments/payment-links.js +97 -0
  148. package/dist/payments/provider-keys.d.ts +150 -0
  149. package/dist/payments/provider-keys.js +118 -0
  150. package/dist/payments/providers.d.ts +86 -11
  151. package/dist/payments/providers.js +29 -0
  152. package/dist/payments/requests.d.ts +144 -0
  153. package/dist/payments/requests.js +92 -0
  154. package/dist/payments/store-credit-fields.d.ts +15 -0
  155. package/dist/payments/store-credit-fields.js +51 -0
  156. package/dist/pickups/index.d.ts +104 -0
  157. package/dist/pickups/index.js +105 -0
  158. package/dist/platform/channels.d.ts +132 -0
  159. package/dist/platform/channels.js +128 -0
  160. package/dist/platform/geo.d.ts +123 -0
  161. package/dist/platform/geo.js +144 -0
  162. package/dist/platform/tax.d.ts +154 -0
  163. package/dist/platform/tax.js +139 -0
  164. package/dist/pos/anomalies.d.ts +158 -0
  165. package/dist/pos/anomalies.js +64 -0
  166. package/dist/pos/assisted-selling.d.ts +79 -0
  167. package/dist/pos/assisted-selling.js +38 -0
  168. package/dist/pos/exchanges.d.ts +103 -0
  169. package/dist/pos/exchanges.js +22 -0
  170. package/dist/pos/gift-cards.d.ts +135 -0
  171. package/dist/pos/gift-cards.js +47 -0
  172. package/dist/pos/index.d.ts +2125 -32
  173. package/dist/pos/index.js +742 -4
  174. package/dist/pos/no-receipt.d.ts +94 -0
  175. package/dist/pos/no-receipt.js +25 -0
  176. package/dist/pos/offline-sales.d.ts +187 -0
  177. package/dist/pos/offline-sales.js +116 -0
  178. package/dist/pos/pay-by-link.d.ts +143 -0
  179. package/dist/pos/pay-by-link.js +57 -0
  180. package/dist/pos/quick-keys.d.ts +103 -0
  181. package/dist/pos/quick-keys.js +45 -0
  182. package/dist/pos/reports.d.ts +360 -0
  183. package/dist/pos/reports.js +62 -0
  184. package/dist/pos/returns.d.ts +217 -0
  185. package/dist/pos/returns.js +53 -0
  186. package/dist/pricing/bulk-coupons.d.ts +139 -0
  187. package/dist/pricing/bulk-coupons.js +112 -0
  188. package/dist/pricing/index.d.ts +177 -4
  189. package/dist/pricing/index.js +176 -1
  190. package/dist/pricing/price-lists.d.ts +604 -0
  191. package/dist/pricing/price-lists.js +600 -0
  192. package/dist/pricing/vouchers.d.ts +103 -0
  193. package/dist/pricing/vouchers.js +69 -0
  194. package/dist/purchasing/alerts.d.ts +89 -0
  195. package/dist/purchasing/alerts.js +62 -0
  196. package/dist/purchasing/cost.d.ts +110 -0
  197. package/dist/purchasing/cost.js +86 -0
  198. package/dist/purchasing/index.d.ts +36 -0
  199. package/dist/purchasing/index.js +16 -0
  200. package/dist/purchasing/purchase-orders.d.ts +548 -0
  201. package/dist/purchasing/purchase-orders.js +491 -0
  202. package/dist/purchasing/replenishment.d.ts +281 -0
  203. package/dist/purchasing/replenishment.js +240 -0
  204. package/dist/purchasing/settings.d.ts +152 -0
  205. package/dist/purchasing/settings.js +181 -0
  206. package/dist/purchasing/suppliers.d.ts +476 -0
  207. package/dist/purchasing/suppliers.js +438 -0
  208. package/dist/quotes/index.d.ts +501 -0
  209. package/dist/quotes/index.js +439 -0
  210. package/dist/reports/index.d.ts +71 -8
  211. package/dist/reports/index.js +74 -11
  212. package/dist/returns/index.d.ts +818 -0
  213. package/dist/returns/index.js +844 -0
  214. package/dist/search/index.d.ts +174 -0
  215. package/dist/search/index.js +125 -0
  216. package/dist/shipping/definitions.d.ts +29 -0
  217. package/dist/shipping/definitions.js +47 -0
  218. package/dist/shipping/fulfillment-profiles.d.ts +174 -0
  219. package/dist/shipping/fulfillment-profiles.js +104 -0
  220. package/dist/shipping/hendriks.d.ts +97 -0
  221. package/dist/shipping/hendriks.js +50 -0
  222. package/dist/shipping/index.d.ts +48 -0
  223. package/dist/shipping/index.js +25 -0
  224. package/dist/shipping/methods.d.ts +198 -0
  225. package/dist/shipping/methods.js +240 -0
  226. package/dist/shipping/myparcel.d.ts +254 -0
  227. package/dist/shipping/myparcel.js +178 -0
  228. package/dist/shipping/parcel-count-suggestion.d.ts +2 -0
  229. package/dist/shipping/parcel-rule.d.ts +6 -5
  230. package/dist/shipping/parcel-rule.js +21 -23
  231. package/dist/shipping/rate-tables.d.ts +179 -0
  232. package/dist/shipping/rate-tables.js +184 -0
  233. package/dist/stock/index.d.ts +10 -3
  234. package/dist/stock/index.js +3 -0
  235. package/dist/stock/locations.d.ts +144 -0
  236. package/dist/stock/locations.js +168 -0
  237. package/dist/stock/transfers.d.ts +216 -43
  238. package/dist/stock/transfers.js +140 -13
  239. package/dist/stored-value/index.d.ts +214 -4
  240. package/dist/stored-value/index.js +152 -0
  241. package/dist/subscriptions/index.d.ts +682 -0
  242. package/dist/subscriptions/index.js +815 -0
  243. package/dist/tax/index.d.ts +76 -1
  244. package/dist/tax/index.js +50 -0
  245. package/dist/tenant/email-style.d.ts +102 -0
  246. package/dist/tenant/email-style.js +72 -0
  247. package/dist/tenant/email-templates.d.ts +66 -0
  248. package/dist/tenant/email-templates.js +54 -0
  249. package/dist/tenant/notifications.d.ts +23 -17
  250. package/dist/tenant/settings-sources.d.ts +1 -1
  251. package/dist/tenant/time-zone.d.ts +17 -0
  252. package/dist/tenant/time-zone.js +11 -0
  253. package/dist/types.d.ts +51 -4
  254. package/dist/users/index.d.ts +3 -0
  255. package/dist/users/index.js +2 -0
  256. package/dist/users/warehouses.d.ts +50 -0
  257. package/dist/users/warehouses.js +51 -0
  258. package/package.json +2 -2
@@ -0,0 +1,363 @@
1
+ import { ConflictError, createPage, ValidationError, } from '@sixtyninecommerce/core';
2
+ import { assertDeleted, fieldOf, vendureListPage, } from '../catalog/types.js';
3
+ import { createMollieMethodsModule } from './mollie-methods.js';
4
+ import { createProviderKeysModule } from './provider-keys.js';
5
+ /** A store has a handful; one page holds them. */
6
+ const DEFAULT_PAGE_SIZE = 100;
7
+ const OPERATION_FIELDS = /* GraphQL */ `
8
+ code
9
+ args {
10
+ name
11
+ value
12
+ }
13
+ `;
14
+ /** One selection for the list and the single read, so both answer the same {@link PaymentMethod}. */
15
+ const METHOD_FIELDS = /* GraphQL */ `
16
+ id
17
+ createdAt
18
+ updatedAt
19
+ code
20
+ name
21
+ description
22
+ enabled
23
+ handler { ${OPERATION_FIELDS} }
24
+ checker { ${OPERATION_FIELDS} }
25
+ translations {
26
+ id
27
+ languageCode
28
+ name
29
+ description
30
+ }
31
+ customFields {
32
+ isNetTermsCredit
33
+ netTermsStaffAnyCustomer
34
+ enabledInStorefront
35
+ }
36
+ `;
37
+ export const PAYMENT_METHODS_QUERY = /* GraphQL */ `
38
+ query StorePaymentMethods($options: PaymentMethodListOptions) {
39
+ paymentMethods(options: $options) {
40
+ items { ${METHOD_FIELDS} }
41
+ totalItems
42
+ }
43
+ }
44
+ `;
45
+ export const PAYMENT_METHOD_QUERY = /* GraphQL */ `
46
+ query StorePaymentMethod($id: ID!) {
47
+ paymentMethod(id: $id) { ${METHOD_FIELDS} }
48
+ }
49
+ `;
50
+ const DEFINITION_FIELDS = /* GraphQL */ `
51
+ code
52
+ description
53
+ args {
54
+ name
55
+ type
56
+ list
57
+ required
58
+ defaultValue
59
+ label
60
+ description
61
+ ui
62
+ }
63
+ `;
64
+ export const PAYMENT_METHOD_HANDLERS_QUERY = /* GraphQL */ `
65
+ query PaymentMethodHandlers {
66
+ paymentMethodHandlers { ${DEFINITION_FIELDS} }
67
+ }
68
+ `;
69
+ export const PAYMENT_METHOD_CHECKERS_QUERY = /* GraphQL */ `
70
+ query PaymentMethodEligibilityCheckers {
71
+ paymentMethodEligibilityCheckers { ${DEFINITION_FIELDS} }
72
+ }
73
+ `;
74
+ export const PAYMENT_METHOD_CREDENTIAL_PATH_QUERY = /* GraphQL */ `
75
+ query PaymentMethodCredentialPath($code: String!) {
76
+ paymentMethods(options: { filter: { code: { eq: $code } }, take: 1 }) {
77
+ items {
78
+ code
79
+ customFields {
80
+ mollieCredentialPath
81
+ }
82
+ }
83
+ }
84
+ }
85
+ `;
86
+ export const SET_PAYMENT_METHOD_CREDENTIAL_PATH_MUTATION = /* GraphQL */ `
87
+ mutation SetPaymentMethodCredentialPath(
88
+ $paymentMethodCode: String!
89
+ $path: PaymentMethodCredentialPath!
90
+ ) {
91
+ setPaymentMethodCredentialPath(paymentMethodCode: $paymentMethodCode, path: $path) {
92
+ paymentMethodCode
93
+ credentialPath
94
+ }
95
+ }
96
+ `;
97
+ export const CREATE_PAYMENT_METHOD_MUTATION = /* GraphQL */ `
98
+ mutation CreateStorePaymentMethod($input: CreatePaymentMethodInput!) {
99
+ createPaymentMethod(input: $input) { ${METHOD_FIELDS} }
100
+ }
101
+ `;
102
+ export const UPDATE_PAYMENT_METHOD_MUTATION = /* GraphQL */ `
103
+ mutation UpdateStorePaymentMethod($input: UpdatePaymentMethodInput!) {
104
+ updatePaymentMethod(input: $input) { ${METHOD_FIELDS} }
105
+ }
106
+ `;
107
+ // `force: false`, written into the document: in the default channel `true` deletes a method
108
+ // other stores still hold, and no caller of this SDK may ask for that.
109
+ export const DELETE_PAYMENT_METHOD_MUTATION = /* GraphQL */ `
110
+ mutation DeleteStorePaymentMethod($id: ID!) {
111
+ deletePaymentMethod(id: $id, force: false) {
112
+ result
113
+ message
114
+ }
115
+ }
116
+ `;
117
+ export const DELETE_PAYMENT_METHODS_MUTATION = /* GraphQL */ `
118
+ mutation DeleteStorePaymentMethods($ids: [ID!]!) {
119
+ deletePaymentMethods(ids: $ids, force: false) {
120
+ result
121
+ message
122
+ }
123
+ }
124
+ `;
125
+ export const ASSIGN_PAYMENT_METHODS_TO_CHANNEL_MUTATION = /* GraphQL */ `
126
+ mutation AssignPaymentMethodsToStore($input: AssignPaymentMethodsToChannelInput!) {
127
+ assignPaymentMethodsToChannel(input: $input) { ${METHOD_FIELDS} }
128
+ }
129
+ `;
130
+ export const REMOVE_PAYMENT_METHODS_FROM_CHANNEL_MUTATION = /* GraphQL */ `
131
+ mutation RemovePaymentMethodsFromStore($input: RemovePaymentMethodsFromChannelInput!) {
132
+ removePaymentMethodsFromChannel(input: $input) { ${METHOD_FIELDS} }
133
+ }
134
+ `;
135
+ const invalidInput = (message) => new ValidationError({
136
+ code: 'INVALID_PAYMENT_METHOD_INPUT',
137
+ message,
138
+ status: 400,
139
+ service: 'vendure',
140
+ });
141
+ const isObject = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
142
+ const isIdList = (value) => Array.isArray(value) && value.every((id) => typeof id === 'string' && id !== '');
143
+ const FLAGS = ['isNetTermsCredit', 'netTermsStaffAnyCustomer', 'enabledInStorefront'];
144
+ /** A handler or checker as the engine takes it, checked here so a wrong shape never leaves. */
145
+ function operationInput(value, what) {
146
+ if (!isObject(value) || typeof value.code !== 'string' || value.code === '') {
147
+ throw invalidInput(`${what} needs a code.`);
148
+ }
149
+ const args = value.arguments;
150
+ if (!Array.isArray(args) ||
151
+ !args.every((arg) => isObject(arg) && typeof arg.name === 'string' && typeof arg.value === 'string')) {
152
+ throw invalidInput(`${what}.arguments must be a list of { name, value } strings (a list or a boolean JSON-encoded).`);
153
+ }
154
+ return {
155
+ code: value.code,
156
+ arguments: args.map((arg) => ({ name: String(arg.name), value: String(arg.value) })),
157
+ };
158
+ }
159
+ function translationsInput(value) {
160
+ if (!Array.isArray(value) ||
161
+ !value.every((row) => isObject(row) &&
162
+ typeof row.languageCode === 'string' &&
163
+ row.languageCode !== '' &&
164
+ typeof row.name === 'string' &&
165
+ (row.description === undefined || typeof row.description === 'string'))) {
166
+ throw invalidInput('translations must be a list of { languageCode, name, description? } with strings.');
167
+ }
168
+ return value.map((row) => ({
169
+ languageCode: String(row.languageCode),
170
+ name: String(row.name),
171
+ description: typeof row.description === 'string' ? row.description : '',
172
+ }));
173
+ }
174
+ /**
175
+ * The fields both writes share, in the engine's shape: the three flags under `customFields`,
176
+ * the checker kept as null (which an update reads as "take it away").
177
+ */
178
+ function sharedInput(input) {
179
+ const out = {};
180
+ if (input.code !== undefined) {
181
+ if (typeof input.code !== 'string')
182
+ throw invalidInput('code must be a string.');
183
+ out.code = input.code;
184
+ }
185
+ if (input.enabled !== undefined) {
186
+ if (typeof input.enabled !== 'boolean')
187
+ throw invalidInput('enabled must be true or false.');
188
+ out.enabled = input.enabled;
189
+ }
190
+ if (input.handler !== undefined)
191
+ out.handler = operationInput(input.handler, 'handler');
192
+ if (input.checker === null)
193
+ out.checker = null;
194
+ else if (input.checker !== undefined)
195
+ out.checker = operationInput(input.checker, 'checker');
196
+ if (input.translations !== undefined)
197
+ out.translations = translationsInput(input.translations);
198
+ const customFields = {};
199
+ for (const flag of FLAGS) {
200
+ const value = input[flag];
201
+ if (value === undefined)
202
+ continue;
203
+ if (typeof value !== 'boolean')
204
+ throw invalidInput(`${flag} must be true or false.`);
205
+ customFields[flag] = value;
206
+ }
207
+ if (Object.keys(customFields).length > 0)
208
+ out.customFields = customFields;
209
+ return out;
210
+ }
211
+ function assignmentInput(ids, channelId) {
212
+ if (!isIdList(ids))
213
+ throw invalidInput('ids must be a list of payment method ids.');
214
+ if (typeof channelId !== 'string' || channelId === '') {
215
+ throw invalidInput("channelId must be the receiving store's channel id.");
216
+ }
217
+ return [...ids];
218
+ }
219
+ const asPath = (value) => value === 'connect' ? 'connect' : 'api_key';
220
+ const toMethod = (method) => ({
221
+ id: method.id,
222
+ code: method.code,
223
+ name: method.name,
224
+ description: method.description,
225
+ enabled: method.enabled,
226
+ handlerCode: method.handler.code,
227
+ // As answered: the engine has already masked each secret argument for this caller.
228
+ handler: method.handler,
229
+ checker: method.checker ?? null,
230
+ translations: method.translations,
231
+ // A flag the engine did not answer reads as its column's default: the two net-terms flags
232
+ // off, the storefront flag on.
233
+ isNetTermsCredit: method.customFields?.isNetTermsCredit === true,
234
+ netTermsStaffAnyCustomer: method.customFields?.netTermsStaffAnyCustomer === true,
235
+ enabledInStorefront: method.customFields?.enabledInStorefront !== false,
236
+ createdAt: method.createdAt,
237
+ updatedAt: method.updatedAt,
238
+ });
239
+ /** A complete array behind the SDK's page shape: the engine lists every definition at once. */
240
+ function wholeList(items, what) {
241
+ return createPage(items, { nextCursor: null, hasNext: false, total: items.length }, () => {
242
+ // Unreachable while `hasNext` is false: `Page.next()` short-circuits.
243
+ throw new Error(`${what} returns a complete list; there is no next page`);
244
+ });
245
+ }
246
+ export function createPaymentMethodsModule(transport) {
247
+ return {
248
+ providerKeys: createProviderKeysModule(transport),
249
+ mollie: createMollieMethodsModule(transport),
250
+ list(options) {
251
+ return vendureListPage(transport, PAYMENT_METHODS_QUERY, 'paymentMethods', (skip, take) => ({ options: { skip, take } }), { ...options, limit: options?.limit ?? DEFAULT_PAGE_SIZE }, toMethod);
252
+ },
253
+ async get(id, options) {
254
+ const method = await fieldOf(transport, PAYMENT_METHOD_QUERY, 'paymentMethod', { id }, options);
255
+ return method ? toMethod(method) : null;
256
+ },
257
+ async handlers(options) {
258
+ return wholeList(await fieldOf(transport, PAYMENT_METHOD_HANDLERS_QUERY, 'paymentMethodHandlers', {}, options), 'paymentMethodHandlers');
259
+ },
260
+ async checkers(options) {
261
+ return wholeList(await fieldOf(transport, PAYMENT_METHOD_CHECKERS_QUERY, 'paymentMethodEligibilityCheckers', {}, options), 'paymentMethodEligibilityCheckers');
262
+ },
263
+ async credentialPath(paymentMethodCode, options) {
264
+ const data = await transport.graphql({
265
+ api: 'admin',
266
+ query: PAYMENT_METHOD_CREDENTIAL_PATH_QUERY,
267
+ variables: { code: paymentMethodCode },
268
+ }, options);
269
+ // `eq` is not guaranteed case-sensitive on every driver: the code is matched here too.
270
+ const method = data.paymentMethods.items.find((item) => item.code === paymentMethodCode);
271
+ return method ? asPath(method.customFields?.mollieCredentialPath) : null;
272
+ },
273
+ async setCredentialPath(paymentMethodCode, path, options) {
274
+ const data = await transport.graphql({
275
+ api: 'admin',
276
+ query: SET_PAYMENT_METHOD_CREDENTIAL_PATH_MUTATION,
277
+ variables: { paymentMethodCode, path },
278
+ }, options);
279
+ return {
280
+ paymentMethodCode: data.setPaymentMethodCredentialPath.paymentMethodCode,
281
+ credentialPath: asPath(data.setPaymentMethodCredentialPath.credentialPath),
282
+ };
283
+ },
284
+ async create(input, options) {
285
+ if (!isObject(input))
286
+ throw invalidInput('A new payment method must be an object.');
287
+ if (typeof input.code !== 'string')
288
+ throw invalidInput('A payment method needs a code.');
289
+ if (typeof input.enabled !== 'boolean') {
290
+ throw invalidInput('A new payment method says whether it is enabled.');
291
+ }
292
+ if (input.handler === undefined)
293
+ throw invalidInput('A payment method needs a handler.');
294
+ if (input.translations === undefined) {
295
+ throw invalidInput('A payment method needs its name in at least one language.');
296
+ }
297
+ const wireInput = sharedInput(input);
298
+ // Core's create takes no null checker: "none" is leaving it out.
299
+ if (wireInput.checker === null)
300
+ delete wireInput.checker;
301
+ return toMethod(await fieldOf(transport, CREATE_PAYMENT_METHOD_MUTATION, 'createPaymentMethod', { input: wireInput }, options));
302
+ },
303
+ async update(id, patch, options) {
304
+ if (typeof id !== 'string' || id === '')
305
+ throw invalidInput('id must be a payment method id.');
306
+ if (!isObject(patch))
307
+ throw invalidInput('The change to a payment method must be an object.');
308
+ return toMethod(await fieldOf(transport, UPDATE_PAYMENT_METHOD_MUTATION, 'updatePaymentMethod', { input: { id, ...sharedInput(patch) } }, options));
309
+ },
310
+ async delete(id, options) {
311
+ if (typeof id !== 'string' || id === '')
312
+ throw invalidInput('id must be a payment method id.');
313
+ assertDeleted('PAYMENT_METHOD_NOT_DELETED', [
314
+ await fieldOf(transport, DELETE_PAYMENT_METHOD_MUTATION, 'deletePaymentMethod', { id }, options),
315
+ ]);
316
+ },
317
+ async deleteMany(ids, options) {
318
+ if (!isIdList(ids))
319
+ throw invalidInput('ids must be a list of payment method ids.');
320
+ if (ids.length === 0)
321
+ return;
322
+ const responses = await fieldOf(transport, DELETE_PAYMENT_METHODS_MUTATION, 'deletePaymentMethods', { ids: [...ids] }, options);
323
+ // One answer per id, in the order sent. A missing answer is not a removal.
324
+ const kept = ids.flatMap((id, index) => {
325
+ const response = Array.isArray(responses) ? responses[index] : undefined;
326
+ return response?.result === 'DELETED'
327
+ ? []
328
+ : [{ id, index, reason: response?.message ?? 'The server gave no reason.' }];
329
+ });
330
+ if (kept.length === 0)
331
+ return;
332
+ // Answered at HTTP 200, so the transport never throws for it: the ids not named here WERE
333
+ // removed.
334
+ throw new ConflictError({
335
+ code: 'PAYMENT_METHOD_NOT_DELETED',
336
+ message: kept.length === ids.length
337
+ ? `No payment method was removed: ${kept[0]?.reason ?? ''}`
338
+ : `${String(kept.length)} of ${String(ids.length)} payment methods were not removed (the others were): ${kept[0]?.reason ?? ''}`,
339
+ status: 409,
340
+ service: 'vendure',
341
+ details: kept.map(({ id, index, reason }) => ({
342
+ field: `ids.${String(index)}`,
343
+ code: 'PAYMENT_METHOD_NOT_DELETED',
344
+ message: `${id}: ${reason}`,
345
+ })),
346
+ });
347
+ },
348
+ async assignToStores(ids, channelId, options) {
349
+ const paymentMethodIds = assignmentInput(ids, channelId);
350
+ if (paymentMethodIds.length === 0)
351
+ return [];
352
+ const methods = await fieldOf(transport, ASSIGN_PAYMENT_METHODS_TO_CHANNEL_MUTATION, 'assignPaymentMethodsToChannel', { input: { paymentMethodIds, channelId } }, options);
353
+ return methods.map(toMethod);
354
+ },
355
+ async removeFromStores(ids, channelId, options) {
356
+ const paymentMethodIds = assignmentInput(ids, channelId);
357
+ if (paymentMethodIds.length === 0)
358
+ return [];
359
+ const methods = await fieldOf(transport, REMOVE_PAYMENT_METHODS_FROM_CHANNEL_MUTATION, 'removePaymentMethodsFromChannel', { input: { paymentMethodIds, channelId } }, options);
360
+ return methods.map(toMethod);
361
+ },
362
+ };
363
+ }
@@ -0,0 +1,159 @@
1
+ import { type Transport } from '@sixtyninecommerce/core';
2
+ import type { Call } from '../types.js';
3
+ /** Why Mollie's own answer is missing: the method has nothing to ask with, or Mollie refused. */
4
+ export type MollieProbeErrorKind = 'no_key' | 'auth' | 'network' | 'provider';
5
+ /** What went wrong asking Mollie, in the engine's classification. */
6
+ export interface MollieProbeError {
7
+ /**
8
+ * `no_key`: nothing to ask with (no such method in the store, not a Mollie method, no key, or
9
+ * a Connect-path method whose store has no Mollie account connected); `auth`: Mollie refused
10
+ * the key or the Connect grant; `network`: Mollie did not answer; `provider`: Mollie answered
11
+ * with an error. An unknown kind reads `provider`.
12
+ */
13
+ kind: MollieProbeErrorKind;
14
+ /** In the engine's or Mollie's words. */
15
+ message: string;
16
+ /** Mollie's real HTTP status when it answered; null otherwise. */
17
+ statusCode: number | null;
18
+ }
19
+ /** One checkout method of the Mollie account, with the store's choice to hide it. */
20
+ export interface MollieMethod {
21
+ /** Mollie's method id: `ideal`, `creditcard`, `klarnapaylater`, … */
22
+ id: string;
23
+ description: string | null;
24
+ /** Mollie's icon for it (SVG preferred); null when Mollie gave none. */
25
+ imageUrl: string | null;
26
+ /** The store hides it at checkout (`setMethods`). */
27
+ hidden: boolean;
28
+ /**
29
+ * Mollie's activation status: `activated`, `pending-boarding`, `pending-review`,
30
+ * `pending-external` or `rejected`; null when Mollie gave none.
31
+ */
32
+ status: string | null;
33
+ /** Usable now: `activated`, or no status given. */
34
+ available: boolean;
35
+ }
36
+ /** The method list of one Mollie payment method, in the store's checkout order. */
37
+ export interface MollieMethodList {
38
+ /**
39
+ * Mollie's one-off (checkout) methods merged with the saved order, hidden ones included.
40
+ * Mandate-only methods (SEPA `directdebit`) are never here: see `diagnose`.
41
+ */
42
+ methods: MollieMethod[];
43
+ /**
44
+ * Why Mollie's list is missing, or null. An empty `methods` with a null `error` means Mollie
45
+ * answered and offers no method on this profile.
46
+ */
47
+ error: MollieProbeError | null;
48
+ }
49
+ /** The checkout order and the hidden methods, each as Mollie's method ids. */
50
+ export interface SetMollieMethodsInput {
51
+ /** Every method id, in the order the checkout shows them. */
52
+ order: string[];
53
+ /** The method ids the checkout hides. */
54
+ hidden: string[];
55
+ }
56
+ /** One method of the account across Mollie's three payment sequences. */
57
+ export interface MollieDiagnosisMethod {
58
+ id: string;
59
+ description: string | null;
60
+ /** Mollie's activation status, when its list of every method gave one. */
61
+ status: string | null;
62
+ /** Offered for a regular checkout payment. */
63
+ oneoff: boolean;
64
+ /** Offered as the first payment of a recurring sequence (it creates a mandate). */
65
+ first: boolean;
66
+ /** Offered for charging an existing mandate. */
67
+ recurring: boolean;
68
+ }
69
+ /** SEPA Direct Debit (`directdebit`) as each probe saw it. */
70
+ export interface MollieDirectDebitDiagnosis {
71
+ availableOneoff: boolean;
72
+ availableFirst: boolean;
73
+ availableRecurring: boolean;
74
+ status: string | null;
75
+ /** What Mollie answered for `directdebit` itself: `ok`, `forbidden`, `not_found` or `error`. */
76
+ getProbe: string;
77
+ }
78
+ /**
79
+ * The headline answer, about SEPA Direct Debit at checkout:
80
+ * `CHECKOUT_TILE_AVAILABLE`, `CHECKOUT_TILE_PENDING_ACTIVATION`, `MANDATE_ONLY`,
81
+ * `NOT_ON_ACCOUNT`, `INDETERMINATE`, `REJECTED`, `UNKNOWN_KEY_ERROR` (every probe refused, or
82
+ * nothing to probe with) or `UNREACHABLE`. A verdict the engine adds later is passed through.
83
+ */
84
+ export type MollieDiagnosisVerdict = 'CHECKOUT_TILE_AVAILABLE' | 'CHECKOUT_TILE_PENDING_ACTIVATION' | 'MANDATE_ONLY' | 'NOT_ON_ACCOUNT' | 'INDETERMINATE' | 'REJECTED' | 'UNKNOWN_KEY_ERROR' | 'UNREACHABLE';
85
+ /** What Mollie's account offers for each payment sequence, and the verdict drawn from it. */
86
+ export interface MollieDiagnosis {
87
+ /** Every probe succeeded. */
88
+ ok: boolean;
89
+ /** From the key's prefix only (`test_`, `live_`); `unknown` without a key. */
90
+ keyMode: 'test' | 'live' | 'unknown';
91
+ /** The first probe's failure, or null. */
92
+ error: MollieProbeError | null;
93
+ methods: MollieDiagnosisMethod[];
94
+ directDebit: MollieDirectDebitDiagnosis;
95
+ verdict: MollieDiagnosisVerdict;
96
+ /** When the probes ran (ISO 8601, UTC). */
97
+ probedAt: string;
98
+ }
99
+ /**
100
+ * The checkout methods a Mollie payment method offers, their order and visibility, and a
101
+ * diagnosis of the Mollie account (headless spec §9.2 `payments`). Scoped to the store the
102
+ * client is on. Configuration only: nothing here moves money.
103
+ *
104
+ * Every call is refused `PLUGIN_ACCESS_DENIED` (`PermissionDeniedError`, 403) for a store that
105
+ * does not hold the Mollie plugin.
106
+ */
107
+ export interface MollieMethodsModule {
108
+ /**
109
+ * Mollie's checkout methods for one payment method, merged with the store's saved order and
110
+ * hidden list. Asked with the method's own API key, or through the store's Mollie Connect
111
+ * account when the method pays through it (`credentialPath: 'connect'`). Goes to Mollie on
112
+ * every call. Needs `ReadPaymentMethod`.
113
+ *
114
+ * Never throws for Mollie's answer: a refused key or grant, Mollie not answering, a method
115
+ * with nothing to ask with, a code the store has no method for and a method that is not
116
+ * Mollie's all answer an empty or saved-only `methods` with `error` saying why.
117
+ *
118
+ * @effect read
119
+ * @permission ReadPaymentMethod
120
+ */
121
+ methods(paymentMethodCode: string, options?: Call): Promise<MollieMethodList>;
122
+ /**
123
+ * Save the checkout order and the hidden methods of one payment method, and answer the list
124
+ * as {@link methods} reads it (so it asks Mollie again). The lists are stored as sent: an id
125
+ * Mollie does not offer is kept, and a method Mollie offers that `order` leaves out is shown
126
+ * after the ordered ones. Needs `UpdatePaymentMethod`.
127
+ *
128
+ * Refused, with nothing saved:
129
+ *
130
+ * - `USER_INPUT_ERROR` (`ValidationError`, 400): the store has no method with that code.
131
+ * - `SHARED_PAYMENT_METHOD_NOT_ALLOWED` (`PermissionDeniedError`, 403): another store holds
132
+ * the method and the caller may not change it there.
133
+ * - `INVALID_MOLLIE_METHODS_INPUT` (`ValidationError`, 400), before sending: `order` or
134
+ * `hidden` is not a list of strings.
135
+ *
136
+ * @effect write
137
+ * @permission UpdatePaymentMethod
138
+ */
139
+ setMethods(paymentMethodCode: string, input: SetMollieMethodsInput, options?: Call): Promise<MollieMethodList>;
140
+ /**
141
+ * Ask Mollie, with the method's own API key, which methods it offers for each payment
142
+ * sequence (one-off, first, recurring), and draw a verdict on SEPA Direct Debit. Five calls
143
+ * to Mollie; changes nothing, here or at Mollie. A method paying through Mollie Connect is
144
+ * still diagnosed with its key: without one the answer is `UNKNOWN_KEY_ERROR`.
145
+ *
146
+ * Never throws for Mollie's answer (it is in `error` and `verdict`). It throws only when the
147
+ * call is refused: `USER_INPUT_ERROR` (`ValidationError`, 400) for a code the store has no
148
+ * method for, `FORBIDDEN` (`PermissionDeniedError`, 403) without `UpdatePaymentMethod`, which
149
+ * it needs because it uses the stored key, and `PLUGIN_ACCESS_DENIED` (403).
150
+ *
151
+ * @effect read
152
+ * @permission UpdatePaymentMethod
153
+ */
154
+ diagnose(paymentMethodCode: string, options?: Call): Promise<MollieDiagnosis>;
155
+ }
156
+ export declare const MOLLIE_METHODS_QUERY = "\n query MollieMethodList($paymentMethodCode: String!) {\n mollieMethods(paymentMethodCode: $paymentMethodCode) { \n methods {\n id\n description\n imageUrl\n hidden\n status\n available\n }\n \n error {\n kind\n message\n statusCode\n }\n\n }\n }\n";
157
+ export declare const SET_MOLLIE_METHODS_MUTATION = "\n mutation SetMollieMethodList($input: SetMollieMethodsInput!) {\n setMollieMethods(input: $input) { \n methods {\n id\n description\n imageUrl\n hidden\n status\n available\n }\n \n error {\n kind\n message\n statusCode\n }\n\n }\n }\n";
158
+ export declare const MOLLIE_DIAGNOSTICS_QUERY = "\n query MollieDiagnosis($paymentMethodCode: String!) {\n mollieDiagnostics(paymentMethodCode: $paymentMethodCode) {\n ok\n keyMode\n \n error {\n kind\n message\n statusCode\n }\n\n methods {\n id\n description\n status\n oneoff\n first\n recurring\n }\n directDebit {\n availableOneoff\n availableFirst\n availableRecurring\n status\n getProbe\n }\n verdict\n probedAt\n }\n }\n";
159
+ export declare function createMollieMethodsModule(transport: Transport): MollieMethodsModule;
@@ -0,0 +1,141 @@
1
+ import { ValidationError } from '@sixtyninecommerce/core';
2
+ import { fieldOf } from '../catalog/types.js';
3
+ const PROBE_ERROR_FIELDS = /* GraphQL */ `
4
+ error {
5
+ kind
6
+ message
7
+ statusCode
8
+ }
9
+ `;
10
+ const LIST_FIELDS = /* GraphQL */ `
11
+ methods {
12
+ id
13
+ description
14
+ imageUrl
15
+ hidden
16
+ status
17
+ available
18
+ }
19
+ ${PROBE_ERROR_FIELDS}
20
+ `;
21
+ export const MOLLIE_METHODS_QUERY = /* GraphQL */ `
22
+ query MollieMethodList($paymentMethodCode: String!) {
23
+ mollieMethods(paymentMethodCode: $paymentMethodCode) { ${LIST_FIELDS} }
24
+ }
25
+ `;
26
+ export const SET_MOLLIE_METHODS_MUTATION = /* GraphQL */ `
27
+ mutation SetMollieMethodList($input: SetMollieMethodsInput!) {
28
+ setMollieMethods(input: $input) { ${LIST_FIELDS} }
29
+ }
30
+ `;
31
+ export const MOLLIE_DIAGNOSTICS_QUERY = /* GraphQL */ `
32
+ query MollieDiagnosis($paymentMethodCode: String!) {
33
+ mollieDiagnostics(paymentMethodCode: $paymentMethodCode) {
34
+ ok
35
+ keyMode
36
+ ${PROBE_ERROR_FIELDS}
37
+ methods {
38
+ id
39
+ description
40
+ status
41
+ oneoff
42
+ first
43
+ recurring
44
+ }
45
+ directDebit {
46
+ availableOneoff
47
+ availableFirst
48
+ availableRecurring
49
+ status
50
+ getProbe
51
+ }
52
+ verdict
53
+ probedAt
54
+ }
55
+ }
56
+ `;
57
+ const invalidInput = (message) => new ValidationError({
58
+ code: 'INVALID_MOLLIE_METHODS_INPUT',
59
+ message,
60
+ status: 400,
61
+ service: 'vendure',
62
+ });
63
+ const requireCode = (value) => {
64
+ if (typeof value !== 'string' || value === '') {
65
+ throw invalidInput('paymentMethodCode must be the code of a payment method.');
66
+ }
67
+ return value;
68
+ };
69
+ const requireIds = (value, name) => {
70
+ if (!Array.isArray(value) || value.some((id) => typeof id !== 'string')) {
71
+ throw invalidInput(`${name} must be a list of Mollie method ids.`);
72
+ }
73
+ return [...value];
74
+ };
75
+ const KINDS = ['no_key', 'auth', 'network', 'provider'];
76
+ const toError = (wire) => wire
77
+ ? {
78
+ kind: KINDS.includes(wire.kind)
79
+ ? wire.kind
80
+ : 'provider',
81
+ message: wire.message,
82
+ statusCode: wire.statusCode ?? null,
83
+ }
84
+ : null;
85
+ const toList = (wire) => ({
86
+ methods: wire.methods.map((method) => ({
87
+ id: method.id,
88
+ description: method.description ?? null,
89
+ imageUrl: method.imageUrl ?? null,
90
+ hidden: method.hidden,
91
+ status: method.status ?? null,
92
+ available: method.available,
93
+ })),
94
+ error: toError(wire.error),
95
+ });
96
+ const toDiagnosis = (wire) => ({
97
+ ok: wire.ok,
98
+ keyMode: wire.keyMode === 'test' || wire.keyMode === 'live' ? wire.keyMode : 'unknown',
99
+ error: toError(wire.error),
100
+ methods: wire.methods.map((method) => ({
101
+ id: method.id,
102
+ description: method.description ?? null,
103
+ status: method.status ?? null,
104
+ oneoff: method.oneoff,
105
+ first: method.first,
106
+ recurring: method.recurring,
107
+ })),
108
+ directDebit: {
109
+ availableOneoff: wire.directDebit.availableOneoff,
110
+ availableFirst: wire.directDebit.availableFirst,
111
+ availableRecurring: wire.directDebit.availableRecurring,
112
+ status: wire.directDebit.status ?? null,
113
+ getProbe: wire.directDebit.getProbe,
114
+ },
115
+ // Passed through: a verdict the engine adds later is still the engine's answer.
116
+ verdict: wire.verdict,
117
+ probedAt: wire.probedAt,
118
+ });
119
+ export function createMollieMethodsModule(transport) {
120
+ return {
121
+ async methods(paymentMethodCode, options) {
122
+ return toList(await fieldOf(transport, MOLLIE_METHODS_QUERY, 'mollieMethods', { paymentMethodCode: requireCode(paymentMethodCode) }, options));
123
+ },
124
+ async setMethods(paymentMethodCode, input, options) {
125
+ const code = requireCode(paymentMethodCode);
126
+ if (typeof input !== 'object' || input === null || Array.isArray(input)) {
127
+ throw invalidInput('setMethods takes { order, hidden }.');
128
+ }
129
+ return toList(await fieldOf(transport, SET_MOLLIE_METHODS_MUTATION, 'setMollieMethods', {
130
+ input: {
131
+ paymentMethodCode: code,
132
+ order: requireIds(input.order, 'order'),
133
+ hidden: requireIds(input.hidden, 'hidden'),
134
+ },
135
+ }, options));
136
+ },
137
+ async diagnose(paymentMethodCode, options) {
138
+ return toDiagnosis(await fieldOf(transport, MOLLIE_DIAGNOSTICS_QUERY, 'mollieDiagnostics', { paymentMethodCode: requireCode(paymentMethodCode) }, options));
139
+ },
140
+ };
141
+ }