diff --git a/package-lock.json b/package-lock.json index 47e34ec82..209b38303 100644 --- a/package-lock.json +++ b/package-lock.json @@ -517,7 +517,6 @@ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@babel/code-frame": "^7.29.0", "@babel/generator": "^7.29.0", @@ -853,7 +852,6 @@ "integrity": "sha512-xkGBRQQab4RLwgXxoqETICr6S5JlogafbhNsidmrkVv2YRs5MLwpjoF2qpiGjQt8S9AoxtIV603s0GIUpY5eYQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@dnd-kit/accessibility": "^3.1.1", "@dnd-kit/utilities": "^3.2.2", @@ -5384,7 +5382,6 @@ "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/body-parser": "*", "@types/express-serve-static-core": "^5.0.0", @@ -5509,7 +5506,6 @@ "integrity": "sha512-ilcTH/UniCkMdtexkoCN0bI7pMcJDvmQFPvuPvmEaYA/NSfFTAgdUSLAoVjaRJm7+6PvcM+q1zYOwS4wTYMF9w==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -5661,7 +5657,6 @@ "integrity": "sha512-4z2nCSBfVIMnbuu8uinj+f0o4qOeggYJLbjpPHka3KH1om7e+H9yLKTYgksTaHcGco+NClhhY2vyO3HsMH1RGw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@typescript-eslint/scope-manager": "8.55.0", "@typescript-eslint/types": "8.55.0", @@ -6493,7 +6488,6 @@ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -7363,7 +7357,6 @@ } ], "license": "MIT", - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -8854,7 +8847,6 @@ "integrity": "sha512-fmTRWbNMmsmWq6xJV8D19U/gw/bwrHfNXxrIN+HfZgnzqTHp9jOmKMhsTUjXOJnZOdZY9Q28y4yebKzqDKlxlQ==", "dev": true, "license": "ISC", - "peer": true, "engines": { "node": ">=12" } @@ -9041,7 +9033,6 @@ "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==", "dev": true, "license": "MIT", - "peer": true, "funding": { "type": "github", "url": "https://github.com/sponsors/kossnocorp" @@ -9435,7 +9426,6 @@ "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "ansi-colors": "^4.1.1", "strip-ansi": "^6.0.1" @@ -9710,7 +9700,6 @@ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -9958,7 +9947,6 @@ "integrity": "sha512-whOE1HFo/qJDyX4SnXzP4N6zOWn79WhnCUY/iDR0mPfQZO8wcYE4JClzI2oZrhBnnMUCBCHZhO6VQyoBU95mZA==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@rtsao/scc": "^1.1.0", "array-includes": "^3.1.9", @@ -10396,7 +10384,6 @@ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", "license": "MIT", - "peer": true, "dependencies": { "accepts": "^2.0.0", "body-parser": "^2.2.1", @@ -11556,7 +11543,6 @@ "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.12.0.tgz", "integrity": "sha512-DKKrynuQRne0PNpEbzuEdHlYOMksHSUI8Zc9Unei5gTsMNA2/vMpoMz/yKba50pejK56qj98qM0SjYxAKi13gQ==", "license": "MIT", - "peer": true, "engines": { "node": "^12.22.0 || ^14.16.0 || ^16.0.0 || >=17.0.0" } @@ -11939,7 +11925,6 @@ "integrity": "sha512-yoLRW+KRlDmnnROdAu7sX77VNLC0bsFoZyGQJLy1cF+X/SkLg/fWkRGrEEYQK8o2cafJ2wmEaMqMEZB3U3DYDg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=20" }, @@ -12316,7 +12301,6 @@ "integrity": "sha512-Eaw2YTGM6WOxA6CXbckaEvslr2Ne4NFsKrvc0v97JD5awbmeBLO5w9Ho9L9kmKonrwF9RJlW6BxT1PVv/agBHQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=16.9.0" } @@ -13581,6 +13565,7 @@ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz", "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==", "license": "MIT", + "peer": true, "dependencies": { "jws": "^4.0.1", "lodash.includes": "^4.3.0", @@ -14188,13 +14173,15 @@ "version": "4.3.0", "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz", "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.isboolean": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz", "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.isequal": { "version": "4.5.0", @@ -14208,25 +14195,29 @@ "version": "4.0.4", "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz", "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.isnumber": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz", "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.isplainobject": { "version": "4.0.6", "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.isstring": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz", "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==", - "license": "MIT" + "license": "MIT", + "peer": true }, "node_modules/lodash.merge": { "version": "4.6.2", @@ -15616,7 +15607,6 @@ "https://github.com/sponsors/broofa" ], "license": "MIT", - "peer": true, "bin": { "mime": "bin/cli.js" }, @@ -15796,7 +15786,6 @@ "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-7.1.0.tgz", "integrity": "sha512-kMfnKunbolQYwCIyrkxNJFB4Ypy91pYqua5NargS/f8ODNSJxT03ZU3n1JqL4mCzbSih8tvmMEMLpKTT7x5gCg==", "license": "Apache-2.0", - "peer": true, "dependencies": { "@mongodb-js/saslprep": "^1.3.0", "bson": "^7.1.1", @@ -16193,6 +16182,7 @@ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.2.tgz", "integrity": "sha512-6xKiQ+cph9KImrRh0VsjH2d8/GXA4FIMlgU4B757iI1ApvcyA9VlouP0yZJha01V+huImO+kKMU7ih+2+E14fw==", "license": "(BSD-3-Clause OR GPL-2.0)", + "peer": true, "engines": { "node": ">= 6.13.0" } @@ -17310,7 +17300,6 @@ "integrity": "sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==", "dev": true, "license": "MIT", - "peer": true, "bin": { "prettier": "bin/prettier.cjs" }, @@ -17588,7 +17577,6 @@ "integrity": "sha512-9nfp2hYpCwOjAN+8TZFGhtWEwgvWHXqESH8qT89AT/lWklpLON22Lc8pEtnpsZz7VmawabSU0gCjnj8aC0euHQ==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -17599,7 +17587,6 @@ "integrity": "sha512-AXJdLo8kgMbimY95O2aKQqsz2iWi9jMgKJhRBAxECE4IFxfcazB2LmzloIoibJI3C12IlY20+KFaLv+71bUJeQ==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -17682,7 +17669,6 @@ "integrity": "sha512-ROY9fvHhwOD9ySfrF0wmvu//bKCQ6AeZZq1nJNtbDC+kk5DuSuNX/n6YWYF/SYy7bSba4D4FSz8DJeKY/S/r+g==", "dev": true, "license": "MIT", - "peer": true, "dependencies": { "@types/use-sync-external-store": "^0.0.6", "use-sync-external-store": "^1.4.0" @@ -17828,8 +17814,7 @@ "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz", "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/redux-thunk": { "version": "3.1.0", @@ -18224,7 +18209,6 @@ "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", "dev": true, "license": "Apache-2.0", - "peer": true, "dependencies": { "tslib": "^2.1.0" } @@ -19614,8 +19598,7 @@ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.18.tgz", "integrity": "sha512-4+Z+0yiYyEtUVCScyfHCxOYP06L5Ne+JiHhY2IjR2KWMIWhJOYZKLSGZaP5HkZ8+bY0cxfzwDE5uOmzFXyIwxw==", "dev": true, - "license": "MIT", - "peer": true + "license": "MIT" }, "node_modules/tapable": { "version": "2.3.0", @@ -20138,7 +20121,6 @@ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", "dev": true, "license": "Apache-2.0", - "peer": true, "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -20589,6 +20571,7 @@ "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.1.tgz", "integrity": "sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==", "license": "MIT", + "peer": true, "dependencies": { "assert-plus": "^1.0.0", "core-util-is": "1.0.2", @@ -20913,7 +20896,6 @@ "integrity": "sha512-blAT2mjOEIi0ZzruJfIhb3nps74PRWTCz1IjglWEEpQl5XS/UNama6u2/rjFkDDouqr4L67ry+1aGIALViWjDg==", "dev": true, "license": "MIT", - "peer": true, "engines": { "node": ">=10.0.0" }, @@ -21082,7 +21064,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.3.6.tgz", "integrity": "sha512-rftlrkhHZOcjDwkGlnUtZZkvaPHCsDATp4pGpuOOMDaTdDDXF91wuVDJoWoPsKX/3YPQ5fHuF3STjcYyKr+Qhg==", "license": "MIT", - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/packages/api/src/resolvers/mutations/index.ts b/packages/api/src/resolvers/mutations/index.ts index f155fb0e9..1a3d9845d 100755 --- a/packages/api/src/resolvers/mutations/index.ts +++ b/packages/api/src/resolvers/mutations/index.ts @@ -146,6 +146,7 @@ import rejectOrder from './orders/rejectOrder.ts'; import removePushSubscription from './users/removePushSubscription.ts'; import addPushSubscription from './users/addPushSubscription.ts'; import removeUserProductReviews from './users/removeUserProductReviews.ts'; +import updateCartDeliveryDownload from './orders/updateCartDeliveryDownload.ts'; import updateCartDeliveryPickUp from './orders/updateCartDeliveryPickUp.ts'; import updateCartDeliveryShipping from './orders/updateCartDeliveryShipping.ts'; import updateCartPaymentGeneric from './orders/updateCartPaymentGeneric.ts'; @@ -242,6 +243,7 @@ export default { updateCartItem: acl(actions.updateOrderItem)(updateCartItem), removeCartItem: acl(actions.updateOrderItem)(removeCartItem), removeCartDiscount: acl(actions.updateOrderDiscount)(removeCartDiscount), + updateCartDeliveryDownload: acl(actions.updateCart)(updateCartDeliveryDownload), updateCartDeliveryPickUp: acl(actions.updateCart)(updateCartDeliveryPickUp), updateCartDeliveryShipping: acl(actions.updateCart)(updateCartDeliveryShipping), updateCartPaymentGeneric: acl(actions.updateCart)(updateCartPaymentGeneric), diff --git a/packages/api/src/resolvers/mutations/orders/updateCartDeliveryDownload.ts b/packages/api/src/resolvers/mutations/orders/updateCartDeliveryDownload.ts new file mode 100644 index 000000000..db090a5d5 --- /dev/null +++ b/packages/api/src/resolvers/mutations/orders/updateCartDeliveryDownload.ts @@ -0,0 +1,53 @@ +import type { Context } from '../../../context.ts'; +import { DeliveryProviderType } from '@unchainedshop/core-delivery'; +import { log } from '@unchainedshop/logger'; +import { + InvalidIdError, + OrderDeliveryNotFoundError, + OrderDeliveryTypeError, + OrderNotFoundError, + OrderWrongStatusError, +} from '../../../errors.ts'; + +export default async function updateCartDeliveryDownload( + root: never, + params: { orderId: string; deliveryProviderId: string; meta: any }, + context: Context, +) { + const { modules, services, userId, user } = context; + const { orderId, deliveryProviderId, meta } = params; + log(`mutation updateCartDeliveryDownload provider ${deliveryProviderId}`, { + userId, + }); + + if (!deliveryProviderId) throw new InvalidIdError({ deliveryProviderId }); + + let order = await services.orders.findOrInitCart({ + orderId, + user: user!, + countryCode: context.countryCode, + }); + if (!order) throw new OrderNotFoundError({ orderId }); + if (!modules.orders.isCart(order)) throw new OrderWrongStatusError({ status: order.status }); + + const provider = await modules.delivery.findProvider({ + deliveryProviderId, + }); + const deliveryProviderType = provider?.type; + + if (deliveryProviderType !== DeliveryProviderType.DOWNLOAD) + throw new OrderDeliveryTypeError({ + orderId: order._id, + received: deliveryProviderType, + required: DeliveryProviderType.DOWNLOAD, + }); + + order = (await modules.orders.setDeliveryProvider(order._id, deliveryProviderId)) || order; + + if (!order.deliveryId) throw new OrderDeliveryNotFoundError({ orderId: order._id }); + + await modules.orders.deliveries.updateContext(order.deliveryId, { + meta, + }); + return services.orders.updateCalculation(order._id); +} diff --git a/packages/api/src/resolvers/type/delivery-provider-download-types.ts b/packages/api/src/resolvers/type/delivery-provider-download-types.ts new file mode 100644 index 000000000..52b96f70d --- /dev/null +++ b/packages/api/src/resolvers/type/delivery-provider-download-types.ts @@ -0,0 +1,5 @@ +import { DeliveryProviderInterface } from './delivery-provider-interface.ts'; + +export const DeliveryProviderDownload = { + ...DeliveryProviderInterface, +}; diff --git a/packages/api/src/resolvers/type/delivery-provider-types.ts b/packages/api/src/resolvers/type/delivery-provider-types.ts index 3bc5baf26..3f076d364 100644 --- a/packages/api/src/resolvers/type/delivery-provider-types.ts +++ b/packages/api/src/resolvers/type/delivery-provider-types.ts @@ -9,6 +9,8 @@ export const DeliveryProvider = { switch (provider?.type) { case DeliveryProviderType.PICKUP: return 'DeliveryProviderPickUp'; + case DeliveryProviderType.DOWNLOAD: + return 'DeliveryProviderDownload'; default: return 'DeliveryProviderShipping'; } diff --git a/packages/api/src/resolvers/type/index.ts b/packages/api/src/resolvers/type/index.ts index 1d66dd210..01ec0edfc 100755 --- a/packages/api/src/resolvers/type/index.ts +++ b/packages/api/src/resolvers/type/index.ts @@ -67,6 +67,7 @@ import { Web3Address } from './web3-address.ts'; import { LoginMethodResponse } from './login-method-response-types.ts'; import { ProductSearchResult } from './product-search-result-types.ts'; import { OrderStatistics } from './order/order-statistics-types.ts'; +import { DeliveryProviderDownload } from './delivery-provider-download-types.ts'; import { DeliveryProviderPickUp } from './delivery-provider-pickup-types.ts'; import { DeliveryProviderShipping } from './delivery-provider-shipping-types.ts'; @@ -83,6 +84,7 @@ const types = { Country, Currency, DeliveryProvider, + DeliveryProviderDownload, DeliveryProviderPickUp, DeliveryProviderShipping, Dimensions, diff --git a/packages/api/src/resolvers/type/order/order-delivery-types.ts b/packages/api/src/resolvers/type/order/order-delivery-types.ts index fa0a3ac74..2ae2afac6 100644 --- a/packages/api/src/resolvers/type/order/order-delivery-types.ts +++ b/packages/api/src/resolvers/type/order/order-delivery-types.ts @@ -11,6 +11,8 @@ export const OrderDelivery = { switch (provider?.type) { case DeliveryProviderType.PICKUP: return 'OrderDeliveryPickUp'; + case DeliveryProviderType.DOWNLOAD: + return 'OrderDeliveryDownload'; default: return 'OrderDeliveryShipping'; } diff --git a/packages/api/src/schema/mutation.ts b/packages/api/src/schema/mutation.ts index d5305ec40..87e1eb955 100644 --- a/packages/api/src/schema/mutation.ts +++ b/packages/api/src/schema/mutation.ts @@ -247,6 +247,15 @@ export default [ meta: JSON ): Order! + """ + Update the cart by changing the delivery provider and using a download specific configuration + """ + updateCartDeliveryDownload( + orderId: ID + deliveryProviderId: ID! + meta: JSON + ): Order! + """ Update the cart by changing the payment provider and using an invoice-type specific configuration """ diff --git a/packages/api/src/schema/types/delivery.ts b/packages/api/src/schema/types/delivery.ts index 021a8cc69..022ab6518 100644 --- a/packages/api/src/schema/types/delivery.ts +++ b/packages/api/src/schema/types/delivery.ts @@ -16,6 +16,11 @@ export default [ Shipping """ SHIPPING + + """ + Download (digital delivery) + """ + DOWNLOAD } enum DeliveryProviderError { @@ -79,5 +84,23 @@ export default [ context: JSON ): Price @cacheControl(scope: PRIVATE, maxAge: 10) } + + type DeliveryProviderDownload implements DeliveryProvider @cacheControl(maxAge: 60) { + _id: ID! + created: DateTime + updated: DateTime + deleted: DateTime + type: DeliveryProviderType + interface: DeliveryInterface + configuration: JSON + configurationError: DeliveryProviderError + isActive: Boolean + simulatedPrice( + currencyCode: String + useNetPrice: Boolean = false + orderId: ID + context: JSON + ): Price @cacheControl(scope: PRIVATE, maxAge: 10) + } `, ]; diff --git a/packages/api/src/schema/types/order/delivery.ts b/packages/api/src/schema/types/order/delivery.ts index df2833dca..75adddc23 100644 --- a/packages/api/src/schema/types/order/delivery.ts +++ b/packages/api/src/schema/types/order/delivery.ts @@ -45,5 +45,14 @@ export default [ discounts: [OrderDeliveryDiscount!] address: Address } + + type OrderDeliveryDownload implements OrderDelivery { + _id: ID! + provider: DeliveryProvider + status: OrderDeliveryStatus + delivered: DateTime + fee: Price + discounts: [OrderDeliveryDiscount!] + } `, ]; diff --git a/packages/core-delivery/src/db/DeliveryProvidersCollection.ts b/packages/core-delivery/src/db/DeliveryProvidersCollection.ts index 22a32764d..6a23125df 100644 --- a/packages/core-delivery/src/db/DeliveryProvidersCollection.ts +++ b/packages/core-delivery/src/db/DeliveryProvidersCollection.ts @@ -3,6 +3,7 @@ import { mongodb, buildDbIndexes, type TimestampFields } from '@unchainedshop/mo export const DeliveryProviderType = { SHIPPING: 'SHIPPING', PICKUP: 'PICKUP', + DOWNLOAD: 'DOWNLOAD', } as const; export type DeliveryProviderType = (typeof DeliveryProviderType)[keyof typeof DeliveryProviderType]; diff --git a/packages/core-delivery/src/module/buildFindSelector.test.ts b/packages/core-delivery/src/module/buildFindSelector.test.ts index 06c2dc457..7feed3f5b 100644 --- a/packages/core-delivery/src/module/buildFindSelector.test.ts +++ b/packages/core-delivery/src/module/buildFindSelector.test.ts @@ -15,5 +15,12 @@ describe('Delivery', () => { deleted: null, }); }); + + it('Return correct filter object when passed DOWNLOAD type', () => { + assert.deepStrictEqual(buildFindSelector({ type: DeliveryProviderType.DOWNLOAD }), { + type: 'DOWNLOAD', + deleted: null, + }); + }); }); }); diff --git a/packages/core/src/factory/index.ts b/packages/core/src/factory/index.ts index dbb7359c6..04753f7d6 100644 --- a/packages/core/src/factory/index.ts +++ b/packages/core/src/factory/index.ts @@ -1,4 +1,5 @@ import registerProductDiscoverabilityFilter from './registerProductDiscoverabilityFilter.ts'; +import registerDownloadDelivery from './registerDownloadDelivery.ts'; import registerPickUpDelivery from './registerPickUpDelivery.ts'; import registerShippingDelivery from './registerShippingDelivery.ts'; import registerWorker from './registerWorker.ts'; @@ -10,6 +11,7 @@ import registerInvoicePayment from './registerInvoicePayment.ts'; export { registerProductDiscoverabilityFilter, + registerDownloadDelivery, registerPickUpDelivery, registerShippingDelivery, registerInvoicePayment, diff --git a/packages/core/src/factory/registerDownloadDelivery.ts b/packages/core/src/factory/registerDownloadDelivery.ts new file mode 100644 index 000000000..e3e62f7a0 --- /dev/null +++ b/packages/core/src/factory/registerDownloadDelivery.ts @@ -0,0 +1,82 @@ +import type { DeliveryConfiguration } from '@unchainedshop/core-delivery'; +import { DeliveryProviderType } from '@unchainedshop/core-delivery'; +import { + DeliveryAdapter, + type DeliveryContext, + type IPlugin, + type IDeliveryAdapter, +} from '../core-index.ts'; +import { pluginRegistry } from '../plugins/PluginRegistry.ts'; +import type { Work } from '@unchainedshop/core-worker'; + +export default function registerDownloadDelivery({ + adapterId, + active, + autoReleaseAllowed, + estimatedDeliveryThroughput, + send, +}: { + adapterId: string; + active?: boolean; + autoReleaseAllowed?: boolean; + estimatedDeliveryThroughput?: ( + warehousingThroughputTime: number, + context: DeliveryContext, + ) => Promise; + send: + | boolean + | ((configuration: DeliveryConfiguration, context: DeliveryContext) => Promise); +}): IPlugin { + const adapter: IDeliveryAdapter = { + ...DeliveryAdapter, + + key: `shop.unchained.delivery.download-${adapterId}`, + label: 'Download Delivery: ' + adapterId, + version: '1.0.0', + + initialConfiguration: [], + + typeSupported: (type) => { + return type === DeliveryProviderType.DOWNLOAD; + }, + + actions: (config, context) => { + return { + ...DeliveryAdapter.actions(config, context), + + isActive: () => { + return active ?? true; + }, + + isAutoReleaseAllowed: () => { + return autoReleaseAllowed ?? true; + }, + + configurationError: () => { + return null; + }, + + estimatedDeliveryThroughput: async (warehousingThroughputTime) => { + if (estimatedDeliveryThroughput) { + return estimatedDeliveryThroughput(warehousingThroughputTime, context); + } + return 0; + }, + + send: async () => { + return typeof send === 'function' ? await send(config, context) : send; + }, + }; + }, + }; + + const plugin: IPlugin = { + key: adapter.key, + label: adapter.label, + version: adapter.version, + adapters: [adapter], + }; + + pluginRegistry.register(plugin); + return plugin; +} diff --git a/packages/plugins/src/delivery/download/adapter.ts b/packages/plugins/src/delivery/download/adapter.ts new file mode 100644 index 000000000..6f5146cf1 --- /dev/null +++ b/packages/plugins/src/delivery/download/adapter.ts @@ -0,0 +1,28 @@ +import { type IDeliveryAdapter, DeliveryAdapter } from '@unchainedshop/core'; +import { DeliveryProviderType } from '@unchainedshop/core-delivery'; + +export const Download: IDeliveryAdapter = { + ...DeliveryAdapter, + + key: 'shop.unchained.delivery.download', + label: 'Download', + version: '1.0.0', + + typeSupported: (type) => { + return type === DeliveryProviderType.DOWNLOAD; + }, + + actions: (config, context) => { + return { + ...DeliveryAdapter.actions(config, context), + + isActive: () => { + return true; + }, + + configurationError: () => { + return null; + }, + }; + }, +}; diff --git a/packages/plugins/src/delivery/download/index.ts b/packages/plugins/src/delivery/download/index.ts new file mode 100644 index 000000000..acfbe45d4 --- /dev/null +++ b/packages/plugins/src/delivery/download/index.ts @@ -0,0 +1,16 @@ +import { type IPlugin } from '@unchainedshop/core'; +import { Download } from './adapter.ts'; + +// Plugin definition +export const DownloadPlugin: IPlugin = { + key: 'shop.unchained.delivery.download', + label: 'Download Delivery Plugin', + version: '1.0.0', + + adapters: [Download], +}; + +export default DownloadPlugin; + +// Re-export adapter for direct use +export { Download } from './adapter.ts'; diff --git a/packages/plugins/src/presets/base.ts b/packages/plugins/src/presets/base.ts index d46870350..4fbef9384 100644 --- a/packages/plugins/src/presets/base.ts +++ b/packages/plugins/src/presets/base.ts @@ -13,6 +13,7 @@ import { InvoicePlugin } from '../payment/invoice/index.ts'; // Import plugins - Delivery import { PostPlugin } from '../delivery/post/index.ts'; +import { DownloadPlugin } from '../delivery/download/index.ts'; // Import plugins - Warehousing import { StorePlugin } from '../warehousing/store/index.ts'; @@ -58,6 +59,7 @@ export function registerBasePlugins() { // Delivery pluginRegistry.register(PostPlugin); + pluginRegistry.register(DownloadPlugin); // Warehousing pluginRegistry.register(StorePlugin);