@hartl-services/medusa-base 0.3.0 → 1.0.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 (323) hide show
  1. package/.medusa/server/src/admin/index.js +2164 -29
  2. package/.medusa/server/src/admin/index.mjs +2166 -31
  3. package/.medusa/server/src/api/admin/email/messages/[id]/resends/route.js +24 -0
  4. package/.medusa/server/src/api/admin/email/messages/[id]/route.js +12 -0
  5. package/.medusa/server/src/api/admin/email/messages/route.js +12 -0
  6. package/.medusa/server/src/api/admin/email/terms-versions/[id]/download/route.js +16 -0
  7. package/.medusa/server/src/api/admin/email/terms-versions/route.js +47 -0
  8. package/.medusa/server/src/api/admin/orders/[id]/documents/[document_id]/download/route.js +21 -0
  9. package/.medusa/server/src/api/admin/orders/[id]/documents/[document_id]/regenerate/route.js +38 -0
  10. package/.medusa/server/src/api/admin/orders/[id]/documents/regenerate/route.js +32 -0
  11. package/.medusa/server/src/api/admin/orders/[id]/documents/route.js +36 -0
  12. package/.medusa/server/src/api/admin/orders/[id]/packing-lists/[fulfillment_id]/download/route.js +24 -0
  13. package/.medusa/server/src/api/admin/orders/[id]/packing-lists/[fulfillment_id]/retry/route.js +44 -0
  14. package/.medusa/server/src/api/admin/orders/[id]/packing-lists/route.js +82 -0
  15. package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/actions/[action_key]/route.js +31 -0
  16. package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/actions/[action_key]/runs/route.js +16 -0
  17. package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/route.js +14 -0
  18. package/.medusa/server/src/api/admin/plugin-features/[plugin_key]/settings/route.js +22 -0
  19. package/.medusa/server/src/api/admin/plugin-features/route.js +6 -4
  20. package/.medusa/server/src/api/document-download-response.js +16 -0
  21. package/.medusa/server/src/api/document-response.js +23 -0
  22. package/.medusa/server/src/api/files/[asset]/route.js +24 -0
  23. package/.medusa/server/src/api/files/file-response.js +43 -0
  24. package/.medusa/server/src/api/files/gateway-options.js +31 -0
  25. package/.medusa/server/src/api/files/private/[token]/route.js +29 -0
  26. package/.medusa/server/src/api/files/upload/[token]/route.js +66 -0
  27. package/.medusa/server/src/api/middlewares.js +186 -5
  28. package/.medusa/server/src/api/packing-list-response.js +22 -0
  29. package/.medusa/server/src/api/plugin-actions.js +221 -0
  30. package/.medusa/server/src/api/plugin-features-http.js +67 -8
  31. package/.medusa/server/src/api/route.js +27 -0
  32. package/.medusa/server/src/api/store/documents/[id]/download/route.js +21 -0
  33. package/.medusa/server/src/api/store/documents/[id]/route.js +15 -0
  34. package/.medusa/server/src/api/store/documents/route.js +11 -0
  35. package/.medusa/server/src/api/terms-download-response.js +12 -0
  36. package/.medusa/server/src/documents/config/index.js +18 -0
  37. package/.medusa/server/src/documents/paths/documents.js +6 -0
  38. package/.medusa/server/src/documents/paths/index.js +18 -0
  39. package/.medusa/server/src/documents/plugin-features.js +24 -0
  40. package/.medusa/server/src/documents/schemas/documents.js +18 -0
  41. package/.medusa/server/src/documents/schemas/index.js +18 -0
  42. package/.medusa/server/src/documents/scripts/verify-documents-file-storage.js +55 -0
  43. package/.medusa/server/src/documents/templates/financial-document.js +142 -0
  44. package/.medusa/server/src/documents/templates/format.js +31 -0
  45. package/.medusa/server/src/documents/templates/html-factory.js +40 -0
  46. package/.medusa/server/src/documents/templates/html-utils.js +13 -0
  47. package/.medusa/server/src/documents/templates/layout.js +97 -0
  48. package/.medusa/server/src/documents/templates/packing-list.js +50 -0
  49. package/.medusa/server/src/documents/types/admin-api.js +3 -0
  50. package/.medusa/server/src/documents/types/document-summary.js +3 -0
  51. package/.medusa/server/src/documents/types/documents.js +3 -0
  52. package/.medusa/server/src/documents/types/html-factory.js +6 -0
  53. package/.medusa/server/src/documents/types/index.js +22 -0
  54. package/.medusa/server/src/documents/types/store-api.js +3 -0
  55. package/.medusa/server/src/documents/utils/document-merchant.js +22 -0
  56. package/.medusa/server/src/documents/utils/html-to-pdf.js +61 -0
  57. package/.medusa/server/src/documents/utils/private-file-storage.js +64 -0
  58. package/.medusa/server/src/documents/utils/resolve-services.js +7 -0
  59. package/.medusa/server/src/email/application/handle-invite-event.js +312 -0
  60. package/.medusa/server/src/email/application/handle-password-reset-event.js +354 -0
  61. package/.medusa/server/src/email/config/index.js +84 -0
  62. package/.medusa/server/src/email/config/notification-module.js +20 -0
  63. package/.medusa/server/src/email/domain/business-keys.js +50 -0
  64. package/.medusa/server/src/email/domain/documents-fact-fingerprint.js +7 -0
  65. package/.medusa/server/src/email/domain/event-schemas.js +36 -0
  66. package/.medusa/server/src/email/domain/failure-classification.js +53 -0
  67. package/.medusa/server/src/email/plugin-features.js +31 -0
  68. package/.medusa/server/src/email/rendering/default-templates.js +91 -0
  69. package/.medusa/server/src/email/rendering/render-email.js +37 -0
  70. package/.medusa/server/src/email/rendering/resolve-shop-configuration.js +48 -0
  71. package/.medusa/server/src/email/types/email-kinds.js +18 -0
  72. package/.medusa/server/src/email/types/index.js +21 -0
  73. package/.medusa/server/src/email/types/shop-configuration.js +3 -0
  74. package/.medusa/server/src/email/types/smtp-configuration.js +3 -0
  75. package/.medusa/server/src/email/types/template-data.js +79 -0
  76. package/.medusa/server/src/files/config/index.js +256 -0
  77. package/.medusa/server/src/files/gateway/index.js +115 -0
  78. package/.medusa/server/src/files/types/index.js +6 -0
  79. package/.medusa/server/src/files/types/public.js +6 -0
  80. package/.medusa/server/src/jobs/document-fact-publication-reconciliation.js +18 -0
  81. package/.medusa/server/src/jobs/document-resolution-reconciliation.js +20 -0
  82. package/.medusa/server/src/jobs/packing-list-reconciliation.js +49 -0
  83. package/.medusa/server/src/jobs/reconcile-email-attempts.js +63 -0
  84. package/.medusa/server/src/jobs/reconcile-pending-email-messages.js +41 -0
  85. package/.medusa/server/src/jobs/retry-email-messages.js +27 -0
  86. package/.medusa/server/src/migration-scripts/dismiss-orphaned-cart-promotion-links.js +26 -0
  87. package/.medusa/server/src/modules/documents/domain/cancellation-snapshot.js +97 -0
  88. package/.medusa/server/src/modules/documents/domain/document-number.js +36 -0
  89. package/.medusa/server/src/modules/documents/domain/document-resolution.js +24 -0
  90. package/.medusa/server/src/modules/documents/domain/issuance-rules.js +37 -0
  91. package/.medusa/server/src/modules/documents/domain/merchant.js +86 -0
  92. package/.medusa/server/src/modules/documents/domain/options.js +40 -0
  93. package/.medusa/server/src/modules/documents/domain/packing-list.js +90 -0
  94. package/.medusa/server/src/modules/documents/domain/snapshot-normalization.js +17 -0
  95. package/.medusa/server/src/modules/documents/domain/tax-breakdown.js +66 -0
  96. package/.medusa/server/src/modules/documents/index.js +15 -0
  97. package/.medusa/server/src/modules/documents/loaders/assert-private-file-storage.js +20 -0
  98. package/.medusa/server/src/modules/documents/migrations/Migration20260827061749.js +75 -0
  99. package/.medusa/server/src/modules/documents/migrations/Migration20260830111207.js +28 -0
  100. package/.medusa/server/src/modules/documents/models/document-artifact.js +25 -0
  101. package/.medusa/server/src/modules/documents/models/document-number-sequence.js +29 -0
  102. package/.medusa/server/src/modules/documents/models/document.js +82 -0
  103. package/.medusa/server/src/modules/documents/models/order-cancellation-resolution.js +51 -0
  104. package/.medusa/server/src/modules/documents/models/packing-list-revision.js +36 -0
  105. package/.medusa/server/src/modules/documents/models/packing-list.js +27 -0
  106. package/.medusa/server/src/modules/documents/models/refund-document-resolution.js +66 -0
  107. package/.medusa/server/src/modules/documents/models/shipment-invoice-assignment.js +51 -0
  108. package/.medusa/server/src/modules/documents/models/shipment-invoice-coordinator.js +44 -0
  109. package/.medusa/server/src/modules/documents/service.js +1701 -0
  110. package/.medusa/server/src/modules/email/domain/attachment.js +25 -0
  111. package/.medusa/server/src/modules/email/domain/message-state.js +69 -0
  112. package/.medusa/server/src/modules/email/index.js +13 -0
  113. package/.medusa/server/src/modules/email/migrations/Migration20260826173422.js +32 -0
  114. package/.medusa/server/src/modules/email/migrations/Migration20260827172945.js +16 -0
  115. package/.medusa/server/src/modules/email/migrations/Migration20260827194804.js +22 -0
  116. package/.medusa/server/src/modules/email/migrations/Migration20260906195205.js +16 -0
  117. package/.medusa/server/src/modules/email/models/email-attempt.js +56 -0
  118. package/.medusa/server/src/modules/email/models/email-message.js +71 -0
  119. package/.medusa/server/src/modules/email/models/email-terms-version.js +37 -0
  120. package/.medusa/server/src/modules/email/service.js +1285 -0
  121. package/.medusa/server/src/modules/plugin-features/domain/plugin-action-runs.js +92 -0
  122. package/.medusa/server/src/modules/plugin-features/domain/plugin-settings.js +213 -0
  123. package/.medusa/server/src/modules/plugin-features/domain/secret-box.js +56 -0
  124. package/.medusa/server/src/modules/plugin-features/migrations/Migration20260928205031.js +16 -0
  125. package/.medusa/server/src/modules/plugin-features/migrations/Migration20260928215428.js +17 -0
  126. package/.medusa/server/src/modules/plugin-features/models/plugin-action-run.js +43 -0
  127. package/.medusa/server/src/modules/plugin-features/models/plugin-setting-state.js +32 -0
  128. package/.medusa/server/src/modules/plugin-features/service.js +419 -17
  129. package/.medusa/server/src/providers/s3-cache/cache/atomic-write.js +25 -0
  130. package/.medusa/server/src/providers/s3-cache/cache/cache-manager.js +115 -0
  131. package/.medusa/server/src/providers/s3-cache/cache/keyed-lock.js +28 -0
  132. package/.medusa/server/src/providers/s3-cache/index.js +8 -0
  133. package/.medusa/server/src/providers/s3-cache/object-key.js +53 -0
  134. package/.medusa/server/src/providers/s3-cache/s3-cache-file.js +229 -0
  135. package/.medusa/server/src/providers/s3-cache/s3-object-store.js +86 -0
  136. package/.medusa/server/src/providers/smtp/index.js +8 -0
  137. package/.medusa/server/src/providers/smtp/service.js +236 -0
  138. package/.medusa/server/src/providers/smtp/types.js +11 -0
  139. package/.medusa/server/src/public/action-progress.js +67 -0
  140. package/.medusa/server/src/public/config.js +186 -0
  141. package/.medusa/server/src/public/descriptor.js +199 -2
  142. package/.medusa/server/src/public/effective-features.js +9 -5
  143. package/.medusa/server/src/public/enforcement.js +18 -8
  144. package/.medusa/server/src/public/gateway.js +19 -0
  145. package/.medusa/server/src/public/index.js +10 -2
  146. package/.medusa/server/src/public/instrumentation.js +56 -0
  147. package/.medusa/server/src/public/module-access.js +14 -0
  148. package/.medusa/server/src/public/settings.js +17 -0
  149. package/.medusa/server/src/public/shop-config.js +12 -0
  150. package/.medusa/server/src/public/shop-master-data.js +95 -0
  151. package/.medusa/server/src/public/shop-types.js +24 -0
  152. package/.medusa/server/src/shop-config/build-food-shop-config.js +248 -0
  153. package/.medusa/server/src/shop-config/options.js +71 -0
  154. package/.medusa/server/src/subscribers/affiliate-consignment-reminder-due.js +26 -0
  155. package/.medusa/server/src/subscribers/documents-order-canceled.js +24 -0
  156. package/.medusa/server/src/subscribers/documents-order-cancellation-ready.js +26 -0
  157. package/.medusa/server/src/subscribers/documents-refund-ready.js +24 -0
  158. package/.medusa/server/src/subscribers/documents-shipment-created.js +36 -0
  159. package/.medusa/server/src/subscribers/documents-shipment-invoice-assignment-decided.js +26 -0
  160. package/.medusa/server/src/subscribers/email-order-canceled.js +28 -0
  161. package/.medusa/server/src/subscribers/email-shipment-created.js +32 -0
  162. package/.medusa/server/src/subscribers/order-placed.js +27 -0
  163. package/.medusa/server/src/subscribers/packing-list-allocation-revised.js +32 -0
  164. package/.medusa/server/src/subscribers/packing-list-fulfillment-canceled.js +54 -0
  165. package/.medusa/server/src/subscribers/packing-list-fulfillment-created.js +31 -0
  166. package/.medusa/server/src/subscribers/password-reset.js +23 -0
  167. package/.medusa/server/src/subscribers/payment-refunded.js +38 -0
  168. package/.medusa/server/src/subscribers/return-received.js +27 -0
  169. package/.medusa/server/src/subscribers/return-requested.js +27 -0
  170. package/.medusa/server/src/subscribers/user-invite.js +23 -0
  171. package/.medusa/server/src/utils/cart-promotion-links.js +101 -0
  172. package/.medusa/server/src/utils/discover-complete-cart-participants.js +9 -2
  173. package/.medusa/server/src/utils/discover-plugin-features.js +47 -9
  174. package/.medusa/server/src/workflows/documents/issue-cancellation-after-refund.js +246 -0
  175. package/.medusa/server/src/workflows/documents/issue-document.js +163 -0
  176. package/.medusa/server/src/workflows/documents/issue-invoice-after-shipment.js +521 -0
  177. package/.medusa/server/src/workflows/documents/issue-packing-list.js +384 -0
  178. package/.medusa/server/src/workflows/documents/publish-document-facts.js +53 -0
  179. package/.medusa/server/src/workflows/documents/reconcile-document-resolutions.js +48 -0
  180. package/.medusa/server/src/workflows/documents/reconcile-order-cancellation.js +92 -0
  181. package/.medusa/server/src/workflows/documents/regenerate-issued-document.js +61 -0
  182. package/.medusa/server/src/workflows/email/dispatch-email-message.js +299 -0
  183. package/.medusa/server/src/workflows/email/documents-required-facts.js +30 -0
  184. package/.medusa/server/src/workflows/email/prepare-affiliate-reminder-email.js +58 -0
  185. package/.medusa/server/src/workflows/email/prepare-order-canceled-email.js +64 -0
  186. package/.medusa/server/src/workflows/email/prepare-order-received-email.js +56 -0
  187. package/.medusa/server/src/workflows/email/prepare-refund-email.js +47 -0
  188. package/.medusa/server/src/workflows/email/prepare-return-email.js +75 -0
  189. package/.medusa/server/src/workflows/email/prepare-shipment-email.js +82 -0
  190. package/.medusa/server/src/workflows/email/retry-email-messages.js +31 -0
  191. package/.medusa/server/src/workflows/hooks/complete-cart-participants.js +28 -16
  192. package/.medusa/server/src/workflows/hooks/dismiss-deleted-promotion-cart-links.js +23 -0
  193. package/README.md +2004 -11
  194. package/dist/admin-components/features/plugin-features/components/PluginActionsSection.d.ts +6 -0
  195. package/dist/admin-components/features/plugin-features/components/PluginActionsSection.js +66 -0
  196. package/dist/admin-components/features/plugin-features/components/PluginDetailPage.d.ts +2 -0
  197. package/dist/admin-components/features/plugin-features/components/PluginDetailPage.js +9 -0
  198. package/dist/admin-components/features/plugin-features/components/PluginFeatureGate.d.ts +22 -0
  199. package/dist/admin-components/features/plugin-features/components/PluginFeatureGate.js +18 -0
  200. package/dist/admin-components/features/plugin-features/components/PluginFeatureSections.d.ts +11 -0
  201. package/dist/admin-components/features/plugin-features/components/PluginFeatureSections.js +19 -0
  202. package/dist/admin-components/features/plugin-features/components/PluginFeaturesCard.d.ts +12 -0
  203. package/dist/admin-components/features/plugin-features/components/PluginFeaturesCard.js +34 -0
  204. package/dist/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.d.ts +5 -0
  205. package/dist/admin-components/features/plugin-features/components/PluginFeaturesSettingsPage.js +16 -0
  206. package/dist/admin-components/features/plugin-features/components/PluginHubCard.d.ts +7 -0
  207. package/dist/admin-components/features/plugin-features/components/PluginHubCard.js +21 -0
  208. package/dist/admin-components/features/plugin-features/components/PluginPageShell.d.ts +13 -0
  209. package/dist/admin-components/features/plugin-features/components/PluginPageShell.js +20 -0
  210. package/dist/admin-components/features/plugin-features/components/PluginSettingsForm.d.ts +7 -0
  211. package/dist/admin-components/features/plugin-features/components/PluginSettingsForm.js +39 -0
  212. package/dist/admin-components/features/plugin-features/components/PluginStatusChips.d.ts +5 -0
  213. package/dist/admin-components/features/plugin-features/components/PluginStatusChips.js +8 -0
  214. package/dist/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.d.ts +114 -0
  215. package/dist/admin-components/features/plugin-features/hooks/usePluginFeatureEnabled.js +40 -0
  216. package/dist/admin-components/features/plugin-features/hooks/usePluginFeatures.d.ts +392 -0
  217. package/dist/admin-components/features/plugin-features/hooks/usePluginFeatures.js +128 -0
  218. package/dist/admin-components/features/plugin-features/hooks/usePluginSettingsForm.d.ts +93 -0
  219. package/dist/admin-components/features/plugin-features/hooks/usePluginSettingsForm.js +44 -0
  220. package/dist/admin-components/features/plugin-features/lib/action-runs.d.ts +19 -0
  221. package/dist/admin-components/features/plugin-features/lib/action-runs.js +74 -0
  222. package/dist/admin-components/features/plugin-features/lib/plugin-features-admin-client.d.ts +363 -0
  223. package/dist/admin-components/features/plugin-features/lib/plugin-features-admin-client.js +9 -0
  224. package/dist/admin-components/features/plugin-features/lib/plugin-paths.d.ts +4 -0
  225. package/dist/admin-components/features/plugin-features/lib/plugin-paths.js +4 -0
  226. package/dist/admin-components/features/plugin-features/lib/settings-draft.d.ts +28 -0
  227. package/dist/admin-components/features/plugin-features/lib/settings-draft.js +86 -0
  228. package/dist/admin-components/features/plugin-features/queries/pluginFeatureKeys.d.ts +7 -0
  229. package/dist/admin-components/features/plugin-features/queries/pluginFeatureKeys.js +7 -0
  230. package/dist/admin-components/i18n/texts.d.ts +90 -0
  231. package/dist/admin-components/i18n/texts.js +90 -0
  232. package/dist/admin-components/index.d.ts +14 -0
  233. package/dist/admin-components/index.js +14 -0
  234. package/dist/admin-components/lib/errors.d.ts +6 -0
  235. package/dist/admin-components/lib/errors.js +27 -0
  236. package/dist/admin-components/lib/sdk.d.ts +2 -0
  237. package/dist/admin-components/lib/sdk.js +13 -0
  238. package/dist/documents/config/index.d.ts +11 -0
  239. package/dist/documents/config/index.js +17 -0
  240. package/dist/documents/templates/financial-document.d.ts +3 -0
  241. package/dist/documents/templates/financial-document.js +141 -0
  242. package/dist/documents/templates/format.d.ts +16 -0
  243. package/dist/documents/templates/format.js +30 -0
  244. package/dist/documents/templates/html-factory.d.ts +11 -0
  245. package/dist/documents/templates/html-factory.js +39 -0
  246. package/dist/documents/templates/html-utils.d.ts +2 -0
  247. package/dist/documents/templates/html-utils.js +12 -0
  248. package/dist/documents/templates/layout.d.ts +17 -0
  249. package/dist/documents/templates/layout.js +96 -0
  250. package/dist/documents/templates/packing-list.d.ts +3 -0
  251. package/dist/documents/templates/packing-list.js +49 -0
  252. package/dist/documents/types/admin-api.d.ts +1 -0
  253. package/dist/documents/types/admin-api.js +2 -0
  254. package/dist/documents/types/document-summary.d.ts +1 -0
  255. package/dist/documents/types/document-summary.js +2 -0
  256. package/dist/documents/types/documents.d.ts +174 -0
  257. package/dist/documents/types/documents.js +2 -0
  258. package/dist/documents/types/html-factory.d.ts +7 -0
  259. package/dist/documents/types/html-factory.js +5 -0
  260. package/dist/documents/types/index.d.ts +5 -0
  261. package/dist/documents/types/index.js +21 -0
  262. package/dist/documents/types/store-api.d.ts +1 -0
  263. package/dist/documents/types/store-api.js +2 -0
  264. package/dist/email/config/index.d.ts +17 -0
  265. package/dist/email/config/index.js +83 -0
  266. package/dist/email/config/notification-module.d.ts +22 -0
  267. package/dist/email/config/notification-module.js +19 -0
  268. package/dist/email/types/email-kinds.d.ts +15 -0
  269. package/dist/email/types/email-kinds.js +17 -0
  270. package/dist/email/types/index.d.ts +4 -0
  271. package/dist/email/types/index.js +20 -0
  272. package/dist/email/types/shop-configuration.d.ts +43 -0
  273. package/dist/email/types/shop-configuration.js +2 -0
  274. package/dist/email/types/smtp-configuration.d.ts +9 -0
  275. package/dist/email/types/smtp-configuration.js +2 -0
  276. package/dist/email/types/template-data.d.ts +100 -0
  277. package/dist/email/types/template-data.js +78 -0
  278. package/dist/files/config/index.d.ts +32 -0
  279. package/dist/files/config/index.js +255 -0
  280. package/dist/files/gateway/index.d.ts +30 -0
  281. package/dist/files/gateway/index.js +114 -0
  282. package/dist/files/types/index.d.ts +2 -0
  283. package/dist/files/types/index.js +5 -0
  284. package/dist/files/types/public.d.ts +90 -0
  285. package/dist/files/types/public.js +5 -0
  286. package/dist/modules/documents/domain/merchant.d.ts +22 -0
  287. package/dist/modules/documents/domain/merchant.js +85 -0
  288. package/dist/modules/documents/domain/options.d.ts +34 -0
  289. package/dist/modules/documents/domain/options.js +39 -0
  290. package/dist/public/action-progress.d.ts +25 -0
  291. package/dist/public/action-progress.js +66 -0
  292. package/dist/public/config.d.ts +59 -0
  293. package/dist/public/config.js +185 -0
  294. package/dist/public/descriptor.d.ts +3 -2
  295. package/dist/public/descriptor.js +198 -1
  296. package/dist/public/effective-features.d.ts +2 -1
  297. package/dist/public/effective-features.js +8 -4
  298. package/dist/public/enforcement.d.ts +7 -0
  299. package/dist/public/enforcement.js +17 -7
  300. package/dist/public/gateway.d.ts +2 -0
  301. package/dist/public/gateway.js +18 -0
  302. package/dist/public/index.d.ts +5 -2
  303. package/dist/public/index.js +9 -1
  304. package/dist/public/instrumentation.d.ts +12 -0
  305. package/dist/public/instrumentation.js +55 -0
  306. package/dist/public/module-access.d.ts +3 -0
  307. package/dist/public/module-access.js +13 -0
  308. package/dist/public/settings.d.ts +11 -0
  309. package/dist/public/settings.js +16 -0
  310. package/dist/public/shop-config.d.ts +8 -0
  311. package/dist/public/shop-config.js +11 -0
  312. package/dist/public/shop-master-data.d.ts +25 -0
  313. package/dist/public/shop-master-data.js +94 -0
  314. package/dist/public/shop-types.d.ts +7 -0
  315. package/dist/public/shop-types.js +23 -0
  316. package/dist/public/types.d.ts +113 -1
  317. package/dist/shop-config/build-food-shop-config.d.ts +44 -0
  318. package/dist/shop-config/build-food-shop-config.js +247 -0
  319. package/dist/shop-config/options.d.ts +41 -0
  320. package/dist/shop-config/options.js +70 -0
  321. package/dist/utils/discover-plugin-features.d.ts +28 -0
  322. package/dist/utils/discover-plugin-features.js +96 -0
  323. package/package.json +53 -6
