@teleporthq/teleport-plugin-next-workflows 0.43.67 → 0.43.69
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.
- package/__tests__/_helpers/bind-workflow-utils.ts +16 -1
- package/__tests__/_helpers/fake-fetch.ts +96 -0
- package/__tests__/_helpers/fake-stripe.ts +52 -0
- package/__tests__/_helpers/load-handler.ts +22 -3
- package/__tests__/_helpers/load-invoice-route.ts +75 -0
- package/__tests__/_helpers/load-payment-drivers.ts +69 -0
- package/__tests__/_helpers/load-server-runtime.ts +33 -0
- package/__tests__/_helpers/run-generated-middleware.ts +50 -9
- package/__tests__/admin-form-hydration-target.test.ts +39 -0
- package/__tests__/admin-form-row-hydration.test.ts +58 -0
- package/__tests__/ai-select-database-data-handler.test.ts +14 -3
- package/__tests__/api-route-file-name-segments.test.ts +33 -0
- package/__tests__/app-secret-env.test.ts +55 -0
- package/__tests__/auth-env-secret-preservation.test.ts +22 -3
- package/__tests__/auth-nextauth-url.test.ts +134 -50
- package/__tests__/cart-add-item-kinds.test.ts +259 -0
- package/__tests__/cart-add-item-line-fields.test.ts +328 -0
- package/__tests__/cart-availability-add-to-cart.test.ts +108 -0
- package/__tests__/cart-get-total-discounts.test.ts +499 -0
- package/__tests__/cart-get-total-product-options.test.ts +195 -0
- package/__tests__/cart-get-total-subscriptions.test.ts +221 -0
- package/__tests__/cart-price-order.test.ts +283 -0
- package/__tests__/cart-update-item-quantity-recurring.test.ts +75 -0
- package/__tests__/client-loop-current-item.test.ts +164 -0
- package/__tests__/cron-route-loop-custom-node.test.ts +123 -0
- package/__tests__/cron-route-loop-templateparams.test.ts +7 -0
- package/__tests__/cron-route-verification.test.ts +252 -0
- package/__tests__/custom-js-runtime-base-url.test.ts +64 -0
- package/__tests__/custom-nodes-admin-module.test.ts +310 -0
- package/__tests__/data-api-browser-reads.test.ts +341 -0
- package/__tests__/data-api-low-stock-autofire.test.ts +67 -17
- package/__tests__/data-api-optional-feature-columns.test.ts +240 -0
- package/__tests__/data-api-protected-tables.test.ts +948 -0
- package/__tests__/data-node-not-awaited.test.ts +7 -3
- package/__tests__/data-write-missing-filter.test.ts +119 -0
- package/__tests__/ecommerce-rewriter-product-options.test.ts +143 -0
- package/__tests__/email-locale-senders.test.ts +1 -1
- package/__tests__/file-storage-upload-picked-files.test.ts +20 -0
- package/__tests__/input-debounce-per-field.test.ts +141 -0
- package/__tests__/internal-request-headers.test.ts +7 -3
- package/__tests__/invoice-data-access-replace.test.ts +340 -0
- package/__tests__/invoice-delivery-fee.test.ts +3 -2
- package/__tests__/invoice-generate-hydration.test.ts +20 -12
- package/__tests__/invoice-order-items-settle.test.ts +51 -46
- package/__tests__/invoice-product-options.test.ts +177 -0
- package/__tests__/invoice-regenerate-route.test.ts +488 -0
- package/__tests__/invoice-regional-tax.test.ts +3 -2
- package/__tests__/invoice-reservation.test.ts +195 -0
- package/__tests__/invoice-route-access.test.ts +275 -0
- package/__tests__/invoice-self-call-origin.test.ts +117 -0
- package/__tests__/invoice-tender.test.ts +550 -0
- package/__tests__/legacy-webhook-self-calls.test.ts +187 -0
- package/__tests__/locale-aware-redirects.test.ts +55 -26
- package/__tests__/loop-collection-unwrap.test.ts +6 -1
- package/__tests__/middleware-subscriber-access.test.ts +269 -0
- package/__tests__/payment-charge-user-earlier-attempt.test.ts +267 -0
- package/__tests__/payment-charge-user-handler-serialization.test.ts +47 -82
- package/__tests__/payment-charge-user-line-descriptions.test.ts +124 -0
- package/__tests__/payment-charge-user-report-refusal.test.ts +105 -0
- package/__tests__/payment-close-checkout-node.test.ts +127 -0
- package/__tests__/payment-driver-close-checkout.test.ts +1163 -0
- package/__tests__/payment-driver-coingate.test.ts +470 -0
- package/__tests__/payment-driver-inspect-checkout.test.ts +648 -0
- package/__tests__/payment-driver-mollie.test.ts +864 -0
- package/__tests__/payment-driver-paddle.test.ts +870 -0
- package/__tests__/payment-driver-paypal-capture.test.ts +158 -0
- package/__tests__/payment-driver-paypal-webhook.test.ts +367 -0
- package/__tests__/payment-driver-razorpay.test.ts +895 -0
- package/__tests__/payment-driver-square.test.ts +977 -0
- package/__tests__/payment-driver-stripe.test.ts +267 -0
- package/__tests__/payment-drivers-module.test.ts +429 -0
- package/__tests__/payment-legacy-webhook-routes.test.ts +588 -0
- package/__tests__/payment-redirect-and-order-notification.test.ts +98 -39
- package/__tests__/payment-refund.test.ts +523 -22
- package/__tests__/payment-subscription-nodes.test.ts +1360 -0
- package/__tests__/payment-webhook-route.test.ts +523 -0
- package/__tests__/paypal-webhook-signature-verification.test.ts +205 -0
- package/__tests__/prune-context-oversized-leaf.test.ts +1 -0
- package/__tests__/prune-context-state-keys.test.ts +89 -0
- package/__tests__/push-node-handlers.test.ts +291 -0
- package/__tests__/route-changed-trigger.test.ts +40 -0
- package/__tests__/runtime-storage-upload-access.test.ts +255 -0
- package/__tests__/security-runtime-shadow.test.ts +103 -1
- package/__tests__/segment-reply-changed-keys.test.ts +146 -0
- package/__tests__/segment-state-keys-emission.test.ts +185 -0
- package/__tests__/segment-state-needs.test.ts +102 -0
- package/__tests__/server-segment-context-integrity.test.ts +210 -0
- package/__tests__/server-step-signing.test.ts +371 -0
- package/__tests__/session-cookie-resolver.test.ts +59 -0
- package/__tests__/stock-decrement-audit.test.ts +17 -0
- package/__tests__/subscriber-access-route.test.ts +406 -0
- package/__tests__/webhook-delivery-lease.test.ts +316 -0
- package/__tests__/workflow-auth-guard.test.ts +253 -2
- package/dist/cjs/admin-form-hydration.d.ts +10 -0
- package/dist/cjs/admin-form-hydration.d.ts.map +1 -0
- package/dist/cjs/admin-form-hydration.js +25 -0
- package/dist/cjs/admin-form-hydration.js.map +1 -0
- package/dist/cjs/api-route-generator.d.ts +19 -3
- package/dist/cjs/api-route-generator.d.ts.map +1 -1
- package/dist/cjs/api-route-generator.js +190 -70
- package/dist/cjs/api-route-generator.js.map +1 -1
- package/dist/cjs/auth-generator.d.ts +4 -1
- package/dist/cjs/auth-generator.d.ts.map +1 -1
- package/dist/cjs/auth-generator.js +241 -62
- package/dist/cjs/auth-generator.js.map +1 -1
- package/dist/cjs/auth-return/signed-in-destination-code.d.ts +17 -0
- package/dist/cjs/auth-return/signed-in-destination-code.d.ts.map +1 -0
- package/dist/cjs/auth-return/signed-in-destination-code.js +37 -0
- package/dist/cjs/auth-return/signed-in-destination-code.js.map +1 -0
- package/dist/cjs/cart-pricing-preamble.d.ts +12 -0
- package/dist/cjs/cart-pricing-preamble.d.ts.map +1 -0
- package/dist/cjs/cart-pricing-preamble.js +23 -0
- package/dist/cjs/cart-pricing-preamble.js.map +1 -0
- package/dist/cjs/cron-request-verification.d.ts +24 -0
- package/dist/cjs/cron-request-verification.d.ts.map +1 -0
- package/dist/cjs/cron-request-verification.js +84 -0
- package/dist/cjs/cron-request-verification.js.map +1 -0
- package/dist/cjs/custom-node-modules.d.ts +30 -0
- package/dist/cjs/custom-node-modules.d.ts.map +1 -0
- package/dist/cjs/custom-node-modules.js +90 -0
- package/dist/cjs/custom-node-modules.js.map +1 -0
- package/dist/cjs/data-api-route-generator.d.ts +27 -0
- package/dist/cjs/data-api-route-generator.d.ts.map +1 -1
- package/dist/cjs/data-api-route-generator.js +366 -29
- package/dist/cjs/data-api-route-generator.js.map +1 -1
- package/dist/cjs/ecommerce/cart-availability.d.ts.map +1 -1
- package/dist/cjs/ecommerce/cart-availability.js +22 -13
- package/dist/cjs/ecommerce/cart-availability.js.map +1 -1
- package/dist/cjs/ecommerce/stock-decrement.d.ts +2 -1
- package/dist/cjs/ecommerce/stock-decrement.d.ts.map +1 -1
- package/dist/cjs/ecommerce/stock-decrement.js +6 -0
- package/dist/cjs/ecommerce/stock-decrement.js.map +1 -1
- package/dist/cjs/executor-generator.d.ts +0 -1
- package/dist/cjs/executor-generator.d.ts.map +1 -1
- package/dist/cjs/executor-generator.js +213 -20
- package/dist/cjs/executor-generator.js.map +1 -1
- package/dist/cjs/index.d.ts +12 -4
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +25 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/invoice/api-routes-code.d.ts +26 -0
- package/dist/cjs/invoice/api-routes-code.d.ts.map +1 -1
- package/dist/cjs/invoice/api-routes-code.js +423 -391
- package/dist/cjs/invoice/api-routes-code.js.map +1 -1
- package/dist/cjs/invoice/data-access-code.d.ts.map +1 -1
- package/dist/cjs/invoice/data-access-code.js +420 -107
- package/dist/cjs/invoice/data-access-code.js.map +1 -1
- package/dist/cjs/invoice/index.d.ts.map +1 -1
- package/dist/cjs/invoice/index.js +24 -0
- package/dist/cjs/invoice/index.js.map +1 -1
- package/dist/cjs/invoice/invoice-assembly-code.d.ts +12 -0
- package/dist/cjs/invoice/invoice-assembly-code.d.ts.map +1 -0
- package/dist/cjs/invoice/invoice-assembly-code.js +517 -0
- package/dist/cjs/invoice/invoice-assembly-code.js.map +1 -0
- package/dist/cjs/invoice/invoice-html-code.d.ts.map +1 -1
- package/dist/cjs/invoice/invoice-html-code.js +111 -9
- package/dist/cjs/invoice/invoice-html-code.js.map +1 -1
- package/dist/cjs/invoice/pdf-service-client-code.d.ts.map +1 -1
- package/dist/cjs/invoice/pdf-service-client-code.js +3 -4
- package/dist/cjs/invoice/pdf-service-client-code.js.map +1 -1
- package/dist/cjs/nodes/account/account-login.d.ts.map +1 -1
- package/dist/cjs/nodes/account/account-login.js +4 -3
- package/dist/cjs/nodes/account/account-login.js.map +1 -1
- package/dist/cjs/nodes/account/account-signup.d.ts.map +1 -1
- package/dist/cjs/nodes/account/account-signup.js +7 -4
- package/dist/cjs/nodes/account/account-signup.js.map +1 -1
- package/dist/cjs/nodes/ai/ai-select-database-data.d.ts.map +1 -1
- package/dist/cjs/nodes/ai/ai-select-database-data.js +6 -1
- package/dist/cjs/nodes/ai/ai-select-database-data.js.map +1 -1
- package/dist/cjs/nodes/browser/browser-get-push-subscription.d.ts +9 -0
- package/dist/cjs/nodes/browser/browser-get-push-subscription.d.ts.map +1 -0
- package/dist/cjs/nodes/browser/browser-get-push-subscription.js +25 -0
- package/dist/cjs/nodes/browser/browser-get-push-subscription.js.map +1 -0
- package/dist/cjs/nodes/browser/browser-show-notification.d.ts +10 -0
- package/dist/cjs/nodes/browser/browser-show-notification.d.ts.map +1 -1
- package/dist/cjs/nodes/browser/browser-show-notification.js +65 -40
- package/dist/cjs/nodes/browser/browser-show-notification.js.map +1 -1
- package/dist/cjs/nodes/browser/browser-subscribe-to-push.d.ts +11 -0
- package/dist/cjs/nodes/browser/browser-subscribe-to-push.d.ts.map +1 -1
- package/dist/cjs/nodes/browser/browser-subscribe-to-push.js +21 -31
- package/dist/cjs/nodes/browser/browser-subscribe-to-push.js.map +1 -1
- package/dist/cjs/nodes/browser/browser-unsubscribe-from-push.d.ts +8 -0
- package/dist/cjs/nodes/browser/browser-unsubscribe-from-push.d.ts.map +1 -0
- package/dist/cjs/nodes/browser/browser-unsubscribe-from-push.js +24 -0
- package/dist/cjs/nodes/browser/browser-unsubscribe-from-push.js.map +1 -0
- package/dist/cjs/nodes/browser/push-api-access.d.ts +12 -0
- package/dist/cjs/nodes/browser/push-api-access.d.ts.map +1 -0
- package/dist/cjs/nodes/browser/push-api-access.js +19 -0
- package/dist/cjs/nodes/browser/push-api-access.js.map +1 -0
- package/dist/cjs/nodes/cart/cart-add-item.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-add-item.js +174 -10
- package/dist/cjs/nodes/cart/cart-add-item.js.map +1 -1
- package/dist/cjs/nodes/cart/cart-clear.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-clear.js +11 -0
- package/dist/cjs/nodes/cart/cart-clear.js.map +1 -1
- package/dist/cjs/nodes/cart/cart-get-total.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-get-total.js +260 -3
- package/dist/cjs/nodes/cart/cart-get-total.js.map +1 -1
- package/dist/cjs/nodes/cart/cart-price-order.d.ts +3 -0
- package/dist/cjs/nodes/cart/cart-price-order.d.ts.map +1 -0
- package/dist/cjs/nodes/cart/cart-price-order.js +281 -0
- package/dist/cjs/nodes/cart/cart-price-order.js.map +1 -0
- package/dist/cjs/nodes/cart/cart-update-item-quantity.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-update-item-quantity.js +7 -0
- package/dist/cjs/nodes/cart/cart-update-item-quantity.js.map +1 -1
- package/dist/cjs/nodes/data/data-count.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-count.js +6 -1
- package/dist/cjs/nodes/data/data-count.js.map +1 -1
- package/dist/cjs/nodes/data/data-create-item.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-create-item.js +11 -1
- package/dist/cjs/nodes/data/data-create-item.js.map +1 -1
- package/dist/cjs/nodes/data/data-delete-item.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-delete-item.js +29 -0
- package/dist/cjs/nodes/data/data-delete-item.js.map +1 -1
- package/dist/cjs/nodes/data/data-raw-query.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-raw-query.js +6 -1
- package/dist/cjs/nodes/data/data-raw-query.js.map +1 -1
- package/dist/cjs/nodes/data/data-select.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-select.js +6 -1
- package/dist/cjs/nodes/data/data-select.js.map +1 -1
- package/dist/cjs/nodes/data/data-update-item.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-update-item.js +29 -0
- package/dist/cjs/nodes/data/data-update-item.js.map +1 -1
- package/dist/cjs/nodes/ecommerce/ecommerce-generate-invoice.d.ts.map +1 -1
- package/dist/cjs/nodes/ecommerce/ecommerce-generate-invoice.js +7 -1
- package/dist/cjs/nodes/ecommerce/ecommerce-generate-invoice.js.map +1 -1
- package/dist/cjs/nodes/file-storage/file-storage-upload.d.ts.map +1 -1
- package/dist/cjs/nodes/file-storage/file-storage-upload.js +7 -0
- package/dist/cjs/nodes/file-storage/file-storage-upload.js.map +1 -1
- package/dist/cjs/nodes/general/general-custom-js.d.ts.map +1 -1
- package/dist/cjs/nodes/general/general-custom-js.js +21 -5
- package/dist/cjs/nodes/general/general-custom-js.js.map +1 -1
- package/dist/cjs/nodes/index.d.ts.map +1 -1
- package/dist/cjs/nodes/index.js +9 -4
- package/dist/cjs/nodes/index.js.map +1 -1
- package/dist/cjs/nodes/payment/payment-billing-portal.d.ts +3 -0
- package/dist/cjs/nodes/payment/payment-billing-portal.d.ts.map +1 -0
- package/dist/cjs/nodes/payment/payment-billing-portal.js +52 -0
- package/dist/cjs/nodes/payment/payment-billing-portal.js.map +1 -0
- package/dist/cjs/nodes/payment/payment-charge-user.d.ts.map +1 -1
- package/dist/cjs/nodes/payment/payment-charge-user.js +227 -360
- package/dist/cjs/nodes/payment/payment-charge-user.js.map +1 -1
- package/dist/cjs/nodes/payment/payment-close-checkout.d.ts +3 -0
- package/dist/cjs/nodes/payment/payment-close-checkout.d.ts.map +1 -0
- package/dist/cjs/nodes/payment/payment-close-checkout.js +141 -0
- package/dist/cjs/nodes/payment/payment-close-checkout.js.map +1 -0
- package/dist/cjs/nodes/payment/payment-ensure-subscription-plan.d.ts +3 -0
- package/dist/cjs/nodes/payment/payment-ensure-subscription-plan.d.ts.map +1 -0
- package/dist/cjs/nodes/payment/payment-ensure-subscription-plan.js +67 -0
- package/dist/cjs/nodes/payment/payment-ensure-subscription-plan.js.map +1 -0
- package/dist/cjs/nodes/payment/payment-manage-subscription.d.ts +3 -0
- package/dist/cjs/nodes/payment/payment-manage-subscription.d.ts.map +1 -0
- package/dist/cjs/nodes/payment/payment-manage-subscription.js +89 -0
- package/dist/cjs/nodes/payment/payment-manage-subscription.js.map +1 -0
- package/dist/cjs/nodes/payment/payment-refund.d.ts.map +1 -1
- package/dist/cjs/nodes/payment/payment-refund.js +50 -404
- package/dist/cjs/nodes/payment/payment-refund.js.map +1 -1
- package/dist/cjs/nodes/push/push-send-notification.d.ts +14 -0
- package/dist/cjs/nodes/push/push-send-notification.d.ts.map +1 -0
- package/dist/cjs/nodes/push/push-send-notification.js +83 -0
- package/dist/cjs/nodes/push/push-send-notification.js.map +1 -0
- package/dist/cjs/payments/drivers/coingate-driver-code.d.ts +16 -0
- package/dist/cjs/payments/drivers/coingate-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/coingate-driver-code.js +471 -0
- package/dist/cjs/payments/drivers/coingate-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/mollie-driver-code.d.ts +16 -0
- package/dist/cjs/payments/drivers/mollie-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/mollie-driver-code.js +623 -0
- package/dist/cjs/payments/drivers/mollie-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/paddle-driver-code.d.ts +12 -0
- package/dist/cjs/payments/drivers/paddle-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/paddle-driver-code.js +683 -0
- package/dist/cjs/payments/drivers/paddle-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/paypal-driver-code.d.ts +12 -0
- package/dist/cjs/payments/drivers/paypal-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/paypal-driver-code.js +1261 -0
- package/dist/cjs/payments/drivers/paypal-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/razorpay-driver-code.d.ts +12 -0
- package/dist/cjs/payments/drivers/razorpay-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/razorpay-driver-code.js +732 -0
- package/dist/cjs/payments/drivers/razorpay-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/square-driver-code.d.ts +14 -0
- package/dist/cjs/payments/drivers/square-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/square-driver-code.js +931 -0
- package/dist/cjs/payments/drivers/square-driver-code.js.map +1 -0
- package/dist/cjs/payments/drivers/stripe-driver-code.d.ts +12 -0
- package/dist/cjs/payments/drivers/stripe-driver-code.d.ts.map +1 -0
- package/dist/cjs/payments/drivers/stripe-driver-code.js +778 -0
- package/dist/cjs/payments/drivers/stripe-driver-code.js.map +1 -0
- package/dist/cjs/payments/index.d.ts +66 -0
- package/dist/cjs/payments/index.d.ts.map +1 -0
- package/dist/cjs/payments/index.js +175 -0
- package/dist/cjs/payments/index.js.map +1 -0
- package/dist/cjs/payments/payment-core-code.d.ts +19 -0
- package/dist/cjs/payments/payment-core-code.d.ts.map +1 -0
- package/dist/cjs/payments/payment-core-code.js +422 -0
- package/dist/cjs/payments/payment-core-code.js.map +1 -0
- package/dist/cjs/payments/payment-driver-code-map.d.ts +4 -0
- package/dist/cjs/payments/payment-driver-code-map.d.ts.map +1 -0
- package/dist/cjs/payments/payment-driver-code-map.js +21 -0
- package/dist/cjs/payments/payment-driver-code-map.js.map +1 -0
- package/dist/cjs/payments/payment-drivers-scope.d.ts +35 -0
- package/dist/cjs/payments/payment-drivers-scope.d.ts.map +1 -0
- package/dist/cjs/payments/payment-drivers-scope.js +56 -0
- package/dist/cjs/payments/payment-drivers-scope.js.map +1 -0
- package/dist/cjs/payments/payment-registry-code.d.ts +8 -0
- package/dist/cjs/payments/payment-registry-code.d.ts.map +1 -0
- package/dist/cjs/payments/payment-registry-code.js +41 -0
- package/dist/cjs/payments/payment-registry-code.js.map +1 -0
- package/dist/cjs/pg-client-code.d.ts +10 -0
- package/dist/cjs/pg-client-code.d.ts.map +1 -1
- package/dist/cjs/pg-client-code.js +27 -1
- package/dist/cjs/pg-client-code.js.map +1 -1
- package/dist/cjs/runtime-storage-generator.d.ts +28 -0
- package/dist/cjs/runtime-storage-generator.d.ts.map +1 -1
- package/dist/cjs/runtime-storage-generator.js +240 -5
- package/dist/cjs/runtime-storage-generator.js.map +1 -1
- package/dist/cjs/secret-collector.d.ts.map +1 -1
- package/dist/cjs/secret-collector.js +8 -3
- package/dist/cjs/secret-collector.js.map +1 -1
- package/dist/cjs/security-scanner.d.ts +10 -1
- package/dist/cjs/security-scanner.d.ts.map +1 -1
- package/dist/cjs/security-scanner.js +19 -1
- package/dist/cjs/security-scanner.js.map +1 -1
- package/dist/cjs/segment-context-needs.d.ts +38 -0
- package/dist/cjs/segment-context-needs.d.ts.map +1 -0
- package/dist/cjs/segment-context-needs.js +129 -0
- package/dist/cjs/segment-context-needs.js.map +1 -0
- package/dist/cjs/segment-splitter.d.ts.map +1 -1
- package/dist/cjs/segment-splitter.js +6 -1
- package/dist/cjs/segment-splitter.js.map +1 -1
- package/dist/cjs/segment-trust.d.ts +50 -0
- package/dist/cjs/segment-trust.d.ts.map +1 -0
- package/dist/cjs/segment-trust.js +115 -0
- package/dist/cjs/segment-trust.js.map +1 -0
- package/dist/cjs/sent-email-log/sent-email-log-code.d.ts +19 -0
- package/dist/cjs/sent-email-log/sent-email-log-code.d.ts.map +1 -1
- package/dist/cjs/sent-email-log/sent-email-log-code.js +1 -24
- package/dist/cjs/sent-email-log/sent-email-log-code.js.map +1 -1
- package/dist/cjs/server-runtime-code.d.ts +34 -0
- package/dist/cjs/server-runtime-code.d.ts.map +1 -0
- package/dist/cjs/server-runtime-code.js +303 -0
- package/dist/cjs/server-runtime-code.js.map +1 -0
- package/dist/cjs/session-cookie-resolver.d.ts +3 -78
- package/dist/cjs/session-cookie-resolver.d.ts.map +1 -1
- package/dist/cjs/session-cookie-resolver.js +7 -276
- package/dist/cjs/session-cookie-resolver.js.map +1 -1
- package/dist/cjs/subscriber-access-route-generator.d.ts +71 -0
- package/dist/cjs/subscriber-access-route-generator.d.ts.map +1 -0
- package/dist/cjs/subscriber-access-route-generator.js +301 -0
- package/dist/cjs/subscriber-access-route-generator.js.map +1 -0
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/types.d.ts +6 -0
- package/dist/cjs/types.d.ts.map +1 -1
- package/dist/cjs/webhook-delivery-lease/index.d.ts +8 -0
- package/dist/cjs/webhook-delivery-lease/index.d.ts.map +1 -0
- package/dist/cjs/webhook-delivery-lease/index.js +41 -0
- package/dist/cjs/webhook-delivery-lease/index.js.map +1 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-code.d.ts +26 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-code.d.ts.map +1 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-code.js +151 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-code.js.map +1 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-scope.d.ts +16 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-scope.d.ts.map +1 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-scope.js +19 -0
- package/dist/cjs/webhook-delivery-lease/webhook-delivery-lease-scope.js.map +1 -0
- package/dist/cjs/webhook-generator.d.ts +1 -1
- package/dist/cjs/webhook-generator.d.ts.map +1 -1
- package/dist/cjs/webhook-generator.js +342 -254
- package/dist/cjs/webhook-generator.js.map +1 -1
- package/dist/cjs/webhook-signature-verification.d.ts +17 -1
- package/dist/cjs/webhook-signature-verification.d.ts.map +1 -1
- package/dist/cjs/webhook-signature-verification.js +182 -27
- package/dist/cjs/webhook-signature-verification.js.map +1 -1
- package/dist/cjs/workflow-auth-generator.d.ts +9 -6
- package/dist/cjs/workflow-auth-generator.d.ts.map +1 -1
- package/dist/cjs/workflow-auth-generator.js +133 -29
- package/dist/cjs/workflow-auth-generator.js.map +1 -1
- package/dist/cjs/workflow-component-plugin.d.ts.map +1 -1
- package/dist/cjs/workflow-component-plugin.js +65 -28
- package/dist/cjs/workflow-component-plugin.js.map +1 -1
- package/dist/cjs/workflow-project-plugin.d.ts +13 -0
- package/dist/cjs/workflow-project-plugin.d.ts.map +1 -1
- package/dist/cjs/workflow-project-plugin.js +215 -65
- package/dist/cjs/workflow-project-plugin.js.map +1 -1
- package/dist/esm/admin-form-hydration.d.ts +10 -0
- package/dist/esm/admin-form-hydration.d.ts.map +1 -0
- package/dist/esm/admin-form-hydration.js +21 -0
- package/dist/esm/admin-form-hydration.js.map +1 -0
- package/dist/esm/api-route-generator.d.ts +19 -3
- package/dist/esm/api-route-generator.d.ts.map +1 -1
- package/dist/esm/api-route-generator.js +189 -70
- package/dist/esm/api-route-generator.js.map +1 -1
- package/dist/esm/auth-generator.d.ts +4 -1
- package/dist/esm/auth-generator.d.ts.map +1 -1
- package/dist/esm/auth-generator.js +241 -62
- package/dist/esm/auth-generator.js.map +1 -1
- package/dist/esm/auth-return/signed-in-destination-code.d.ts +17 -0
- package/dist/esm/auth-return/signed-in-destination-code.d.ts.map +1 -0
- package/dist/esm/auth-return/signed-in-destination-code.js +33 -0
- package/dist/esm/auth-return/signed-in-destination-code.js.map +1 -0
- package/dist/esm/cart-pricing-preamble.d.ts +12 -0
- package/dist/esm/cart-pricing-preamble.d.ts.map +1 -0
- package/dist/esm/cart-pricing-preamble.js +19 -0
- package/dist/esm/cart-pricing-preamble.js.map +1 -0
- package/dist/esm/cron-request-verification.d.ts +24 -0
- package/dist/esm/cron-request-verification.d.ts.map +1 -0
- package/dist/esm/cron-request-verification.js +80 -0
- package/dist/esm/cron-request-verification.js.map +1 -0
- package/dist/esm/custom-node-modules.d.ts +30 -0
- package/dist/esm/custom-node-modules.d.ts.map +1 -0
- package/dist/esm/custom-node-modules.js +84 -0
- package/dist/esm/custom-node-modules.js.map +1 -0
- package/dist/esm/data-api-route-generator.d.ts +27 -0
- package/dist/esm/data-api-route-generator.d.ts.map +1 -1
- package/dist/esm/data-api-route-generator.js +365 -28
- package/dist/esm/data-api-route-generator.js.map +1 -1
- package/dist/esm/ecommerce/cart-availability.d.ts.map +1 -1
- package/dist/esm/ecommerce/cart-availability.js +22 -13
- package/dist/esm/ecommerce/cart-availability.js.map +1 -1
- package/dist/esm/ecommerce/stock-decrement.d.ts +2 -1
- package/dist/esm/ecommerce/stock-decrement.d.ts.map +1 -1
- package/dist/esm/ecommerce/stock-decrement.js +6 -0
- package/dist/esm/ecommerce/stock-decrement.js.map +1 -1
- package/dist/esm/executor-generator.d.ts +0 -1
- package/dist/esm/executor-generator.d.ts.map +1 -1
- package/dist/esm/executor-generator.js +212 -18
- package/dist/esm/executor-generator.js.map +1 -1
- package/dist/esm/index.d.ts +12 -4
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +10 -4
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/invoice/api-routes-code.d.ts +26 -0
- package/dist/esm/invoice/api-routes-code.d.ts.map +1 -1
- package/dist/esm/invoice/api-routes-code.js +421 -390
- package/dist/esm/invoice/api-routes-code.js.map +1 -1
- package/dist/esm/invoice/data-access-code.d.ts.map +1 -1
- package/dist/esm/invoice/data-access-code.js +420 -107
- package/dist/esm/invoice/data-access-code.js.map +1 -1
- package/dist/esm/invoice/index.d.ts.map +1 -1
- package/dist/esm/invoice/index.js +25 -1
- package/dist/esm/invoice/index.js.map +1 -1
- package/dist/esm/invoice/invoice-assembly-code.d.ts +12 -0
- package/dist/esm/invoice/invoice-assembly-code.d.ts.map +1 -0
- package/dist/esm/invoice/invoice-assembly-code.js +513 -0
- package/dist/esm/invoice/invoice-assembly-code.js.map +1 -0
- package/dist/esm/invoice/invoice-html-code.d.ts.map +1 -1
- package/dist/esm/invoice/invoice-html-code.js +111 -9
- package/dist/esm/invoice/invoice-html-code.js.map +1 -1
- package/dist/esm/invoice/pdf-service-client-code.d.ts.map +1 -1
- package/dist/esm/invoice/pdf-service-client-code.js +3 -4
- package/dist/esm/invoice/pdf-service-client-code.js.map +1 -1
- package/dist/esm/nodes/account/account-login.d.ts.map +1 -1
- package/dist/esm/nodes/account/account-login.js +4 -3
- package/dist/esm/nodes/account/account-login.js.map +1 -1
- package/dist/esm/nodes/account/account-signup.d.ts.map +1 -1
- package/dist/esm/nodes/account/account-signup.js +7 -4
- package/dist/esm/nodes/account/account-signup.js.map +1 -1
- package/dist/esm/nodes/ai/ai-select-database-data.d.ts.map +1 -1
- package/dist/esm/nodes/ai/ai-select-database-data.js +6 -1
- package/dist/esm/nodes/ai/ai-select-database-data.js.map +1 -1
- package/dist/esm/nodes/browser/browser-get-push-subscription.d.ts +9 -0
- package/dist/esm/nodes/browser/browser-get-push-subscription.d.ts.map +1 -0
- package/dist/esm/nodes/browser/browser-get-push-subscription.js +22 -0
- package/dist/esm/nodes/browser/browser-get-push-subscription.js.map +1 -0
- package/dist/esm/nodes/browser/browser-show-notification.d.ts +10 -0
- package/dist/esm/nodes/browser/browser-show-notification.d.ts.map +1 -1
- package/dist/esm/nodes/browser/browser-show-notification.js +65 -40
- package/dist/esm/nodes/browser/browser-show-notification.js.map +1 -1
- package/dist/esm/nodes/browser/browser-subscribe-to-push.d.ts +11 -0
- package/dist/esm/nodes/browser/browser-subscribe-to-push.d.ts.map +1 -1
- package/dist/esm/nodes/browser/browser-subscribe-to-push.js +21 -31
- package/dist/esm/nodes/browser/browser-subscribe-to-push.js.map +1 -1
- package/dist/esm/nodes/browser/browser-unsubscribe-from-push.d.ts +8 -0
- package/dist/esm/nodes/browser/browser-unsubscribe-from-push.d.ts.map +1 -0
- package/dist/esm/nodes/browser/browser-unsubscribe-from-push.js +21 -0
- package/dist/esm/nodes/browser/browser-unsubscribe-from-push.js.map +1 -0
- package/dist/esm/nodes/browser/push-api-access.d.ts +12 -0
- package/dist/esm/nodes/browser/push-api-access.d.ts.map +1 -0
- package/dist/esm/nodes/browser/push-api-access.js +13 -0
- package/dist/esm/nodes/browser/push-api-access.js.map +1 -0
- package/dist/esm/nodes/cart/cart-add-item.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-add-item.js +174 -10
- package/dist/esm/nodes/cart/cart-add-item.js.map +1 -1
- package/dist/esm/nodes/cart/cart-clear.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-clear.js +11 -0
- package/dist/esm/nodes/cart/cart-clear.js.map +1 -1
- package/dist/esm/nodes/cart/cart-get-total.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-get-total.js +261 -4
- package/dist/esm/nodes/cart/cart-get-total.js.map +1 -1
- package/dist/esm/nodes/cart/cart-price-order.d.ts +3 -0
- package/dist/esm/nodes/cart/cart-price-order.d.ts.map +1 -0
- package/dist/esm/nodes/cart/cart-price-order.js +278 -0
- package/dist/esm/nodes/cart/cart-price-order.js.map +1 -0
- package/dist/esm/nodes/cart/cart-update-item-quantity.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-update-item-quantity.js +7 -0
- package/dist/esm/nodes/cart/cart-update-item-quantity.js.map +1 -1
- package/dist/esm/nodes/data/data-count.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-count.js +6 -1
- package/dist/esm/nodes/data/data-count.js.map +1 -1
- package/dist/esm/nodes/data/data-create-item.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-create-item.js +11 -1
- package/dist/esm/nodes/data/data-create-item.js.map +1 -1
- package/dist/esm/nodes/data/data-delete-item.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-delete-item.js +29 -0
- package/dist/esm/nodes/data/data-delete-item.js.map +1 -1
- package/dist/esm/nodes/data/data-raw-query.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-raw-query.js +6 -1
- package/dist/esm/nodes/data/data-raw-query.js.map +1 -1
- package/dist/esm/nodes/data/data-select.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-select.js +6 -1
- package/dist/esm/nodes/data/data-select.js.map +1 -1
- package/dist/esm/nodes/data/data-update-item.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-update-item.js +29 -0
- package/dist/esm/nodes/data/data-update-item.js.map +1 -1
- package/dist/esm/nodes/ecommerce/ecommerce-generate-invoice.d.ts.map +1 -1
- package/dist/esm/nodes/ecommerce/ecommerce-generate-invoice.js +7 -1
- package/dist/esm/nodes/ecommerce/ecommerce-generate-invoice.js.map +1 -1
- package/dist/esm/nodes/file-storage/file-storage-upload.d.ts.map +1 -1
- package/dist/esm/nodes/file-storage/file-storage-upload.js +7 -0
- package/dist/esm/nodes/file-storage/file-storage-upload.js.map +1 -1
- package/dist/esm/nodes/general/general-custom-js.d.ts.map +1 -1
- package/dist/esm/nodes/general/general-custom-js.js +21 -5
- package/dist/esm/nodes/general/general-custom-js.js.map +1 -1
- package/dist/esm/nodes/index.d.ts.map +1 -1
- package/dist/esm/nodes/index.js +9 -4
- package/dist/esm/nodes/index.js.map +1 -1
- package/dist/esm/nodes/payment/payment-billing-portal.d.ts +3 -0
- package/dist/esm/nodes/payment/payment-billing-portal.d.ts.map +1 -0
- package/dist/esm/nodes/payment/payment-billing-portal.js +49 -0
- package/dist/esm/nodes/payment/payment-billing-portal.js.map +1 -0
- package/dist/esm/nodes/payment/payment-charge-user.d.ts.map +1 -1
- package/dist/esm/nodes/payment/payment-charge-user.js +227 -360
- package/dist/esm/nodes/payment/payment-charge-user.js.map +1 -1
- package/dist/esm/nodes/payment/payment-close-checkout.d.ts +3 -0
- package/dist/esm/nodes/payment/payment-close-checkout.d.ts.map +1 -0
- package/dist/esm/nodes/payment/payment-close-checkout.js +138 -0
- package/dist/esm/nodes/payment/payment-close-checkout.js.map +1 -0
- package/dist/esm/nodes/payment/payment-ensure-subscription-plan.d.ts +3 -0
- package/dist/esm/nodes/payment/payment-ensure-subscription-plan.d.ts.map +1 -0
- package/dist/esm/nodes/payment/payment-ensure-subscription-plan.js +64 -0
- package/dist/esm/nodes/payment/payment-ensure-subscription-plan.js.map +1 -0
- package/dist/esm/nodes/payment/payment-manage-subscription.d.ts +3 -0
- package/dist/esm/nodes/payment/payment-manage-subscription.d.ts.map +1 -0
- package/dist/esm/nodes/payment/payment-manage-subscription.js +86 -0
- package/dist/esm/nodes/payment/payment-manage-subscription.js.map +1 -0
- package/dist/esm/nodes/payment/payment-refund.d.ts.map +1 -1
- package/dist/esm/nodes/payment/payment-refund.js +50 -404
- package/dist/esm/nodes/payment/payment-refund.js.map +1 -1
- package/dist/esm/nodes/push/push-send-notification.d.ts +14 -0
- package/dist/esm/nodes/push/push-send-notification.d.ts.map +1 -0
- package/dist/esm/nodes/push/push-send-notification.js +80 -0
- package/dist/esm/nodes/push/push-send-notification.js.map +1 -0
- package/dist/esm/payments/drivers/coingate-driver-code.d.ts +16 -0
- package/dist/esm/payments/drivers/coingate-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/coingate-driver-code.js +467 -0
- package/dist/esm/payments/drivers/coingate-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/mollie-driver-code.d.ts +16 -0
- package/dist/esm/payments/drivers/mollie-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/mollie-driver-code.js +619 -0
- package/dist/esm/payments/drivers/mollie-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/paddle-driver-code.d.ts +12 -0
- package/dist/esm/payments/drivers/paddle-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/paddle-driver-code.js +679 -0
- package/dist/esm/payments/drivers/paddle-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/paypal-driver-code.d.ts +12 -0
- package/dist/esm/payments/drivers/paypal-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/paypal-driver-code.js +1257 -0
- package/dist/esm/payments/drivers/paypal-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/razorpay-driver-code.d.ts +12 -0
- package/dist/esm/payments/drivers/razorpay-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/razorpay-driver-code.js +728 -0
- package/dist/esm/payments/drivers/razorpay-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/square-driver-code.d.ts +14 -0
- package/dist/esm/payments/drivers/square-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/square-driver-code.js +927 -0
- package/dist/esm/payments/drivers/square-driver-code.js.map +1 -0
- package/dist/esm/payments/drivers/stripe-driver-code.d.ts +12 -0
- package/dist/esm/payments/drivers/stripe-driver-code.d.ts.map +1 -0
- package/dist/esm/payments/drivers/stripe-driver-code.js +774 -0
- package/dist/esm/payments/drivers/stripe-driver-code.js.map +1 -0
- package/dist/esm/payments/index.d.ts +66 -0
- package/dist/esm/payments/index.d.ts.map +1 -0
- package/dist/esm/payments/index.js +164 -0
- package/dist/esm/payments/index.js.map +1 -0
- package/dist/esm/payments/payment-core-code.d.ts +19 -0
- package/dist/esm/payments/payment-core-code.d.ts.map +1 -0
- package/dist/esm/payments/payment-core-code.js +418 -0
- package/dist/esm/payments/payment-core-code.js.map +1 -0
- package/dist/esm/payments/payment-driver-code-map.d.ts +4 -0
- package/dist/esm/payments/payment-driver-code-map.d.ts.map +1 -0
- package/dist/esm/payments/payment-driver-code-map.js +18 -0
- package/dist/esm/payments/payment-driver-code-map.js.map +1 -0
- package/dist/esm/payments/payment-drivers-scope.d.ts +35 -0
- package/dist/esm/payments/payment-drivers-scope.d.ts.map +1 -0
- package/dist/esm/payments/payment-drivers-scope.js +51 -0
- package/dist/esm/payments/payment-drivers-scope.js.map +1 -0
- package/dist/esm/payments/payment-registry-code.d.ts +8 -0
- package/dist/esm/payments/payment-registry-code.d.ts.map +1 -0
- package/dist/esm/payments/payment-registry-code.js +37 -0
- package/dist/esm/payments/payment-registry-code.js.map +1 -0
- package/dist/esm/pg-client-code.d.ts +10 -0
- package/dist/esm/pg-client-code.d.ts.map +1 -1
- package/dist/esm/pg-client-code.js +25 -0
- package/dist/esm/pg-client-code.js.map +1 -1
- package/dist/esm/runtime-storage-generator.d.ts +28 -0
- package/dist/esm/runtime-storage-generator.d.ts.map +1 -1
- package/dist/esm/runtime-storage-generator.js +239 -4
- package/dist/esm/runtime-storage-generator.js.map +1 -1
- package/dist/esm/secret-collector.d.ts.map +1 -1
- package/dist/esm/secret-collector.js +8 -3
- package/dist/esm/secret-collector.js.map +1 -1
- package/dist/esm/security-scanner.d.ts +10 -1
- package/dist/esm/security-scanner.d.ts.map +1 -1
- package/dist/esm/security-scanner.js +18 -0
- package/dist/esm/security-scanner.js.map +1 -1
- package/dist/esm/segment-context-needs.d.ts +38 -0
- package/dist/esm/segment-context-needs.d.ts.map +1 -0
- package/dist/esm/segment-context-needs.js +125 -0
- package/dist/esm/segment-context-needs.js.map +1 -0
- package/dist/esm/segment-splitter.d.ts.map +1 -1
- package/dist/esm/segment-splitter.js +6 -1
- package/dist/esm/segment-splitter.js.map +1 -1
- package/dist/esm/segment-trust.d.ts +50 -0
- package/dist/esm/segment-trust.d.ts.map +1 -0
- package/dist/esm/segment-trust.js +111 -0
- package/dist/esm/segment-trust.js.map +1 -0
- package/dist/esm/sent-email-log/sent-email-log-code.d.ts +19 -0
- package/dist/esm/sent-email-log/sent-email-log-code.d.ts.map +1 -1
- package/dist/esm/sent-email-log/sent-email-log-code.js +2 -25
- package/dist/esm/sent-email-log/sent-email-log-code.js.map +1 -1
- package/dist/esm/server-runtime-code.d.ts +34 -0
- package/dist/esm/server-runtime-code.d.ts.map +1 -0
- package/dist/esm/server-runtime-code.js +299 -0
- package/dist/esm/server-runtime-code.js.map +1 -0
- package/dist/esm/session-cookie-resolver.d.ts +3 -78
- package/dist/esm/session-cookie-resolver.d.ts.map +1 -1
- package/dist/esm/session-cookie-resolver.js +7 -274
- package/dist/esm/session-cookie-resolver.js.map +1 -1
- package/dist/esm/subscriber-access-route-generator.d.ts +71 -0
- package/dist/esm/subscriber-access-route-generator.d.ts.map +1 -0
- package/dist/esm/subscriber-access-route-generator.js +292 -0
- package/dist/esm/subscriber-access-route-generator.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/types.d.ts +6 -0
- package/dist/esm/types.d.ts.map +1 -1
- package/dist/esm/webhook-delivery-lease/index.d.ts +8 -0
- package/dist/esm/webhook-delivery-lease/index.d.ts.map +1 -0
- package/dist/esm/webhook-delivery-lease/index.js +37 -0
- package/dist/esm/webhook-delivery-lease/index.js.map +1 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-code.d.ts +26 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-code.d.ts.map +1 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-code.js +147 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-code.js.map +1 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-scope.d.ts +16 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-scope.d.ts.map +1 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-scope.js +16 -0
- package/dist/esm/webhook-delivery-lease/webhook-delivery-lease-scope.js.map +1 -0
- package/dist/esm/webhook-generator.d.ts +1 -1
- package/dist/esm/webhook-generator.d.ts.map +1 -1
- package/dist/esm/webhook-generator.js +342 -254
- package/dist/esm/webhook-generator.js.map +1 -1
- package/dist/esm/webhook-signature-verification.d.ts +17 -1
- package/dist/esm/webhook-signature-verification.d.ts.map +1 -1
- package/dist/esm/webhook-signature-verification.js +179 -25
- package/dist/esm/webhook-signature-verification.js.map +1 -1
- package/dist/esm/workflow-auth-generator.d.ts +9 -6
- package/dist/esm/workflow-auth-generator.d.ts.map +1 -1
- package/dist/esm/workflow-auth-generator.js +132 -28
- package/dist/esm/workflow-auth-generator.js.map +1 -1
- package/dist/esm/workflow-component-plugin.d.ts.map +1 -1
- package/dist/esm/workflow-component-plugin.js +65 -28
- package/dist/esm/workflow-component-plugin.js.map +1 -1
- package/dist/esm/workflow-project-plugin.d.ts +13 -0
- package/dist/esm/workflow-project-plugin.d.ts.map +1 -1
- package/dist/esm/workflow-project-plugin.js +212 -63
- package/dist/esm/workflow-project-plugin.js.map +1 -1
- package/package.json +4 -4
- package/src/admin-form-hydration.ts +28 -0
- package/src/api-route-generator.ts +251 -64
- package/src/auth-generator.ts +273 -53
- package/src/auth-return/signed-in-destination-code.ts +32 -0
- package/src/cart-pricing-preamble.ts +22 -0
- package/src/cron-request-verification.ts +79 -0
- package/src/custom-node-modules.ts +102 -0
- package/src/data-api-route-generator.ts +370 -28
- package/src/ecommerce/cart-availability.ts +22 -13
- package/src/ecommerce/stock-decrement.ts +13 -1
- package/src/executor-generator.ts +212 -19
- package/src/index.ts +28 -7
- package/src/invoice/api-routes-code.ts +424 -391
- package/src/invoice/data-access-code.ts +431 -110
- package/src/invoice/index.ts +31 -1
- package/src/invoice/invoice-assembly-code.ts +514 -0
- package/src/invoice/invoice-html-code.ts +111 -9
- package/src/invoice/pdf-service-client-code.ts +3 -4
- package/src/nodes/account/account-login.ts +4 -3
- package/src/nodes/account/account-signup.ts +7 -4
- package/src/nodes/ai/ai-select-database-data.ts +10 -1
- package/src/nodes/browser/browser-get-push-subscription.ts +23 -0
- package/src/nodes/browser/browser-show-notification.ts +61 -38
- package/src/nodes/browser/browser-subscribe-to-push.ts +26 -36
- package/src/nodes/browser/browser-unsubscribe-from-push.ts +22 -0
- package/src/nodes/browser/push-api-access.ts +20 -0
- package/src/nodes/cart/cart-add-item.ts +200 -9
- package/src/nodes/cart/cart-clear.ts +11 -0
- package/src/nodes/cart/cart-get-total.ts +279 -7
- package/src/nodes/cart/cart-price-order.ts +351 -0
- package/src/nodes/cart/cart-update-item-quantity.ts +7 -0
- package/src/nodes/data/data-count.ts +9 -1
- package/src/nodes/data/data-create-item.ts +15 -1
- package/src/nodes/data/data-delete-item.ts +32 -0
- package/src/nodes/data/data-raw-query.ts +9 -1
- package/src/nodes/data/data-select.ts +9 -1
- package/src/nodes/data/data-update-item.ts +32 -0
- package/src/nodes/ecommerce/ecommerce-generate-invoice.ts +11 -1
- package/src/nodes/file-storage/file-storage-upload.ts +8 -0
- package/src/nodes/general/general-custom-js.ts +21 -5
- package/src/nodes/index.ts +16 -6
- package/src/nodes/payment/payment-billing-portal.ts +51 -0
- package/src/nodes/payment/payment-charge-user.ts +236 -442
- package/src/nodes/payment/payment-close-checkout.ts +137 -0
- package/src/nodes/payment/payment-ensure-subscription-plan.ts +66 -0
- package/src/nodes/payment/payment-manage-subscription.ts +89 -0
- package/src/nodes/payment/payment-refund.ts +52 -467
- package/src/nodes/payment-drivers-global.d.ts +13 -0
- package/src/nodes/push/push-send-notification.ts +83 -0
- package/src/nodes/workflow-utils-global.d.ts +5 -0
- package/src/payments/drivers/coingate-driver-code.ts +466 -0
- package/src/payments/drivers/mollie-driver-code.ts +618 -0
- package/src/payments/drivers/paddle-driver-code.ts +678 -0
- package/src/payments/drivers/paypal-driver-code.ts +1256 -0
- package/src/payments/drivers/razorpay-driver-code.ts +727 -0
- package/src/payments/drivers/square-driver-code.ts +926 -0
- package/src/payments/drivers/stripe-driver-code.ts +773 -0
- package/src/payments/index.ts +204 -0
- package/src/payments/payment-core-code.ts +421 -0
- package/src/payments/payment-driver-code-map.ts +19 -0
- package/src/payments/payment-drivers-scope.ts +66 -0
- package/src/payments/payment-registry-code.ts +38 -0
- package/src/pg-client-code.ts +30 -0
- package/src/runtime-storage-generator.ts +241 -4
- package/src/secret-collector.ts +8 -3
- package/src/security-scanner.ts +22 -0
- package/src/segment-context-needs.ts +148 -0
- package/src/segment-splitter.ts +6 -1
- package/src/segment-trust.ts +170 -0
- package/src/sent-email-log/sent-email-log-code.ts +2 -32
- package/src/server-runtime-code.ts +298 -0
- package/src/session-cookie-resolver.ts +9 -277
- package/src/subscriber-access-route-generator.ts +351 -0
- package/src/types.ts +6 -0
- package/src/webhook-delivery-lease/index.ts +44 -0
- package/src/webhook-delivery-lease/webhook-delivery-lease-code.ts +151 -0
- package/src/webhook-delivery-lease/webhook-delivery-lease-scope.ts +18 -0
- package/src/webhook-generator.ts +359 -260
- package/src/webhook-signature-verification.ts +180 -25
- package/src/workflow-auth-generator.ts +137 -28
- package/src/workflow-component-plugin.ts +77 -20
- package/src/workflow-project-plugin.ts +247 -44
- package/dist/cjs/nodes/payment/payment-cancel-plan.d.ts +0 -3
- package/dist/cjs/nodes/payment/payment-cancel-plan.d.ts.map +0 -1
- package/dist/cjs/nodes/payment/payment-cancel-plan.js +0 -33
- package/dist/cjs/nodes/payment/payment-cancel-plan.js.map +0 -1
- package/dist/cjs/nodes/payment/payment-create-subscription.d.ts +0 -3
- package/dist/cjs/nodes/payment/payment-create-subscription.d.ts.map +0 -1
- package/dist/cjs/nodes/payment/payment-create-subscription.js +0 -41
- package/dist/cjs/nodes/payment/payment-create-subscription.js.map +0 -1
- package/dist/cjs/nodes/payment/payment-subscribe-to-plan.d.ts +0 -3
- package/dist/cjs/nodes/payment/payment-subscribe-to-plan.d.ts.map +0 -1
- package/dist/cjs/nodes/payment/payment-subscribe-to-plan.js +0 -45
- package/dist/cjs/nodes/payment/payment-subscribe-to-plan.js.map +0 -1
- package/dist/esm/nodes/payment/payment-cancel-plan.d.ts +0 -3
- package/dist/esm/nodes/payment/payment-cancel-plan.d.ts.map +0 -1
- package/dist/esm/nodes/payment/payment-cancel-plan.js +0 -30
- package/dist/esm/nodes/payment/payment-cancel-plan.js.map +0 -1
- package/dist/esm/nodes/payment/payment-create-subscription.d.ts +0 -3
- package/dist/esm/nodes/payment/payment-create-subscription.d.ts.map +0 -1
- package/dist/esm/nodes/payment/payment-create-subscription.js +0 -38
- package/dist/esm/nodes/payment/payment-create-subscription.js.map +0 -1
- package/dist/esm/nodes/payment/payment-subscribe-to-plan.d.ts +0 -3
- package/dist/esm/nodes/payment/payment-subscribe-to-plan.d.ts.map +0 -1
- package/dist/esm/nodes/payment/payment-subscribe-to-plan.js +0 -42
- package/dist/esm/nodes/payment/payment-subscribe-to-plan.js.map +0 -1
- package/src/nodes/payment/payment-cancel-plan.ts +0 -33
- package/src/nodes/payment/payment-create-subscription.ts +0 -42
- package/src/nodes/payment/payment-subscribe-to-plan.ts +0 -46
|
@@ -1,24 +1,79 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { generateCommonJsSessionTokenResolverCode } from '../session-cookie-resolver';
|
|
2
|
+
import { ROLE_OF_TOKEN_CODE } from '../workflow-auth-generator';
|
|
3
|
+
/**
|
|
4
|
+
* The roles that act on invoices from a browser: the ones every generated
|
|
5
|
+
* admin-panel page is protected with, since the admin panel is the only
|
|
6
|
+
* browser that issues, rebuilds or lists every invoice.
|
|
7
|
+
*/
|
|
8
|
+
const INVOICE_ADMIN_ROLES = ['admin'];
|
|
9
|
+
/**
|
|
10
|
+
* Who is calling an invoice route, as ES5 source shared by the routes:
|
|
11
|
+
* `invoiceCaller(req)` resolves to `{ server, signedIn, admin, userId }`.
|
|
12
|
+
*
|
|
13
|
+
* `server` is this deployment's own server code — the invoice node of a
|
|
14
|
+
* payment webhook or a checkout segment, the payment webhooks — which presents
|
|
15
|
+
* the app secret in `x-internal-data-secret`. Only server code can read
|
|
16
|
+
* NEXTAUTH_SECRET, so a browser cannot forge it; it is compared in constant
|
|
17
|
+
* time. Everyone else is who their session says they are.
|
|
18
|
+
*/
|
|
19
|
+
const INVOICE_CALLER_CODE = `${generateCommonJsSessionTokenResolverCode()}
|
|
20
|
+
${ROLE_OF_TOKEN_CODE}
|
|
21
|
+
|
|
22
|
+
var INVOICE_ADMIN_ROLES = ${JSON.stringify(INVOICE_ADMIN_ROLES)};
|
|
23
|
+
|
|
24
|
+
function presentsAppSecret(req) {
|
|
25
|
+
var given = req && req.headers ? req.headers['x-internal-data-secret'] : '';
|
|
26
|
+
var expected = process.env.NEXTAUTH_SECRET;
|
|
27
|
+
if (typeof given !== 'string' || !given || !expected) return false;
|
|
28
|
+
var a = Buffer.from(given);
|
|
29
|
+
var b = Buffer.from(String(expected));
|
|
30
|
+
return a.length === b.length && require('crypto').timingSafeEqual(a, b);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
async function invoiceCaller(req) {
|
|
34
|
+
if (presentsAppSecret(req)) {
|
|
35
|
+
return { server: true, signedIn: false, admin: false, userId: null };
|
|
36
|
+
}
|
|
37
|
+
var token = null;
|
|
38
|
+
try {
|
|
39
|
+
token = await __tqSessionToken(req);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
console.warn('[invoice] Could not read the session — ' + (err && err.message));
|
|
42
|
+
token = null;
|
|
43
|
+
}
|
|
44
|
+
if (!token) {
|
|
45
|
+
return { server: false, signedIn: false, admin: false, userId: null };
|
|
46
|
+
}
|
|
47
|
+
var role = roleOf(token);
|
|
48
|
+
var userId = token.id != null ? token.id : token.sub;
|
|
49
|
+
return {
|
|
50
|
+
server: false,
|
|
51
|
+
signedIn: true,
|
|
52
|
+
admin: !!role && INVOICE_ADMIN_ROLES.indexOf(role) !== -1,
|
|
53
|
+
userId: userId != null ? String(userId) : null,
|
|
54
|
+
};
|
|
55
|
+
}`;
|
|
2
56
|
export const generateInvoiceGenerateRouteCode = (settings) => {
|
|
3
|
-
var _a
|
|
57
|
+
var _a;
|
|
4
58
|
const prefix = settings.invoicePrefix || 'INV-';
|
|
5
|
-
const defaultTaxRate = settings.defaultTaxRate || 0;
|
|
6
|
-
const showDiscount = settings.showDiscount === true;
|
|
7
|
-
const taxIncludedInPrice = settings.taxIncludedInPrice === true;
|
|
8
59
|
const autoGenerate = settings.autoGenerateOnPayment !== false;
|
|
9
60
|
const emailEnabled = ((_a = settings.emailDelivery) === null || _a === void 0 ? void 0 : _a.enabled) === true;
|
|
10
|
-
const templateDocumentJson = ((_b = settings.template) === null || _b === void 0 ? void 0 : _b.document)
|
|
11
|
-
? JSON.stringify(settings.template.document)
|
|
12
|
-
: 'null';
|
|
13
61
|
return `/**
|
|
14
62
|
* POST /api/invoices/generate
|
|
15
63
|
* Generates an invoice PDF, stores it in the database, optionally uploads it
|
|
16
64
|
* to the runtime storage worker (when configured), and optionally sends it
|
|
17
65
|
* via email.
|
|
66
|
+
*
|
|
67
|
+
* Only the store itself issues invoices: its server code (the invoice node,
|
|
68
|
+
* the payment webhooks — they present the app secret) or a signed-in admin.
|
|
69
|
+
* An open route let anyone print invoices on the merchant's letterhead, burn
|
|
70
|
+
* invoice numbers, claim an order's invoice for good, and read another
|
|
71
|
+
* buyer's personal data back from a hydrated order.
|
|
18
72
|
*/
|
|
19
73
|
|
|
20
74
|
var dataAccess = require('../../../utils/invoices/data-access');
|
|
21
75
|
var pdfGenerator = require('../../../utils/invoices/pdf-generator');
|
|
76
|
+
var invoiceAssembly = require('../../../utils/invoices/invoice-assembly');
|
|
22
77
|
${emailEnabled
|
|
23
78
|
? `var emailSender = require('../../../utils/invoices/email-sender');
|
|
24
79
|
var sentEmailLog = require('../../../utils/email/sent-email-log');
|
|
@@ -26,107 +81,38 @@ var emailLocale = require('../../../utils/email/email-locale');`
|
|
|
26
81
|
: ''}
|
|
27
82
|
|
|
28
83
|
var INVOICE_PREFIX = ${JSON.stringify(prefix)};
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
var
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
${REGIONAL_INVOICE_TAX_CODE}
|
|
35
|
-
|
|
36
|
-
// Runtime storage configuration. When all three are set, the generated PDF
|
|
37
|
-
// is also POSTed to the storage worker so consumers (e.g. the payment
|
|
38
|
-
// webhook) can store a persistent URL on the order record. Missing/invalid
|
|
39
|
-
// config silently skips the upload — the in-DB PDF (served via
|
|
40
|
-
// /api/invoices/[id]/pdf) is always available as a fallback.
|
|
41
|
-
// Uploads the rendered invoice PDF through THIS project's own
|
|
42
|
-
// \`/api/runtime-storage/upload\` route — the exact same path that the
|
|
43
|
-
// admin-panel asset uploader uses (client-side \`file-storage-upload\`
|
|
44
|
-
// workflow node → the same proxy). Centralising on that one route means:
|
|
45
|
-
//
|
|
46
|
-
// 1. The storage service URL + api key + project id live in one place
|
|
47
|
-
// (the proxy), so invoice and admin uploads can never drift.
|
|
48
|
-
// 2. When runtime storage is not configured, the proxy returns
|
|
49
|
-
// HTTP 500 with \`{ error: 'Runtime storage is not configured' }\`.
|
|
50
|
-
// We surface that as the upload failure reason so the
|
|
51
|
-
// \`invoice_pdf_url\` column stays empty instead of silently
|
|
52
|
-
// holding a stale/fake URL.
|
|
53
|
-
//
|
|
54
|
-
// \`baseUrl\` is the live request origin (http://host:port) stamped at
|
|
55
|
-
// the top of \`handler\` from \`req.headers.host\`. The self-fetch pattern
|
|
56
|
-
// is necessary because this endpoint runs server-side, where Node's
|
|
57
|
-
// undici fetch rejects relative URLs.
|
|
58
|
-
async function uploadInvoicePdfToRuntimeStorage(pdfBuffer, fileName, baseUrl) {
|
|
59
|
-
if (!baseUrl) {
|
|
60
|
-
console.error('[invoice] Runtime storage: cannot compute proxy URL (baseUrl missing). Skipping upload.');
|
|
61
|
-
return { storageUrl: '', error: 'baseUrl missing' };
|
|
62
|
-
}
|
|
63
|
-
if (typeof Blob === 'undefined' || typeof FormData === 'undefined' || typeof fetch === 'undefined') {
|
|
64
|
-
console.error('[invoice] Runtime storage: Node runtime missing Blob/FormData/fetch (requires Node >= 18). Skipping upload.');
|
|
65
|
-
return { storageUrl: '', error: 'node runtime too old' };
|
|
66
|
-
}
|
|
67
|
-
try {
|
|
68
|
-
var proxyUrl = String(baseUrl).replace(/\\/+$/, '') + '/api/runtime-storage/upload';
|
|
69
|
-
console.info('[invoice] Runtime storage: POST ' + proxyUrl + ' (' + pdfBuffer.length + ' bytes, fileName=' + fileName + ', folder=invoices)');
|
|
70
|
-
var blob = new Blob([pdfBuffer], { type: 'application/pdf' });
|
|
71
|
-
var form = new FormData();
|
|
72
|
-
form.append('file', blob, fileName);
|
|
73
|
-
form.append('folder', 'invoices');
|
|
74
|
-
var res = await fetch(proxyUrl, { method: 'POST', body: form });
|
|
75
|
-
var data = {};
|
|
76
|
-
try { data = await res.json(); } catch (_parseErr) { data = {}; }
|
|
77
|
-
if (!res.ok) {
|
|
78
|
-
var reason = (data && (data.error || data.message)) || ('HTTP ' + res.status);
|
|
79
|
-
console.error('[invoice] Runtime storage: upload FAILED via proxy — ' + reason +
|
|
80
|
-
' (this is expected in dev when RUNTIME_STORAGE_URL / RUNTIME_STORAGE_API_KEY / RUNTIME_STORAGE_PROJECT_ID are unset in .env)');
|
|
81
|
-
return { storageUrl: '', error: reason };
|
|
82
|
-
}
|
|
83
|
-
var files = Array.isArray(data.files) ? data.files : [];
|
|
84
|
-
var first = files.length > 0 ? files[0] : null;
|
|
85
|
-
var resolvedUrl = first && first.url ? String(first.url) : (data.url ? String(data.url) : '');
|
|
86
|
-
var resolvedId = first && first.id ? String(first.id) : (data.id ? String(data.id) : '');
|
|
87
|
-
if (resolvedUrl) {
|
|
88
|
-
console.info('[invoice] Runtime storage: upload OK — fileId=' + (resolvedId || '(missing)') + ', storageUrl=' + resolvedUrl);
|
|
89
|
-
} else {
|
|
90
|
-
console.error('[invoice] Runtime storage: proxy returned 2xx but no url in payload — ' + JSON.stringify(data).slice(0, 500));
|
|
91
|
-
}
|
|
92
|
-
return { storageUrl: resolvedUrl, fileId: resolvedId };
|
|
93
|
-
} catch (err) {
|
|
94
|
-
console.error('[invoice] Runtime storage: upload threw — ' + (err && err.message));
|
|
95
|
-
return { storageUrl: '', error: (err && err.message) || 'upload threw' };
|
|
96
|
-
}
|
|
97
|
-
}
|
|
84
|
+
// How long a reserved invoice may wait for its PDF before another request for
|
|
85
|
+
// the same order finishes it: longer than any one request lives.
|
|
86
|
+
var UNFINISHED_INVOICE_STALE_SECONDS = 900;
|
|
87
|
+
|
|
88
|
+
${INVOICE_CALLER_CODE}
|
|
98
89
|
|
|
99
90
|
// ---------------------------------------------------------------------------
|
|
100
91
|
// Waiting for the order's line items to be fully written.
|
|
101
92
|
//
|
|
102
|
-
//
|
|
103
|
-
//
|
|
104
|
-
//
|
|
105
|
-
//
|
|
106
|
-
// the
|
|
107
|
-
//
|
|
108
|
-
// real 3-line order was invoiced with a single line and a total 225.45
|
|
109
|
-
// short of what the buyer was charged, because the other two rows were
|
|
110
|
-
// still in flight when the hydration query ran.
|
|
93
|
+
// The checkout workflow writes the \`teleport_orders\` row first and then
|
|
94
|
+
// inserts \`teleport_order_items\` one HTTP round-trip at a time, so a caller
|
|
95
|
+
// that reaches this endpoint early can hydrate a HALF-WRITTEN order: a real
|
|
96
|
+
// 3-line order was once invoiced with a single line and a total 225.45 short
|
|
97
|
+
// of what the buyer was charged, because the other two rows were still in
|
|
98
|
+
// flight when the hydration query ran.
|
|
111
99
|
//
|
|
112
|
-
// So don't race it — wait for the order to settle, then hydrate.
|
|
100
|
+
// So don't race it — wait for the order to settle, then hydrate. Two exit
|
|
113
101
|
// conditions, cheapest first:
|
|
114
102
|
//
|
|
115
|
-
// 1. \`
|
|
116
|
-
//
|
|
117
|
-
//
|
|
118
|
-
//
|
|
119
|
-
//
|
|
120
|
-
//
|
|
121
|
-
// so a non-empty order number proves every line has been written.
|
|
122
|
-
// 3. The row count is identical across \`SETTLE_STABLE_READS\` consecutive
|
|
103
|
+
// 1. \`teleport_orders.order_number\` is populated. Checkout backfills the
|
|
104
|
+
// order number only AFTER the item loop has run to completion (the
|
|
105
|
+
// settled branch does it in "Mark Order As Settled", the online-payment
|
|
106
|
+
// branch in "Set Order Number Before Payment Redirect"), so a non-empty
|
|
107
|
+
// order number proves every line has been written.
|
|
108
|
+
// 2. The row count is identical across \`SETTLE_STABLE_READS\` consecutive
|
|
123
109
|
// reads — the fallback for orders written by a flow that never sets an
|
|
124
110
|
// order number.
|
|
125
111
|
//
|
|
126
|
-
// An order that is already complete — every webhook-driven call,
|
|
127
|
-
// hand-built admin call —
|
|
128
|
-
// only request that ever pays for a
|
|
129
|
-
// have shipped a wrong invoice.
|
|
112
|
+
// An order that is already complete — every webhook-driven call, the
|
|
113
|
+
// checkout's own settled-branch call, and any hand-built admin call —
|
|
114
|
+
// satisfies (1) on the FIRST read, so the only request that ever pays for a
|
|
115
|
+
// poll is the one that would otherwise have shipped a wrong invoice.
|
|
130
116
|
var SETTLE_TIMEOUT_MS = 6000;
|
|
131
117
|
var SETTLE_POLL_MS = 400;
|
|
132
118
|
var SETTLE_STABLE_READS = 3;
|
|
@@ -135,7 +121,7 @@ function sleepMs(ms) {
|
|
|
135
121
|
return new Promise(function (resolve) { setTimeout(resolve, ms); });
|
|
136
122
|
}
|
|
137
123
|
|
|
138
|
-
async function hydrateOrderWhenSettled(orderId
|
|
124
|
+
async function hydrateOrderWhenSettled(orderId) {
|
|
139
125
|
var deadline = Date.now() + SETTLE_TIMEOUT_MS;
|
|
140
126
|
var lastCount = -1;
|
|
141
127
|
var repeats = 0;
|
|
@@ -153,13 +139,6 @@ async function hydrateOrderWhenSettled(orderId, expectedItemCount) {
|
|
|
153
139
|
var rows = Array.isArray(hydrated.items) ? hydrated.items : [];
|
|
154
140
|
var count = rows.length;
|
|
155
141
|
|
|
156
|
-
if (expectedItemCount > 0 && count >= expectedItemCount) {
|
|
157
|
-
if (attempts > 1) {
|
|
158
|
-
console.info('[invoice] Order ' + orderId + ' settled at ' + count + ' line(s) after ' + attempts + ' read(s) (expected ' + expectedItemCount + ')');
|
|
159
|
-
}
|
|
160
|
-
return hydrated;
|
|
161
|
-
}
|
|
162
|
-
|
|
163
142
|
var orderNumber = hydrated.order.order_number;
|
|
164
143
|
if (count > 0 && orderNumber != null && String(orderNumber).length > 0) {
|
|
165
144
|
if (attempts > 1) {
|
|
@@ -181,8 +160,7 @@ async function hydrateOrderWhenSettled(orderId, expectedItemCount) {
|
|
|
181
160
|
|
|
182
161
|
if (Date.now() >= deadline) {
|
|
183
162
|
console.warn('[invoice] Order ' + orderId + ' did not settle within ' + SETTLE_TIMEOUT_MS +
|
|
184
|
-
'ms — invoicing the ' + count + ' line(s) visible now'
|
|
185
|
-
(expectedItemCount > 0 ? ' (expected ' + expectedItemCount + ')' : ''));
|
|
163
|
+
'ms — invoicing the ' + count + ' line(s) visible now');
|
|
186
164
|
return hydrated;
|
|
187
165
|
}
|
|
188
166
|
|
|
@@ -190,33 +168,24 @@ async function hydrateOrderWhenSettled(orderId, expectedItemCount) {
|
|
|
190
168
|
}
|
|
191
169
|
}
|
|
192
170
|
|
|
193
|
-
var CURRENCY_SYMBOLS = {
|
|
194
|
-
'USD': '$', 'EUR': '\\u20AC', 'GBP': '\\u00A3', 'JPY': '\\u00A5',
|
|
195
|
-
'CAD': 'C$', 'AUD': 'A$', 'CHF': 'CHF ', 'CNY': '\\u00A5',
|
|
196
|
-
'INR': '\\u20B9', 'BRL': 'R$', 'KRW': '\\u20A9', 'MXN': 'MX$',
|
|
197
|
-
'SEK': 'kr', 'NOK': 'kr', 'DKK': 'kr', 'PLN': 'z\\u0142',
|
|
198
|
-
'CZK': 'K\\u010D', 'HUF': 'Ft', 'RON': 'lei', 'BGN': 'лв',
|
|
199
|
-
'HRK': 'kn', 'TRY': '\\u20BA', 'ZAR': 'R', 'SGD': 'S$',
|
|
200
|
-
'HKD': 'HK$', 'NZD': 'NZ$', 'THB': '\\u0E3F', 'MYR': 'RM',
|
|
201
|
-
'PHP': '\\u20B1', 'IDR': 'Rp', 'TWD': 'NT$', 'AED': 'AED',
|
|
202
|
-
'SAR': 'SAR', 'ILS': '\\u20AA', 'EGP': 'E\\u00A3', 'NGN': '\\u20A6',
|
|
203
|
-
'KES': 'KSh', 'GHS': 'GH\\u20B5', 'COP': 'COL$', 'ARS': 'AR$',
|
|
204
|
-
'CLP': 'CLP$', 'PEN': 'S/.', 'VND': '\\u20AB', 'UAH': '\\u20B4',
|
|
205
|
-
};
|
|
206
|
-
|
|
207
171
|
module.exports = async function handler(req, res) {
|
|
208
172
|
if (req.method !== 'POST') {
|
|
209
173
|
res.status(405).json({ error: 'Method not allowed' });
|
|
210
174
|
return;
|
|
211
175
|
}
|
|
212
176
|
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
177
|
+
var caller = await invoiceCaller(req);
|
|
178
|
+
if (!caller.server && !caller.admin) {
|
|
179
|
+
res.status(caller.signedIn ? 403 : 401).json({
|
|
180
|
+
success: false,
|
|
181
|
+
error: caller.signedIn ? 'Only the store can issue invoices.' : 'Unauthenticated',
|
|
182
|
+
});
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
// The live request origin, so the runtime-storage upload can self-fetch the
|
|
187
|
+
// same \`/api/runtime-storage/upload\` route the admin-panel uploader hits.
|
|
188
|
+
var __baseUrl = invoiceAssembly.requestBaseUrl(req);
|
|
220
189
|
|
|
221
190
|
try {
|
|
222
191
|
var body = typeof req.body === 'string' ? JSON.parse(req.body) : (req.body || {});
|
|
@@ -228,21 +197,11 @@ module.exports = async function handler(req, res) {
|
|
|
228
197
|
|
|
229
198
|
var callerSuppliedItems = Array.isArray(body.items) && body.items.length > 0;
|
|
230
199
|
|
|
231
|
-
// How many line items the caller believes this order has. Used only to
|
|
232
|
-
// stop \`hydrateOrderWhenSettled\` polling the moment the order is whole —
|
|
233
|
-
// never to reject or pad the invoice, so a wrong count can at worst make
|
|
234
|
-
// us wait a little longer and fall through to the other exit conditions.
|
|
235
|
-
var expectedItemCount = Number(body.expectedItemCount);
|
|
236
|
-
if (!isFinite(expectedItemCount) || expectedItemCount < 0) {
|
|
237
|
-
expectedItemCount = 0;
|
|
238
|
-
}
|
|
239
|
-
|
|
240
200
|
console.info('[invoice] === /api/invoices/generate === baseUrl=' + __baseUrl);
|
|
241
201
|
console.info('[invoice] Request received:', {
|
|
242
202
|
orderId: body.orderId || null,
|
|
243
203
|
hasBodyItems: callerSuppliedItems,
|
|
244
204
|
bodyItemCount: Array.isArray(body.items) ? body.items.length : 0,
|
|
245
|
-
expectedItemCount: expectedItemCount,
|
|
246
205
|
hasCustomerEmail: !!body.customerEmail,
|
|
247
206
|
requestedCurrency: body.currency || null,
|
|
248
207
|
});
|
|
@@ -269,7 +228,7 @@ module.exports = async function handler(req, res) {
|
|
|
269
228
|
try {
|
|
270
229
|
var hydrated = callerSuppliedItems
|
|
271
230
|
? await dataAccess.getOrderWithItems(body.orderId)
|
|
272
|
-
: await hydrateOrderWhenSettled(body.orderId
|
|
231
|
+
: await hydrateOrderWhenSettled(body.orderId);
|
|
273
232
|
if (hydrated && hydrated.order) {
|
|
274
233
|
hydratedOrder = hydrated.order;
|
|
275
234
|
hydratedItems = Array.isArray(hydrated.items) ? hydrated.items : [];
|
|
@@ -284,274 +243,73 @@ module.exports = async function handler(req, res) {
|
|
|
284
243
|
console.info('[invoice] No orderId in request — skipping DB hydration, using body.* fields verbatim');
|
|
285
244
|
}
|
|
286
245
|
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
productId: row.product_id || row.productId || null,
|
|
292
|
-
// Paired with \`productId\` to find the rate a line was charged at
|
|
293
|
-
// on an order priced by region (see resolveRegionalInvoiceTax).
|
|
294
|
-
variantId: row.variant_id || row.variantId || null,
|
|
295
|
-
name: row.product_name || row.name || 'Item',
|
|
296
|
-
variantLabel: row.variant_label || row.variantLabel || null,
|
|
297
|
-
variantSwatches: row.variant_swatches || row.variantSwatches || null,
|
|
298
|
-
quantity: Number(row.quantity) || 1,
|
|
299
|
-
unitPrice: Number(row.unit_price || row.unitPrice || row.price) || 0,
|
|
300
|
-
totalPrice: Number(row.total_price || row.totalPrice) || 0,
|
|
301
|
-
currency: row.currency || null,
|
|
302
|
-
};
|
|
303
|
-
});
|
|
304
|
-
if (items.length === 0) {
|
|
246
|
+
// Lines, prices, discounts, tax, delivery and the gift-card tender — the
|
|
247
|
+
// same assembly the admin panel's regenerate route rebuilds an invoice with.
|
|
248
|
+
var invoiceData = invoiceAssembly.assembleInvoiceData(body, hydratedOrder, hydratedItems);
|
|
249
|
+
if (!invoiceData) {
|
|
305
250
|
res.status(400).json({ error: 'At least one item is required' });
|
|
306
251
|
return;
|
|
307
252
|
}
|
|
308
|
-
|
|
309
|
-
var currency =
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
var
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
//
|
|
332
|
-
// A discount STORED ON THE ORDER is money the buyer was not charged, so it
|
|
333
|
-
// is subtracted whatever \`SHOW_DISCOUNT\` says — that flag governs whether
|
|
334
|
-
// the template renders a discount ROW, and honouring it here would print a
|
|
335
|
-
// total larger than the card was debited. \`SHOW_DISCOUNT\` still gates a
|
|
336
|
-
// BODY-supplied amount, which is the manual/ad-hoc path a merchant opts
|
|
337
|
-
// into.
|
|
338
|
-
//
|
|
339
|
-
// The payment webhook calls this route with just an \`orderId\`, so the
|
|
340
|
-
// order row — not the body — is the usual source.
|
|
341
|
-
var discountAmount = 0;
|
|
342
|
-
if (SHOW_DISCOUNT && body.discountAmount != null && body.discountAmount !== '') {
|
|
343
|
-
discountAmount = Number(body.discountAmount) || 0;
|
|
344
|
-
} else if (orderShippingSource.discount_amount != null) {
|
|
345
|
-
discountAmount = Number(orderShippingSource.discount_amount) || 0;
|
|
346
|
-
}
|
|
347
|
-
if (!(discountAmount > 0)) { discountAmount = 0; }
|
|
348
|
-
|
|
349
|
-
var taxRate = body.taxRate != null ? Number(body.taxRate) : DEFAULT_TAX_RATE;
|
|
350
|
-
var subtotal;
|
|
351
|
-
var taxAmount = 0;
|
|
352
|
-
var taxableAmount;
|
|
353
|
-
if (taxRate > 0 && TAX_INCLUDED_IN_PRICE) {
|
|
354
|
-
// Prices already include VAT — extract net subtotal and tax out of the gross sum.
|
|
355
|
-
taxableAmount = grossLineSum - discountAmount;
|
|
356
|
-
var netAmount = taxableAmount / (1 + taxRate / 100);
|
|
357
|
-
taxAmount = taxableAmount - netAmount;
|
|
358
|
-
subtotal = netAmount;
|
|
359
|
-
} else {
|
|
360
|
-
subtotal = grossLineSum;
|
|
361
|
-
taxableAmount = subtotal - discountAmount;
|
|
362
|
-
if (taxRate > 0) {
|
|
363
|
-
taxAmount = taxableAmount * (taxRate / 100);
|
|
253
|
+
var items = invoiceData.items;
|
|
254
|
+
var currency = invoiceData.currency;
|
|
255
|
+
|
|
256
|
+
// The number and the row are taken before the PDF is rendered, under one
|
|
257
|
+
// lock (see reserveInvoice): an order gets one invoice however many times
|
|
258
|
+
// its payment is reported, and no two invoices share a number.
|
|
259
|
+
var reservation = await dataAccess.reserveInvoice(invoiceData, items, INVOICE_PREFIX);
|
|
260
|
+
var held = reservation.invoice;
|
|
261
|
+
if (!reservation.created) {
|
|
262
|
+
if (Number(held.pdf_size_bytes) > 0) {
|
|
263
|
+
console.info('[invoice] Order ' + body.orderId + ' already has invoice ' + held.invoice_number + ' — returning it');
|
|
264
|
+
var heldPdfUrl = held.pdf_url || ('/api/invoices/' + held.id + '/pdf');
|
|
265
|
+
res.status(200).json({
|
|
266
|
+
success: true,
|
|
267
|
+
alreadyIssued: true,
|
|
268
|
+
invoiceId: held.id,
|
|
269
|
+
invoiceNumber: held.invoice_number,
|
|
270
|
+
storageUrl: heldPdfUrl.indexOf('/api/invoices/') === 0 ? '' : heldPdfUrl,
|
|
271
|
+
pdfUrl: heldPdfUrl,
|
|
272
|
+
total: Number(held.total) || 0,
|
|
273
|
+
currency: held.currency || currency,
|
|
274
|
+
});
|
|
275
|
+
return;
|
|
364
276
|
}
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
// the merchant's CURRENT delivery settings — the order is a historical
|
|
373
|
-
// record and its settings may have changed since.
|
|
374
|
-
//
|
|
375
|
-
// It is added to the total but NOT into \`subtotal\` / \`taxAmount\`: those two
|
|
376
|
-
// describe the GOODS, which is what \`teleport_invoice_items\` holds and what
|
|
377
|
-
// the VAT breakdown is computed from. The storefront charges the configured
|
|
378
|
-
// delivery price verbatim (\`computeShippingMeta\` never taxes it), so the
|
|
379
|
-
// invoice must not tax it either — otherwise the invoice total stops
|
|
380
|
-
// matching \`teleport_orders.total_amount\`, i.e. the amount actually taken.
|
|
381
|
-
// 0 for pickup orders, free-delivery orders, and orders placed before the
|
|
382
|
-
// column existed.
|
|
383
|
-
var shippingAmount = Number(
|
|
384
|
-
body.shippingAmount != null ? body.shippingAmount : (orderShippingSource.shipping_amount || 0)
|
|
385
|
-
);
|
|
386
|
-
if (!isFinite(shippingAmount) || shippingAmount < 0) {
|
|
387
|
-
shippingAmount = 0;
|
|
388
|
-
}
|
|
389
|
-
var total = goodsTotal + shippingAmount;
|
|
390
|
-
|
|
391
|
-
// An order priced by region records the rate each line was charged at, so
|
|
392
|
-
// its invoice is computed from that record instead of the store default.
|
|
393
|
-
// A caller that states its own \`taxRate\` keeps the single-rate path.
|
|
394
|
-
var taxIncludedInPrice = TAX_INCLUDED_IN_PRICE;
|
|
395
|
-
var regionalTaxBreakdown = body.taxRate == null
|
|
396
|
-
? parseOrderTaxBreakdown(orderShippingSource.tax_breakdown)
|
|
397
|
-
: null;
|
|
398
|
-
if (regionalTaxBreakdown) {
|
|
399
|
-
var regionalTax = resolveRegionalInvoiceTax(regionalTaxBreakdown, items, discountAmount, shippingAmount);
|
|
400
|
-
taxRate = regionalTax.taxRate;
|
|
401
|
-
taxIncludedInPrice = regionalTax.taxIncluded;
|
|
402
|
-
subtotal = regionalTax.subtotal;
|
|
403
|
-
taxAmount = regionalTax.taxAmount;
|
|
404
|
-
shippingAmount = regionalTax.shippingNet;
|
|
405
|
-
total = regionalTax.total;
|
|
406
|
-
for (var ti = 0; ti < items.length; ti++) {
|
|
407
|
-
items[ti].taxRate = regionalTax.itemTax[ti].rate;
|
|
408
|
-
items[ti].taxIncluded = regionalTax.itemTax[ti].included;
|
|
409
|
-
items[ti].taxAmount = regionalTax.itemTax[ti].amount;
|
|
277
|
+
// Reserved, never finished: another request is rendering it now, or the
|
|
278
|
+
// one that reserved it died — then the first request to find it stale
|
|
279
|
+
// finishes it under the same number.
|
|
280
|
+
if (!(await dataAccess.claimStaleInvoice(held.id, UNFINISHED_INVOICE_STALE_SECONDS))) {
|
|
281
|
+
console.info('[invoice] Order ' + body.orderId + ' invoice ' + held.invoice_number + ' is being issued by another request');
|
|
282
|
+
res.status(409).json({ success: false, inProgress: true, error: "This order's invoice is being issued by another request." });
|
|
283
|
+
return;
|
|
410
284
|
}
|
|
285
|
+
console.warn('[invoice] Finishing invoice ' + held.invoice_number + ' for order ' + body.orderId + ' — the request that reserved it never did');
|
|
286
|
+
invoiceData.id = held.id;
|
|
287
|
+
invoiceData.invoiceNumber = held.invoice_number;
|
|
411
288
|
}
|
|
412
|
-
|
|
413
|
-
// Cross-check against the amount the order was actually placed for. The
|
|
414
|
-
// invoice is built from line items, the order carries the charged total,
|
|
415
|
-
// and the two must agree — when they don't, the invoice is being written
|
|
416
|
-
// from an incomplete set of lines (exactly what a lost race against
|
|
417
|
-
// checkout's item loop looks like). Log-only: a mismatch must never stop
|
|
418
|
-
// the merchant getting an invoice, but it has to be visible in the
|
|
419
|
-
// function logs instead of silently shipping a short bill.
|
|
420
|
-
var orderTotalAmount = Number(orderShippingSource.total_amount);
|
|
421
|
-
if (isFinite(orderTotalAmount) && orderTotalAmount > 0 && Math.abs(orderTotalAmount - total) > 0.02) {
|
|
422
|
-
console.warn('[invoice] Total mismatch for order ' + (body.orderId || '(none)') +
|
|
423
|
-
' — invoice total ' + (Math.round(total * 100) / 100) +
|
|
424
|
-
' vs teleport_orders.total_amount ' + orderTotalAmount +
|
|
425
|
-
' across ' + items.length + ' line item(s). The invoice may be missing lines.');
|
|
426
|
-
}
|
|
427
|
-
|
|
428
|
-
var nextNumber = await dataAccess.getNextInvoiceNumber(INVOICE_PREFIX);
|
|
429
|
-
var invoiceNumber = INVOICE_PREFIX + String(nextNumber).padStart(4, '0');
|
|
430
|
-
|
|
431
|
-
var issueDate = body.issueDate || new Date().toISOString().split('T')[0];
|
|
432
|
-
var parsedIssueDate = new Date(issueDate);
|
|
433
|
-
if (isNaN(parsedIssueDate.getTime())) {
|
|
434
|
-
issueDate = new Date().toISOString().split('T')[0];
|
|
435
|
-
parsedIssueDate = new Date(issueDate);
|
|
436
|
-
}
|
|
437
|
-
// \`dueDate\` defaults to issueDate + 30 days (industry-standard
|
|
438
|
-
// Net 30 terms) when the caller doesn't pass one. Without this
|
|
439
|
-
// default, every invoice generated from the order-notification /
|
|
440
|
-
// payment-webhook paths shipped with an empty \`{{dueDate}}\` slot
|
|
441
|
-
// in the buyer email + PDF — the merchant template literally
|
|
442
|
-
// rendered "Due Date: " with no date — because none of those
|
|
443
|
-
// callers know what payment terms the merchant uses.
|
|
444
|
-
//
|
|
445
|
-
// We compute it from \`parsedIssueDate\` (already validated above)
|
|
446
|
-
// so a bad caller-provided \`issueDate\` doesn't propagate into a
|
|
447
|
-
// bad \`dueDate\`. ISO yyyy-mm-dd is the same format the issueDate
|
|
448
|
-
// path produces, so downstream date formatters get a single shape.
|
|
449
|
-
var DEFAULT_DUE_DATE_OFFSET_DAYS = 30;
|
|
450
|
-
var dueDate = body.dueDate || '';
|
|
451
|
-
if (dueDate) {
|
|
452
|
-
var parsedDue = new Date(dueDate);
|
|
453
|
-
if (isNaN(parsedDue.getTime())) dueDate = '';
|
|
454
|
-
}
|
|
455
|
-
if (!dueDate) {
|
|
456
|
-
var __defaultDue = new Date(parsedIssueDate.getTime());
|
|
457
|
-
__defaultDue.setUTCDate(__defaultDue.getUTCDate() + DEFAULT_DUE_DATE_OFFSET_DAYS);
|
|
458
|
-
dueDate = __defaultDue.toISOString().split('T')[0];
|
|
459
|
-
}
|
|
460
|
-
|
|
461
|
-
// Order-derived fallbacks. When the caller didn't pass a customer
|
|
462
|
-
// field but the order has one, use it. Kept permissive on field
|
|
463
|
-
// names (billing_* wins, falls back to shipping_*) because a buyer
|
|
464
|
-
// who checked "bill to a different address" has both on the order.
|
|
465
|
-
var orderRow = orderShippingSource;
|
|
466
|
-
var fallbackCustomerName =
|
|
467
|
-
orderRow.billing_name || orderRow.shipping_name || orderRow.customer_name || '';
|
|
468
|
-
var fallbackCustomerEmail = orderRow.billing_email || orderRow.customer_email || '';
|
|
469
|
-
var fallbackCustomerAddress = orderRow.billing_address || orderRow.shipping_address || '';
|
|
470
|
-
var fallbackCustomerCity = orderRow.shipping_city || '';
|
|
471
|
-
var fallbackCustomerState = orderRow.shipping_state || '';
|
|
472
|
-
var fallbackCustomerZip = orderRow.shipping_zip || '';
|
|
473
|
-
var fallbackCustomerCountry = orderRow.shipping_country || '';
|
|
474
|
-
var fallbackPaymentMethod = orderRow.payment_method || '';
|
|
475
|
-
var fallbackPaymentProvider = orderRow.payment_provider || '';
|
|
476
|
-
var fallbackPaymentIntentId = orderRow.payment_intent_id || '';
|
|
477
|
-
var fallbackNotes = orderRow.notes || '';
|
|
289
|
+
var invoiceNumber = invoiceData.invoiceNumber;
|
|
478
290
|
${emailEnabled
|
|
479
291
|
? `
|
|
480
292
|
// The language the invoice email goes out in: the one stamped on the
|
|
481
293
|
// order at checkout (the buyer's storefront), else the one the caller
|
|
482
294
|
// named, else the language of the request itself. A cron or a webhook
|
|
483
295
|
// has neither of the last two and lands on the store's main language.
|
|
296
|
+
var orderRow = hydratedOrder || {};
|
|
484
297
|
var invoiceLocale = emailLocale.normalizeEmailLocale(orderRow.locale)
|
|
485
298
|
|| emailLocale.normalizeEmailLocale(body.locale)
|
|
486
299
|
|| emailLocale.resolveRequestLocale(req);
|
|
300
|
+
invoiceData.locale = invoiceLocale;
|
|
487
301
|
`
|
|
488
302
|
: ''}
|
|
489
|
-
var invoiceData = {
|
|
490
|
-
id: body.id || require('crypto').randomUUID(),
|
|
491
|
-
invoiceNumber: invoiceNumber,
|
|
492
|
-
status: body.status || 'issued',
|
|
493
|
-
issueDate: issueDate,
|
|
494
|
-
dueDate: dueDate,
|
|
495
|
-
paidAt: body.paidAt || null,
|
|
496
|
-
customerName: body.customerName || fallbackCustomerName || '',
|
|
497
|
-
customerEmail: body.customerEmail || fallbackCustomerEmail || '',${emailEnabled ? '\n locale: invoiceLocale,' : ''}
|
|
498
|
-
customerAddress: body.customerAddress || fallbackCustomerAddress || '',
|
|
499
|
-
customerCity: body.customerCity || fallbackCustomerCity || '',
|
|
500
|
-
customerState: body.customerState || fallbackCustomerState || '',
|
|
501
|
-
customerZip: body.customerZip || fallbackCustomerZip || '',
|
|
502
|
-
customerCountry: body.customerCountry || fallbackCustomerCountry || '',
|
|
503
|
-
customerVat: body.customerVat || '',
|
|
504
|
-
companyName: pdfGenerator.COMPANY_DETAILS.companyName || '',
|
|
505
|
-
companyAddress: pdfGenerator.COMPANY_DETAILS.companyAddress || '',
|
|
506
|
-
companyCity: pdfGenerator.COMPANY_DETAILS.companyCity || '',
|
|
507
|
-
companyState: pdfGenerator.COMPANY_DETAILS.companyState || '',
|
|
508
|
-
companyZip: pdfGenerator.COMPANY_DETAILS.companyZip || '',
|
|
509
|
-
companyCountry: pdfGenerator.COMPANY_DETAILS.companyCountry || '',
|
|
510
|
-
companyVat: pdfGenerator.COMPANY_DETAILS.companyVat || '',
|
|
511
|
-
companyRegNumber: pdfGenerator.COMPANY_DETAILS.companyRegNumber || '',
|
|
512
|
-
companyEmail: pdfGenerator.COMPANY_DETAILS.companyEmail || '',
|
|
513
|
-
companyPhone: pdfGenerator.COMPANY_DETAILS.companyPhone || '',
|
|
514
|
-
companyLogoUrl: body.companyLogoUrl || '',
|
|
515
|
-
companyWebsite: pdfGenerator.COMPANY_DETAILS.companyWebsite || '',
|
|
516
|
-
subtotal: Math.round(subtotal * 100) / 100,
|
|
517
|
-
taxRate: taxRate,
|
|
518
|
-
taxAmount: Math.round(taxAmount * 100) / 100,
|
|
519
|
-
// Surfacing the inclusion mode so the PDF builder can apply the SAME
|
|
520
|
-
// formulas the GUI uses (invoice-vat-formulas.ts) when it derives
|
|
521
|
-
// per-line unitPriceNet / lineVatAmount / lineTotalGross. Without
|
|
522
|
-
// this flag the builder can't tell whether the stored unitPrice is
|
|
523
|
-
// a net (added on top) or a gross (included in price) value, and
|
|
524
|
-
// the line-item table renders blank cells.
|
|
525
|
-
taxIncludedInPrice: taxIncludedInPrice,
|
|
526
|
-
discountAmount: Math.round(discountAmount * 100) / 100,
|
|
527
|
-
// Delivery fee, surfaced so the PDF/HTML renderer can print its own line
|
|
528
|
-
// and the merchant's template can bind \`invoice.shippingAmount\`.
|
|
529
|
-
shippingAmount: Math.round(shippingAmount * 100) / 100,
|
|
530
|
-
total: Math.round(total * 100) / 100,
|
|
531
|
-
currency: currency,
|
|
532
|
-
currencySymbol: currencySymbol,
|
|
533
|
-
paymentMethod: body.paymentMethod || fallbackPaymentMethod || '',
|
|
534
|
-
paymentProvider: body.paymentProvider || fallbackPaymentProvider || '',
|
|
535
|
-
paymentIntentId: body.paymentIntentId || fallbackPaymentIntentId || '',
|
|
536
|
-
orderId: body.orderId || '',
|
|
537
|
-
notes: body.notes || fallbackNotes || '',
|
|
538
|
-
items: items,
|
|
539
|
-
templateSnapshot: TEMPLATE_DOCUMENT ? JSON.stringify(TEMPLATE_DOCUMENT) : null,
|
|
540
|
-
};
|
|
541
303
|
|
|
542
304
|
var pdfBuffer = await pdfGenerator.generateInvoicePdf(invoiceData);
|
|
543
305
|
console.info('[invoice] PDF generated: ' + pdfBuffer.length + ' bytes for ' + invoiceData.invoiceNumber);
|
|
544
306
|
|
|
545
|
-
invoiceData.pdfData = pdfBuffer;
|
|
546
|
-
invoiceData.pdfSizeBytes = pdfBuffer.length;
|
|
547
307
|
invoiceData.pdfUrl = '/api/invoices/' + invoiceData.id + '/pdf';
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
await dataAccess.insertInvoiceItems(invoiceData.id, items);
|
|
551
|
-
console.info('[invoice] DB insert OK — teleport_invoices.id=' + invoiceData.id + ', number=' + invoiceData.invoiceNumber + ', pdf_size_bytes=' + pdfBuffer.length + ', items=' + items.length + ' (accessible at ' + invoiceData.pdfUrl + ')');
|
|
308
|
+
await dataAccess.storeInvoicePdf(invoiceData.id, pdfBuffer, invoiceData.pdfUrl);
|
|
309
|
+
console.info('[invoice] PDF stored — teleport_invoices.id=' + invoiceData.id + ', number=' + invoiceData.invoiceNumber + ', pdf_size_bytes=' + pdfBuffer.length + ', items=' + items.length + ' (accessible at ' + invoiceData.pdfUrl + ')');
|
|
552
310
|
|
|
553
311
|
var safeFileName = String(invoiceNumber || invoiceData.id).replace(/[^a-zA-Z0-9._-]/g, '_') + '.pdf';
|
|
554
|
-
var uploadResult = await uploadInvoicePdfToRuntimeStorage(pdfBuffer, safeFileName, __baseUrl);
|
|
312
|
+
var uploadResult = await invoiceAssembly.uploadInvoicePdfToRuntimeStorage(pdfBuffer, safeFileName, __baseUrl);
|
|
555
313
|
var storageUrl = (uploadResult && uploadResult.storageUrl) || '';
|
|
556
314
|
|
|
557
315
|
// Persist the runtime-storage URL onto \`teleport_invoices.pdf_url\` once
|
|
@@ -571,6 +329,7 @@ ${emailEnabled
|
|
|
571
329
|
} catch (updateErr) {
|
|
572
330
|
console.error('[invoice] DB update FAILED for pdf_url=' + storageUrl + ' (id=' + invoiceData.id + '): ' + (updateErr && updateErr.message));
|
|
573
331
|
}
|
|
332
|
+
await invoiceAssembly.recordStoredInvoicePdfKey(invoiceData.id, uploadResult.fileId);
|
|
574
333
|
} else {
|
|
575
334
|
console.info('[invoice] Skipping pdf_url update — storage upload did not yield a URL; keeping DB fallback ' + invoiceData.pdfUrl);
|
|
576
335
|
}
|
|
@@ -669,19 +428,282 @@ ${emailEnabled
|
|
|
669
428
|
${emailEnabled
|
|
670
429
|
? ` await sentEmailLog.settleSentEmailLog();
|
|
671
430
|
`
|
|
672
|
-
: ''}
|
|
431
|
+
: ''} // The error names the store's tables and data: server log only (above).
|
|
432
|
+
res.status(500).json({ success: false, error: 'Failed to generate invoice' });
|
|
673
433
|
}
|
|
674
434
|
};
|
|
675
435
|
`;
|
|
676
436
|
};
|
|
437
|
+
/** The roles allowed to rebuild an invoice (the admin panel is the only caller). */
|
|
438
|
+
const REGENERATE_INVOICE_ROLES = INVOICE_ADMIN_ROLES;
|
|
439
|
+
/**
|
|
440
|
+
* POST /api/invoices/[id]/regenerate — the admin panel's "Regenerate" action.
|
|
441
|
+
*
|
|
442
|
+
* Rebuilds ONE invoice from its order with the very assembly that issued it at
|
|
443
|
+
* payment (`utils/invoices/invoice-assembly.js`), IN PLACE: the same id, number,
|
|
444
|
+
* dates and status, so the order, the sent-email ledger and any refund recorded
|
|
445
|
+
* against it keep pointing at a valid invoice. What a merchant corrected on the
|
|
446
|
+
* invoice itself (customer details, notes, payment method) wins over the order;
|
|
447
|
+
* the lines and every figure are recomputed from the order. The old PDF is
|
|
448
|
+
* replaced — and its runtime-storage copy deleted — and the customer is never
|
|
449
|
+
* emailed.
|
|
450
|
+
*
|
|
451
|
+
* Unlike `/generate`, which the payment webhook calls server-to-server, this
|
|
452
|
+
* route is reached from the merchant's browser only, so it checks the session
|
|
453
|
+
* itself: signed in, with an admin role.
|
|
454
|
+
*/
|
|
455
|
+
export const generateInvoiceRegenerateRouteCode = () => {
|
|
456
|
+
return `/**
|
|
457
|
+
* POST /api/invoices/[id]/regenerate
|
|
458
|
+
* Rebuilds one invoice from its order, in place, for the admin panel. Same
|
|
459
|
+
* number, id and dates; a freshly rendered PDF replaces the old one; no email.
|
|
460
|
+
*/
|
|
461
|
+
|
|
462
|
+
var dataAccess = require('../../../../utils/invoices/data-access');
|
|
463
|
+
var pdfGenerator = require('../../../../utils/invoices/pdf-generator');
|
|
464
|
+
var invoiceAssembly = require('../../../../utils/invoices/invoice-assembly');
|
|
465
|
+
|
|
466
|
+
${generateCommonJsSessionTokenResolverCode()}
|
|
467
|
+
${ROLE_OF_TOKEN_CODE}
|
|
468
|
+
|
|
469
|
+
var REGENERATE_ALLOWED_ROLES = ${JSON.stringify(REGENERATE_INVOICE_ROLES)};
|
|
470
|
+
|
|
471
|
+
var MESSAGES = {
|
|
472
|
+
unauthenticated: 'Your session has ended. Sign in again to regenerate invoices.',
|
|
473
|
+
forbidden: 'Only an admin can regenerate invoices.',
|
|
474
|
+
missingId: 'Invoice id is required.',
|
|
475
|
+
notFound: 'This invoice no longer exists.',
|
|
476
|
+
notLinked: 'This invoice is not linked to an order, so there is nothing to rebuild it from.',
|
|
477
|
+
orderGone: 'The order this invoice was issued for no longer exists.',
|
|
478
|
+
noLines: 'The order has no products left to invoice.',
|
|
479
|
+
failed: 'The invoice could not be regenerated.',
|
|
480
|
+
orderNotUpdated: 'The invoice was rebuilt, but its order could not be updated, so the customer still sees the previous PDF. Regenerate it again.',
|
|
481
|
+
};
|
|
482
|
+
|
|
483
|
+
// 'YYYY-MM-DD' of a stored date, the shape the assembly and the PDF expect.
|
|
484
|
+
// pg hands a DATE/TIMESTAMP over as a Date built from the naive column value
|
|
485
|
+
// in LOCAL time, so its local calendar day is the stored one; a string is cut
|
|
486
|
+
// to its date part. Empty when unreadable — the assembly then falls back
|
|
487
|
+
// exactly as it does at payment.
|
|
488
|
+
function calendarDate(value) {
|
|
489
|
+
if (!value) return '';
|
|
490
|
+
if (value instanceof Date) {
|
|
491
|
+
if (isNaN(value.getTime())) return '';
|
|
492
|
+
return value.getFullYear() + '-' + String(value.getMonth() + 1).padStart(2, '0') + '-' + String(value.getDate()).padStart(2, '0');
|
|
493
|
+
}
|
|
494
|
+
var match = /^(\\d{4}-\\d{2}-\\d{2})/.exec(String(value));
|
|
495
|
+
return match ? match[1] : '';
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// What the invoice itself says, stated over the order: the identity of the
|
|
499
|
+
// document (id, dates, status) and what a merchant can correct with Edit —
|
|
500
|
+
// the customer details, the notes and the payment method. Everything left out
|
|
501
|
+
// (the lines, prices, discounts, tax, delivery, gift card, currency) is read
|
|
502
|
+
// from the order, exactly as at payment. An empty field falls back to the
|
|
503
|
+
// order too.
|
|
504
|
+
function regenerationBody(invoice) {
|
|
505
|
+
return {
|
|
506
|
+
orderId: String(invoice.order_id),
|
|
507
|
+
id: String(invoice.id),
|
|
508
|
+
status: invoice.status || 'issued',
|
|
509
|
+
issueDate: calendarDate(invoice.issue_date),
|
|
510
|
+
dueDate: calendarDate(invoice.due_date),
|
|
511
|
+
paidAt: invoice.paid_at || null,
|
|
512
|
+
customerName: invoice.customer_name || '',
|
|
513
|
+
customerEmail: invoice.customer_email || '',
|
|
514
|
+
customerAddress: invoice.customer_address || '',
|
|
515
|
+
customerCity: invoice.customer_city || '',
|
|
516
|
+
customerState: invoice.customer_state || '',
|
|
517
|
+
customerZip: invoice.customer_zip || '',
|
|
518
|
+
customerCountry: invoice.customer_country || '',
|
|
519
|
+
customerVat: invoice.customer_vat || '',
|
|
520
|
+
paymentMethod: invoice.payment_method || '',
|
|
521
|
+
paymentProvider: invoice.payment_provider || '',
|
|
522
|
+
paymentIntentId: invoice.payment_intent_id || '',
|
|
523
|
+
notes: invoice.notes || '',
|
|
524
|
+
};
|
|
525
|
+
}
|
|
526
|
+
|
|
527
|
+
async function sessionRole(req) {
|
|
528
|
+
try {
|
|
529
|
+
var token = await __tqSessionToken(req);
|
|
530
|
+
return token ? { signedIn: true, role: roleOf(token) } : { signedIn: false, role: null };
|
|
531
|
+
} catch (err) {
|
|
532
|
+
console.warn('[invoice] Regenerate: could not read the session — ' + (err && err.message));
|
|
533
|
+
return { signedIn: false, role: null };
|
|
534
|
+
}
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
// Postgres refuses an id that is not a UUID ("invalid_text_representation").
|
|
538
|
+
var MALFORMED_ID_ERROR_CODE = '22P02';
|
|
539
|
+
|
|
540
|
+
// A malformed id is a missing invoice; any other failure (an outage, a full
|
|
541
|
+
// pool) is a server error, never "this invoice no longer exists".
|
|
542
|
+
async function findInvoice(invoiceId) {
|
|
543
|
+
try {
|
|
544
|
+
return await dataAccess.getInvoiceById(invoiceId);
|
|
545
|
+
} catch (err) {
|
|
546
|
+
if (err && err.code === MALFORMED_ID_ERROR_CODE) return null;
|
|
547
|
+
throw err;
|
|
548
|
+
}
|
|
549
|
+
}
|
|
550
|
+
|
|
551
|
+
module.exports = async function handler(req, res) {
|
|
552
|
+
if (req.method !== 'POST') {
|
|
553
|
+
res.setHeader('Allow', 'POST');
|
|
554
|
+
res.status(405).json({ success: false, error: 'Method not allowed' });
|
|
555
|
+
return;
|
|
556
|
+
}
|
|
557
|
+
|
|
558
|
+
var session = await sessionRole(req);
|
|
559
|
+
if (!session.signedIn) {
|
|
560
|
+
res.status(401).json({ success: false, error: MESSAGES.unauthenticated });
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
if (!session.role || REGENERATE_ALLOWED_ROLES.indexOf(session.role) < 0) {
|
|
564
|
+
res.status(403).json({ success: false, error: MESSAGES.forbidden });
|
|
565
|
+
return;
|
|
566
|
+
}
|
|
567
|
+
|
|
568
|
+
var invoiceId = String((req.query && req.query.id) || '').trim();
|
|
569
|
+
if (!invoiceId) {
|
|
570
|
+
res.status(400).json({ success: false, error: MESSAGES.missingId });
|
|
571
|
+
return;
|
|
572
|
+
}
|
|
573
|
+
|
|
574
|
+
try {
|
|
575
|
+
var invoice = await findInvoice(invoiceId);
|
|
576
|
+
if (!invoice) {
|
|
577
|
+
res.status(404).json({ success: false, error: MESSAGES.notFound });
|
|
578
|
+
return;
|
|
579
|
+
}
|
|
580
|
+
if (!invoice.order_id) {
|
|
581
|
+
res.status(409).json({ success: false, error: MESSAGES.notLinked });
|
|
582
|
+
return;
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
var hydrated = await dataAccess.getOrderWithItems(String(invoice.order_id));
|
|
586
|
+
if (!hydrated || !hydrated.order) {
|
|
587
|
+
res.status(409).json({ success: false, error: MESSAGES.orderGone });
|
|
588
|
+
return;
|
|
589
|
+
}
|
|
590
|
+
|
|
591
|
+
var invoiceData = invoiceAssembly.assembleInvoiceData(
|
|
592
|
+
regenerationBody(invoice),
|
|
593
|
+
hydrated.order,
|
|
594
|
+
Array.isArray(hydrated.items) ? hydrated.items : []
|
|
595
|
+
);
|
|
596
|
+
if (!invoiceData) {
|
|
597
|
+
res.status(409).json({ success: false, error: MESSAGES.noLines });
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
600
|
+
invoiceData.invoiceNumber = String(invoice.invoice_number || '');
|
|
601
|
+
|
|
602
|
+
// Rendered BEFORE anything is written: a PDF service that is down leaves
|
|
603
|
+
// the invoice exactly as it was.
|
|
604
|
+
var pdfBuffer = await pdfGenerator.generateInvoicePdf(invoiceData);
|
|
605
|
+
invoiceData.pdfData = pdfBuffer;
|
|
606
|
+
invoiceData.pdfSizeBytes = pdfBuffer.length;
|
|
607
|
+
invoiceData.pdfUrl = '/api/invoices/' + invoiceData.id + '/pdf';
|
|
608
|
+
|
|
609
|
+
await dataAccess.replaceInvoice(invoiceData.id, invoiceData, invoiceData.items);
|
|
610
|
+
console.info('[invoice] Regenerated ' + invoiceData.invoiceNumber + ' (id=' + invoiceData.id + ', items=' + invoiceData.items.length + ', pdf_size_bytes=' + pdfBuffer.length + ')');
|
|
611
|
+
|
|
612
|
+
// The new PDF's public copy. The row already serves the new bytes through
|
|
613
|
+
// /api/invoices/<id>/pdf, so a failed upload costs nothing but the public URL.
|
|
614
|
+
var previousStorageKey = invoice.pdf_storage_key ? String(invoice.pdf_storage_key) : '';
|
|
615
|
+
var safeFileName = String(invoiceData.invoiceNumber || invoiceData.id).replace(/[^a-zA-Z0-9._-]/g, '_') + '.pdf';
|
|
616
|
+
var upload = await invoiceAssembly.uploadInvoicePdfToRuntimeStorage(pdfBuffer, safeFileName, invoiceAssembly.requestBaseUrl(req));
|
|
617
|
+
var storedUrl = upload && upload.storageUrl ? String(upload.storageUrl) : '';
|
|
618
|
+
var storageKey = storedUrl ? String(upload.fileId || '') : '';
|
|
619
|
+
var pdfUrl = storedUrl || invoiceData.pdfUrl;
|
|
620
|
+
|
|
621
|
+
// The order BEFORE the old copy goes: the customer's "View invoice" (their
|
|
622
|
+
// profile, the order page) opens the order's link, so until it names the
|
|
623
|
+
// new PDF the old copy must stay. On failure the new copy is dropped
|
|
624
|
+
// instead and nothing else changes, so regenerating again starts clean.
|
|
625
|
+
try {
|
|
626
|
+
await dataAccess.linkOrderToInvoice(invoiceData.orderId, invoiceData.id, invoiceData.invoiceNumber, pdfUrl);
|
|
627
|
+
} catch (linkErr) {
|
|
628
|
+
console.error('[invoice] Regenerate: could not update order ' + invoiceData.orderId + ' — ' + (linkErr && linkErr.message));
|
|
629
|
+
if (storageKey) {
|
|
630
|
+
await invoiceAssembly.deleteStoredInvoicePdf(storageKey);
|
|
631
|
+
}
|
|
632
|
+
res.status(500).json({ success: false, error: MESSAGES.orderNotUpdated });
|
|
633
|
+
return;
|
|
634
|
+
}
|
|
635
|
+
|
|
636
|
+
if (storedUrl) {
|
|
637
|
+
try {
|
|
638
|
+
await dataAccess.updateInvoice(invoiceData.id, { pdf_url: storedUrl });
|
|
639
|
+
} catch (updateErr) {
|
|
640
|
+
console.error('[invoice] Regenerate: could not save pdf_url=' + storedUrl + ' (id=' + invoiceData.id + '): ' + (updateErr && updateErr.message));
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
invoiceData.pdfUrl = pdfUrl;
|
|
644
|
+
if (storageKey !== previousStorageKey) {
|
|
645
|
+
await invoiceAssembly.recordStoredInvoicePdfKey(invoiceData.id, storageKey);
|
|
646
|
+
}
|
|
647
|
+
if (previousStorageKey && previousStorageKey !== storageKey) {
|
|
648
|
+
await invoiceAssembly.deleteStoredInvoicePdf(previousStorageKey);
|
|
649
|
+
}
|
|
650
|
+
|
|
651
|
+
res.status(200).json({
|
|
652
|
+
success: true,
|
|
653
|
+
invoiceId: invoiceData.id,
|
|
654
|
+
invoiceNumber: invoiceData.invoiceNumber,
|
|
655
|
+
pdfUrl: invoiceData.pdfUrl,
|
|
656
|
+
total: invoiceData.total,
|
|
657
|
+
currency: invoiceData.currency,
|
|
658
|
+
});
|
|
659
|
+
} catch (error) {
|
|
660
|
+
console.error('[invoice] Regeneration threw:', error && error.stack ? error.stack : error);
|
|
661
|
+
// The error names the store's tables and data: server log only (above).
|
|
662
|
+
res.status(500).json({ success: false, error: MESSAGES.failed });
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
`;
|
|
666
|
+
};
|
|
667
|
+
/**
|
|
668
|
+
* GET /api/invoices/[id]/pdf — the invoice PDF kept in the database, the link
|
|
669
|
+
* an order shows when runtime storage is not configured.
|
|
670
|
+
*
|
|
671
|
+
* An invoice carries its buyer's name, address and what they bought, so it is
|
|
672
|
+
* served to the order's own buyer (their session), a signed-in admin, or the
|
|
673
|
+
* store's server code — and to nobody else, whoever knows the id. An invoice
|
|
674
|
+
* someone may not read answers exactly like one that does not exist.
|
|
675
|
+
*/
|
|
677
676
|
export const generateInvoicePdfRouteCode = () => {
|
|
678
677
|
return `/**
|
|
679
678
|
* GET /api/invoices/[id]/pdf
|
|
680
|
-
* Returns the invoice PDF binary for download.
|
|
679
|
+
* Returns the invoice PDF binary for download, to its buyer or the store.
|
|
681
680
|
*/
|
|
682
681
|
|
|
683
682
|
var dataAccess = require('../../../../utils/invoices/data-access');
|
|
684
683
|
|
|
684
|
+
${INVOICE_CALLER_CODE}
|
|
685
|
+
|
|
686
|
+
// Postgres refuses an id that is not a UUID ("invalid_text_representation").
|
|
687
|
+
var MALFORMED_ID_ERROR_CODE = '22P02';
|
|
688
|
+
|
|
689
|
+
async function findInvoice(invoiceId) {
|
|
690
|
+
try {
|
|
691
|
+
return await dataAccess.getInvoiceById(invoiceId);
|
|
692
|
+
} catch (err) {
|
|
693
|
+
if (err && err.code === MALFORMED_ID_ERROR_CODE) return null;
|
|
694
|
+
throw err;
|
|
695
|
+
}
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
// The buyer of the invoice's order: the order row's owner, read from the order
|
|
699
|
+
// itself — an invoice's own customer fields are editable text.
|
|
700
|
+
async function isOrderOwner(invoice, userId) {
|
|
701
|
+
if (!userId || !invoice || !invoice.order_id) return false;
|
|
702
|
+
var hydrated = await dataAccess.getOrderWithItems(String(invoice.order_id));
|
|
703
|
+
var owner = hydrated && hydrated.order ? hydrated.order.user_id : null;
|
|
704
|
+
return owner != null && String(owner) === String(userId);
|
|
705
|
+
}
|
|
706
|
+
|
|
685
707
|
module.exports = async function handler(req, res) {
|
|
686
708
|
if (req.method !== 'GET') {
|
|
687
709
|
res.status(405).json({ error: 'Method not allowed' });
|
|
@@ -689,14 +711,20 @@ module.exports = async function handler(req, res) {
|
|
|
689
711
|
}
|
|
690
712
|
|
|
691
713
|
try {
|
|
714
|
+
var caller = await invoiceCaller(req);
|
|
715
|
+
if (!caller.server && !caller.signedIn) {
|
|
716
|
+
res.status(401).json({ error: 'Unauthenticated' });
|
|
717
|
+
return;
|
|
718
|
+
}
|
|
719
|
+
|
|
692
720
|
var invoiceId = req.query.id;
|
|
693
721
|
if (!invoiceId) {
|
|
694
722
|
res.status(400).json({ error: 'Invoice ID is required' });
|
|
695
723
|
return;
|
|
696
724
|
}
|
|
697
725
|
|
|
698
|
-
var invoice = await
|
|
699
|
-
if (!invoice) {
|
|
726
|
+
var invoice = await findInvoice(String(invoiceId));
|
|
727
|
+
if (!invoice || (!caller.server && !caller.admin && !(await isOrderOwner(invoice, caller.userId)))) {
|
|
700
728
|
res.status(404).json({ error: 'Invoice not found' });
|
|
701
729
|
return;
|
|
702
730
|
}
|
|
@@ -721,10 +749,13 @@ module.exports = async function handler(req, res) {
|
|
|
721
749
|
res.setHeader('Content-Type', 'application/pdf');
|
|
722
750
|
res.setHeader('Content-Disposition', 'attachment; filename="' + safeFilename + '"; filename*=UTF-8' + "'" + "'" + encodeURIComponent(rawFilename));
|
|
723
751
|
res.setHeader('Content-Length', pdfBuffer.length);
|
|
752
|
+
// Personal data: never kept by a shared cache.
|
|
753
|
+
res.setHeader('Cache-Control', 'private, no-store');
|
|
724
754
|
res.status(200).end(pdfBuffer);
|
|
725
755
|
} catch (error) {
|
|
756
|
+
// The error names the store's tables and data: server log only.
|
|
726
757
|
console.error('Invoice PDF download error:', error);
|
|
727
|
-
res.status(500).json({ success: false, error:
|
|
758
|
+
res.status(500).json({ success: false, error: 'Failed to retrieve invoice PDF' });
|
|
728
759
|
}
|
|
729
760
|
};
|
|
730
761
|
`;
|