@@ -0,0 +1,392 @@
1
+ export declare function usePluginFeatures(): import("@tanstack/react-query").UseQueryResult<{
2
+ plugins: {
3
+ plugin_key: string;
4
+ label: string;
5
+ description: string | null;
6
+ default_enabled: boolean;
7
+ switchable: boolean;
8
+ enabled: boolean;
9
+ version: number;
10
+ features: {
11
+ key: string;
12
+ label: string;
13
+ description: string | null;
14
+ parent_key: string | null;
15
+ default_enabled: boolean;
16
+ enabled: boolean;
17
+ effective_enabled: boolean;
18
+ }[];
19
+ settings: ({
20
+ type: "secret";
21
+ key: string;
22
+ label: string;
23
+ description: string | null;
24
+ required: boolean;
25
+ is_set: boolean;
26
+ source: "default" | "stored" | "config" | "none";
27
+ invalidates: string[];
28
+ } | {
29
+ type: "select";
30
+ options: {
31
+ value: string;
32
+ label: string;
33
+ }[];
34
+ default: string | null;
35
+ value: string | null;
36
+ key: string;
37
+ label: string;
38
+ description: string | null;
39
+ required: boolean;
40
+ is_set: boolean;
41
+ source: "default" | "stored" | "config" | "none";
42
+ invalidates: string[];
43
+ } | {
44
+ type: "number";
45
+ min: number | null;
46
+ max: number | null;
47
+ default: number | null;
48
+ value: number | null;
49
+ key: string;
50
+ label: string;
51
+ description: string | null;
52
+ required: boolean;
53
+ is_set: boolean;
54
+ source: "default" | "stored" | "config" | "none";
55
+ invalidates: string[];
56
+ } | {
57
+ type: "string" | "boolean" | "url";
58
+ default: string | number | boolean | null;
59
+ value: string | number | boolean | null;
60
+ key: string;
61
+ label: string;
62
+ description: string | null;
63
+ required: boolean;
64
+ is_set: boolean;
65
+ source: "default" | "stored" | "config" | "none";
66
+ invalidates: string[];
67
+ })[];
68
+ configured: boolean;
69
+ missing: string[];
70
+ settings_version: number;
71
+ actions: {
72
+ key: string;
73
+ label: string;
74
+ description: string | null;
75
+ mode: "sync" | "background";
76
+ confirm: string | null;
77
+ }[];
78
+ admin_page: string | null;
79
+ }[];
80
+ }, Error>;
81
+ /**
82
+ * One plugin (`GET /admin/plugin-features/:plugin_key`). Shows the entry from
83
+ * the already loaded list right away and fetches the plugin itself, so a deep
84
+ * link works without the hub. Toggle, settings and action mutations of the
85
+ * base update this cache; invalidate `pluginFeatureKeys.detail(pluginKey)`
86
+ * after an own mutation that changes what the base reports.
87
+ */
88
+ export declare function usePluginFeature(pluginKey: string | undefined): import("@tanstack/react-query").UseQueryResult<{
89
+ plugin: {
90
+ plugin_key: string;
91
+ label: string;
92
+ description: string | null;
93
+ default_enabled: boolean;
94
+ switchable: boolean;
95
+ enabled: boolean;
96
+ version: number;
97
+ features: {
98
+ key: string;
99
+ label: string;
100
+ description: string | null;
101
+ parent_key: string | null;
102
+ default_enabled: boolean;
103
+ enabled: boolean;
104
+ effective_enabled: boolean;
105
+ }[];
106
+ settings: ({
107
+ type: "secret";
108
+ key: string;
109
+ label: string;
110
+ description: string | null;
111
+ required: boolean;
112
+ is_set: boolean;
113
+ source: "default" | "stored" | "config" | "none";
114
+ invalidates: string[];
115
+ } | {
116
+ type: "select";
117
+ options: {
118
+ value: string;
119
+ label: string;
120
+ }[];
121
+ default: string | null;
122
+ value: string | null;
123
+ key: string;
124
+ label: string;
125
+ description: string | null;
126
+ required: boolean;
127
+ is_set: boolean;
128
+ source: "default" | "stored" | "config" | "none";
129
+ invalidates: string[];
130
+ } | {
131
+ type: "number";
132
+ min: number | null;
133
+ max: number | null;
134
+ default: number | null;
135
+ value: number | null;
136
+ key: string;
137
+ label: string;
138
+ description: string | null;
139
+ required: boolean;
140
+ is_set: boolean;
141
+ source: "default" | "stored" | "config" | "none";
142
+ invalidates: string[];
143
+ } | {
144
+ type: "string" | "boolean" | "url";
145
+ default: string | number | boolean | null;
146
+ value: string | number | boolean | null;
147
+ key: string;
148
+ label: string;
149
+ description: string | null;
150
+ required: boolean;
151
+ is_set: boolean;
152
+ source: "default" | "stored" | "config" | "none";
153
+ invalidates: string[];
154
+ })[];
155
+ configured: boolean;
156
+ missing: string[];
157
+ settings_version: number;
158
+ actions: {
159
+ key: string;
160
+ label: string;
161
+ description: string | null;
162
+ mode: "sync" | "background";
163
+ confirm: string | null;
164
+ }[];
165
+ admin_page: string | null;
166
+ };
167
+ }, Error>;
168
+ /** One instance per plugin card, so pending state is scoped to that plugin. */
169
+ export declare function useUpdatePluginFeatures(): import("@tanstack/react-query").UseMutationResult<{
170
+ plugin: {
171
+ plugin_key: string;
172
+ label: string;
173
+ description: string | null;
174
+ default_enabled: boolean;
175
+ switchable: boolean;
176
+ enabled: boolean;
177
+ version: number;
178
+ features: {
179
+ key: string;
180
+ label: string;
181
+ description: string | null;
182
+ parent_key: string | null;
183
+ default_enabled: boolean;
184
+ enabled: boolean;
185
+ effective_enabled: boolean;
186
+ }[];
187
+ settings: ({
188
+ type: "secret";
189
+ key: string;
190
+ label: string;
191
+ description: string | null;
192
+ required: boolean;
193
+ is_set: boolean;
194
+ source: "default" | "stored" | "config" | "none";
195
+ invalidates: string[];
196
+ } | {
197
+ type: "select";
198
+ options: {
199
+ value: string;
200
+ label: string;
201
+ }[];
202
+ default: string | null;
203
+ value: string | null;
204
+ key: string;
205
+ label: string;
206
+ description: string | null;
207
+ required: boolean;
208
+ is_set: boolean;
209
+ source: "default" | "stored" | "config" | "none";
210
+ invalidates: string[];
211
+ } | {
212
+ type: "number";
213
+ min: number | null;
214
+ max: number | null;
215
+ default: number | null;
216
+ value: number | null;
217
+ key: string;
218
+ label: string;
219
+ description: string | null;
220
+ required: boolean;
221
+ is_set: boolean;
222
+ source: "default" | "stored" | "config" | "none";
223
+ invalidates: string[];
224
+ } | {
225
+ type: "string" | "boolean" | "url";
226
+ default: string | number | boolean | null;
227
+ value: string | number | boolean | null;
228
+ key: string;
229
+ label: string;
230
+ description: string | null;
231
+ required: boolean;
232
+ is_set: boolean;
233
+ source: "default" | "stored" | "config" | "none";
234
+ invalidates: string[];
235
+ })[];
236
+ configured: boolean;
237
+ missing: string[];
238
+ settings_version: number;
239
+ actions: {
240
+ key: string;
241
+ label: string;
242
+ description: string | null;
243
+ mode: "sync" | "background";
244
+ confirm: string | null;
245
+ }[];
246
+ admin_page: string | null;
247
+ };
248
+ }, Error, {
249
+ plugin_key: string;
250
+ expected_version: number;
251
+ enabled: boolean;
252
+ features: Record<string, boolean>;
253
+ }, unknown>;
254
+ export declare function useUpdatePluginSettings(pluginKey: string): import("@tanstack/react-query").UseMutationResult<{
255
+ plugin: {
256
+ plugin_key: string;
257
+ label: string;
258
+ description: string | null;
259
+ default_enabled: boolean;
260
+ switchable: boolean;
261
+ enabled: boolean;
262
+ version: number;
263
+ features: {
264
+ key: string;
265
+ label: string;
266
+ description: string | null;
267
+ parent_key: string | null;
268
+ default_enabled: boolean;
269
+ enabled: boolean;
270
+ effective_enabled: boolean;
271
+ }[];
272
+ settings: ({
273
+ type: "secret";
274
+ key: string;
275
+ label: string;
276
+ description: string | null;
277
+ required: boolean;
278
+ is_set: boolean;
279
+ source: "default" | "stored" | "config" | "none";
280
+ invalidates: string[];
281
+ } | {
282
+ type: "select";
283
+ options: {
284
+ value: string;
285
+ label: string;
286
+ }[];
287
+ default: string | null;
288
+ value: string | null;
289
+ key: string;
290
+ label: string;
291
+ description: string | null;
292
+ required: boolean;
293
+ is_set: boolean;
294
+ source: "default" | "stored" | "config" | "none";
295
+ invalidates: string[];
296
+ } | {
297
+ type: "number";
298
+ min: number | null;
299
+ max: number | null;
300
+ default: number | null;
301
+ value: number | null;
302
+ key: string;
303
+ label: string;
304
+ description: string | null;
305
+ required: boolean;
306
+ is_set: boolean;
307
+ source: "default" | "stored" | "config" | "none";
308
+ invalidates: string[];
309
+ } | {
310
+ type: "string" | "boolean" | "url";
311
+ default: string | number | boolean | null;
312
+ value: string | number | boolean | null;
313
+ key: string;
314
+ label: string;
315
+ description: string | null;
316
+ required: boolean;
317
+ is_set: boolean;
318
+ source: "default" | "stored" | "config" | "none";
319
+ invalidates: string[];
320
+ })[];
321
+ configured: boolean;
322
+ missing: string[];
323
+ settings_version: number;
324
+ actions: {
325
+ key: string;
326
+ label: string;
327
+ description: string | null;
328
+ mode: "sync" | "background";
329
+ confirm: string | null;
330
+ }[];
331
+ admin_page: string | null;
332
+ };
333
+ }, Error, {
334
+ expected_version: number;
335
+ values: Record<string, string | number | boolean | null>;
336
+ }, unknown>;
337
+ /** Poll interval while the latest run of an action is `running`. */
338
+ export declare const PLUGIN_ACTION_RUN_POLL_MS = 2000;
339
+ /**
340
+ * Latest run of one action. Polls every 2 s while it is `running` and stops
341
+ * when it finished.
342
+ */
343
+ export declare function useLatestPluginActionRun(pluginKey: string, actionKey: string): import("@tanstack/react-query").UseQueryResult<{
344
+ id: string;
345
+ plugin_key: string;
346
+ action_key: string;
347
+ status: "failed" | "completed" | "running";
348
+ started_at: string;
349
+ finished_at: string | null;
350
+ triggered_by: string | null;
351
+ message: string | null;
352
+ progress: {
353
+ current: number;
354
+ total: number | null;
355
+ label: string | null;
356
+ } | null;
357
+ result: unknown;
358
+ }, Error>;
359
+ /**
360
+ * Runs one action. The recorded run goes into the action's run query, so a
361
+ * background run is polled right away. 409 (already running) shows a hint
362
+ * and loads the running run.
363
+ */
364
+ export declare function useRunPluginAction(pluginKey: string): import("@tanstack/react-query").UseMutationResult<{
365
+ action: {
366
+ key: string;
367
+ status: "completed" | "started";
368
+ run: {
369
+ id: string;
370
+ plugin_key: string;
371
+ action_key: string;
372
+ status: "failed" | "completed" | "running";
373
+ started_at: string;
374
+ finished_at: string | null;
375
+ triggered_by: string | null;
376
+ message: string | null;
377
+ progress: {
378
+ current: number;
379
+ total: number | null;
380
+ label: string | null;
381
+ } | null;
382
+ result: unknown;
383
+ };
384
+ result?: unknown;
385
+ };
386
+ }, Error, {
387
+ key: string;
388
+ label: string;
389
+ description: string | null;
390
+ mode: "sync" | "background";
391
+ confirm: string | null;
392
+ }, unknown>;
@@ -0,0 +1,128 @@
1
+ import { toast } from "@medusajs/ui";
2
+ import { useMutation, useQuery, useQueryClient, } from "@tanstack/react-query";
3
+ import { texts } from "../../../i18n/texts";
4
+ import { getErrorMessage } from "../../../lib/errors";
5
+ import { listPluginActionRuns, listPluginFeatures, retrievePluginFeatures, runPluginAction, updatePluginFeatures, updatePluginSettings, } from "../lib/plugin-features-admin-client";
6
+ import { pluginFeatureKeys } from "../queries/pluginFeatureKeys";
7
+ const isConflict = (error) => typeof error === "object" &&
8
+ error !== null &&
9
+ "status" in error &&
10
+ error.status === 409;
11
+ /** Writes a server response into the list and the plugin's detail cache. */
12
+ const storePlugin = (queryClient, plugin) => {
13
+ queryClient.setQueryData(pluginFeatureKeys.list(), (current) => current && {
14
+ plugins: current.plugins.map((entry) => entry.plugin_key === plugin.plugin_key ? plugin : entry),
15
+ });
16
+ queryClient.setQueryData(pluginFeatureKeys.detail(plugin.plugin_key), { plugin });
17
+ };
18
+ /** Toast for a failed save; reloads the server state either way. */
19
+ const onSaveError = async (queryClient, error) => {
20
+ if (isConflict(error)) {
21
+ toast.error(texts.toasts.conflict);
22
+ }
23
+ else {
24
+ toast.error(texts.toasts.saveFailed, {
25
+ description: getErrorMessage(error) ?? texts.errors.unknown,
26
+ });
27
+ }
28
+ await queryClient.invalidateQueries({ queryKey: pluginFeatureKeys.all });
29
+ };
30
+ export function usePluginFeatures() {
31
+ return useQuery({
32
+ queryKey: pluginFeatureKeys.list(),
33
+ queryFn: listPluginFeatures,
34
+ });
35
+ }
36
+ /**
37
+ * One plugin (`GET /admin/plugin-features/:plugin_key`). Shows the entry from
38
+ * the already loaded list right away and fetches the plugin itself, so a deep
39
+ * link works without the hub. Toggle, settings and action mutations of the
40
+ * base update this cache; invalidate `pluginFeatureKeys.detail(pluginKey)`
41
+ * after an own mutation that changes what the base reports.
42
+ */
43
+ export function usePluginFeature(pluginKey) {
44
+ const queryClient = useQueryClient();
45
+ return useQuery({
46
+ queryKey: pluginFeatureKeys.detail(pluginKey ?? ""),
47
+ queryFn: () => retrievePluginFeatures(pluginKey),
48
+ enabled: Boolean(pluginKey),
49
+ placeholderData: () => {
50
+ const plugin = queryClient
51
+ .getQueryData(pluginFeatureKeys.list())
52
+ ?.plugins.find((entry) => entry.plugin_key === pluginKey);
53
+ return plugin ? { plugin } : undefined;
54
+ },
55
+ });
56
+ }
57
+ /** One instance per plugin card, so pending state is scoped to that plugin. */
58
+ export function useUpdatePluginFeatures() {
59
+ const queryClient = useQueryClient();
60
+ return useMutation({
61
+ mutationFn: updatePluginFeatures,
62
+ onSuccess: ({ plugin }) => {
63
+ storePlugin(queryClient, plugin);
64
+ toast.success(texts.toasts.saved);
65
+ },
66
+ onError: (error) => onSaveError(queryClient, error),
67
+ });
68
+ }
69
+ export function useUpdatePluginSettings(pluginKey) {
70
+ const queryClient = useQueryClient();
71
+ return useMutation({
72
+ mutationFn: (payload) => updatePluginSettings(pluginKey, payload),
73
+ onSuccess: ({ plugin }) => {
74
+ storePlugin(queryClient, plugin);
75
+ toast.success(texts.toasts.saved);
76
+ },
77
+ onError: (error) => onSaveError(queryClient, error),
78
+ });
79
+ }
80
+ /** Poll interval while the latest run of an action is `running`. */
81
+ export const PLUGIN_ACTION_RUN_POLL_MS = 2000;
82
+ /**
83
+ * Latest run of one action. Polls every 2 s while it is `running` and stops
84
+ * when it finished.
85
+ */
86
+ export function useLatestPluginActionRun(pluginKey, actionKey) {
87
+ return useQuery({
88
+ queryKey: pluginFeatureKeys.actionRuns(pluginKey, actionKey),
89
+ queryFn: () => listPluginActionRuns(pluginKey, actionKey, 1),
90
+ select: (data) => data.runs[0],
91
+ refetchInterval: (query) => query.state.data?.runs[0]?.status === "running"
92
+ ? PLUGIN_ACTION_RUN_POLL_MS
93
+ : false,
94
+ });
95
+ }
96
+ /**
97
+ * Runs one action. The recorded run goes into the action's run query, so a
98
+ * background run is polled right away. 409 (already running) shows a hint
99
+ * and loads the running run.
100
+ */
101
+ export function useRunPluginAction(pluginKey) {
102
+ const queryClient = useQueryClient();
103
+ return useMutation({
104
+ mutationFn: (action) => runPluginAction(pluginKey, action.key),
105
+ onSuccess: ({ action: run }, action) => {
106
+ queryClient.setQueryData(pluginFeatureKeys.actionRuns(pluginKey, action.key), { runs: [run.run] });
107
+ if (run.status === "started") {
108
+ toast.info(texts.toasts.actionStarted(action.label));
109
+ }
110
+ else {
111
+ toast.success(texts.toasts.actionCompleted(action.label));
112
+ }
113
+ },
114
+ onError: async (error, action) => {
115
+ if (isConflict(error)) {
116
+ toast.info(texts.toasts.actionAlreadyRunning(action.label));
117
+ }
118
+ else {
119
+ toast.error(texts.toasts.actionFailed(action.label), {
120
+ description: getErrorMessage(error) ?? texts.errors.unknown,
121
+ });
122
+ }
123
+ await queryClient.invalidateQueries({
124
+ queryKey: pluginFeatureKeys.actionRuns(pluginKey, action.key),
125
+ });
126
+ },
127
+ });
128
+ }
@@ -0,0 +1,93 @@
1
+ import type { AdminPluginFeatures } from "@hartl-services/medusa-food-supplements-contracts/types/plugin-features-admin";
2
+ import type { FormEvent } from "react";
3
+ import { type SettingsDraft } from "../lib/settings-draft";
4
+ export declare function usePluginSettingsForm(plugin: AdminPluginFeatures): {
5
+ draft: SettingsDraft;
6
+ setValue: (key: string, value: string | boolean | null, badInput?: boolean) => void;
7
+ dirty: boolean;
8
+ invalid: string[];
9
+ submit: (event: FormEvent<HTMLFormElement>) => void;
10
+ mutation: import("@tanstack/react-query").UseMutationResult<{
11
+ plugin: {
12
+ plugin_key: string;
13
+ label: string;
14
+ description: string | null;
15
+ default_enabled: boolean;
16
+ switchable: boolean;
17
+ enabled: boolean;
18
+ version: number;
19
+ features: {
20
+ key: string;
21
+ label: string;
22
+ description: string | null;
23
+ parent_key: string | null;
24
+ default_enabled: boolean;
25
+ enabled: boolean;
26
+ effective_enabled: boolean;
27
+ }[];
28
+ settings: ({
29
+ type: "secret";
30
+ key: string;
31
+ label: string;
32
+ description: string | null;
33
+ required: boolean;
34
+ is_set: boolean;
35
+ source: "default" | "stored" | "config" | "none";
36
+ invalidates: string[];
37
+ } | {
38
+ type: "select";
39
+ options: {
40
+ value: string;
41
+ label: string;
42
+ }[];
43
+ default: string | null;
44
+ value: string | null;
45
+ key: string;
46
+ label: string;
47
+ description: string | null;
48
+ required: boolean;
49
+ is_set: boolean;
50
+ source: "default" | "stored" | "config" | "none";
51
+ invalidates: string[];
52
+ } | {
53
+ type: "number";
54
+ min: number | null;
55
+ max: number | null;
56
+ default: number | null;
57
+ value: number | null;
58
+ key: string;
59
+ label: string;
60
+ description: string | null;
61
+ required: boolean;
62
+ is_set: boolean;
63
+ source: "default" | "stored" | "config" | "none";
64
+ invalidates: string[];
65
+ } | {
66
+ type: "string" | "boolean" | "url";
67
+ default: string | number | boolean | null;
68
+ value: string | number | boolean | null;
69
+ key: string;
70
+ label: string;
71
+ description: string | null;
72
+ required: boolean;
73
+ is_set: boolean;
74
+ source: "default" | "stored" | "config" | "none";
75
+ invalidates: string[];
76
+ })[];
77
+ configured: boolean;
78
+ missing: string[];
79
+ settings_version: number;
80
+ actions: {
81
+ key: string;
82
+ label: string;
83
+ description: string | null;
84
+ mode: "sync" | "background";
85
+ confirm: string | null;
86
+ }[];
87
+ admin_page: string | null;
88
+ };
89
+ }, Error, {
90
+ expected_version: number;
91
+ values: Record<string, string | number | boolean | null>;
92
+ }, unknown>;
93
+ };
@@ -0,0 +1,44 @@
1
+ import { useEffect, useMemo, useState } from "react";
2
+ import { changedSettingValues, initialSettingsDraft, invalidDraftKeys, } from "../lib/settings-draft";
3
+ import { useUpdatePluginSettings } from "./usePluginFeatures";
4
+ export function usePluginSettingsForm(plugin) {
5
+ const mutation = useUpdatePluginSettings(plugin.plugin_key);
6
+ const [draft, setDraft] = useState(() => initialSettingsDraft(plugin.settings));
7
+ // Number inputs the browser could not parse (they report "").
8
+ const [unparsable, setUnparsable] = useState([]);
9
+ // New server data (save, conflict reload, refetch) resets the form.
10
+ useEffect(() => {
11
+ setDraft(initialSettingsDraft(plugin.settings));
12
+ setUnparsable([]);
13
+ }, [plugin.settings, plugin.settings_version]);
14
+ const changes = useMemo(() => changedSettingValues(plugin.settings, draft, unparsable), [plugin.settings, draft, unparsable]);
15
+ const invalid = useMemo(() => invalidDraftKeys(plugin.settings, draft, unparsable), [plugin.settings, draft, unparsable]);
16
+ const dirty = Object.keys(changes).length > 0;
17
+ /** `badInput`: the browser could not parse the typed number. */
18
+ const setValue = (key, value, badInput = false) => {
19
+ setDraft((current) => ({ ...current, [key]: value }));
20
+ setUnparsable((current) => badInput
21
+ ? current.includes(key)
22
+ ? current
23
+ : [...current, key]
24
+ : current.filter((entry) => entry !== key));
25
+ };
26
+ const submit = (event) => {
27
+ event.preventDefault();
28
+ if (!dirty || invalid.length > 0 || mutation.isPending) {
29
+ return;
30
+ }
31
+ mutation.mutate({
32
+ expected_version: plugin.settings_version,
33
+ values: changes,
34
+ });
35
+ };
36
+ return {
37
+ draft,
38
+ setValue,
39
+ dirty,
40
+ invalid,
41
+ submit,
42
+ mutation,
43
+ };
44
+ }
@@ -0,0 +1,19 @@
1
+ import type { PluginActionRun, PluginActionRunProgress } from "@hartl-services/medusa-food-supplements-contracts/types/plugin-features-admin";
2
+ /**
3
+ * One line for a finished run's result: a string result, else its `summary`
4
+ * or `message`, else its primitive top-level fields (`key: value, …`).
5
+ * `null` when nothing readable is there.
6
+ */
7
+ export declare const summarizeActionResult: (result: unknown) => string | null;
8
+ /** Share done in percent (0–100); `null` when the total is unknown. */
9
+ export declare const progressPercent: (progress: PluginActionRunProgress | null) => number | null;
10
+ /** "3 / 10" or "3" (unknown total); `null` without progress. */
11
+ export declare const progressCount: (progress: PluginActionRunProgress | null) => string | null;
12
+ /** Short German date and time. */
13
+ export declare const formatRunTime: (iso: string | null) => string;
14
+ export type RunTransition = "completed" | "failed" | null;
15
+ /**
16
+ * Whether the latest run just finished while this page watched it: the same
17
+ * run was `running` before and is `completed`/`failed` now.
18
+ */
19
+ export declare const runTransition: (previous: Pick<PluginActionRun, "id" | "status"> | undefined, current: Pick<PluginActionRun, "id" | "status"> | undefined) => RunTransition;