@teleporthq/teleport-plugin-next-workflows 0.44.11 → 0.44.17
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/fake-fetch.ts +75 -0
- package/__tests__/_helpers/gui-place-order-statements.ts +17 -0
- package/__tests__/_helpers/inserted-lines.ts +22 -0
- package/__tests__/_helpers/invoice-store.ts +10 -1
- package/__tests__/_helpers/load-security-runtime.ts +45 -0
- package/__tests__/_helpers/load-server-runtime.ts +26 -3
- package/__tests__/_helpers/run-account-delete-route.ts +3 -1
- package/__tests__/_helpers/run-generated-middleware.ts +7 -2
- package/__tests__/account-delete-owned-rows.test.ts +3 -1
- package/__tests__/adopted-element-trigger-code.test.ts +128 -0
- package/__tests__/analytics-track-outcome.test.ts +145 -0
- package/__tests__/auth-password-change-ends-sessions.test.ts +8 -1
- package/__tests__/auth-password-security.test.ts +2275 -0
- package/__tests__/auth-session-cost.test.ts +31 -0
- package/__tests__/auth-signup-route.test.ts +960 -0
- package/__tests__/authored-code-every-path.test.ts +247 -0
- package/__tests__/automations-bus.test.ts +3820 -0
- package/__tests__/automations-catalog-drift.test.ts +97 -0
- package/__tests__/booking-calendar-feed-route.test.ts +20 -3
- package/__tests__/cart-price-order.test.ts +336 -1
- package/__tests__/code-lookup-rate-limit-route.test.ts +189 -0
- package/__tests__/cost-bearing-node-types.test.ts +119 -0
- package/__tests__/credential-columns-reply.test.ts +9 -0
- package/__tests__/credential-result-reply.test.ts +19 -5
- package/__tests__/cron-route-loop-templateparams.test.ts +6 -3
- package/__tests__/custom-js-authored-code.test.ts +304 -0
- package/__tests__/custom-node-custom-code-gate.test.ts +136 -0
- package/__tests__/custom-node-step-handlers.test.ts +251 -0
- package/__tests__/custom-node-step-reach.test.ts +63 -0
- package/__tests__/data-api-anon-user-id-fallback.test.ts +7 -2
- package/__tests__/data-api-browser-reads.test.ts +7 -0
- package/__tests__/data-api-business-events.test.ts +403 -0
- package/__tests__/data-api-invalid-body.test.ts +7 -0
- package/__tests__/data-api-low-stock-autofire.test.ts +30 -4
- package/__tests__/data-api-optional-feature-columns.test.ts +44 -0
- package/__tests__/data-api-owner-scope-credentials.test.ts +1324 -0
- package/__tests__/data-api-protected-tables.test.ts +48 -15
- package/__tests__/data-api-retired-table-and-account-fields.test.ts +208 -0
- package/__tests__/email-locale-senders.test.ts +5 -3
- package/__tests__/expression-injection.test.ts +343 -0
- package/__tests__/fixtures/admin-file-workflows.json +242 -0
- package/__tests__/form-confirmation-email-template.test.ts +44 -0
- package/__tests__/internal-request-headers.test.ts +25 -0
- package/__tests__/invoice-pdf-service-project-header.test.ts +120 -0
- package/__tests__/invoice-self-call-origin.test.ts +57 -1
- package/__tests__/legacy-webhook-self-calls.test.ts +86 -1
- package/__tests__/middleware-home-route-protection.test.ts +3 -1
- package/__tests__/middleware-subscriber-access.test.ts +1 -1
- package/__tests__/newsletter-admin-route.test.ts +649 -0
- package/__tests__/newsletter-plugin.test.ts +1248 -0
- package/__tests__/outbound-nodes-security.test.ts +1929 -0
- package/__tests__/page-access-guard.test.ts +217 -0
- package/__tests__/page-access-route-table.test.ts +231 -0
- package/__tests__/payment-drivers-module.test.ts +23 -0
- package/__tests__/payment-legacy-webhook-routes.test.ts +100 -5
- package/__tests__/payment-webhook-route.test.ts +4 -1
- package/__tests__/paypal-webhook-signature-verification.test.ts +44 -0
- package/__tests__/place-order-guards.test.ts +506 -0
- package/__tests__/public-step-guards.test.ts +310 -0
- package/__tests__/publish-refusals.test.ts +505 -0
- package/__tests__/realtime-identity-routes.test.ts +492 -0
- package/__tests__/record-event-writer-server-only.test.ts +975 -0
- package/__tests__/resolve-config-template-params.test.ts +3 -3
- package/__tests__/runtime-storage-upload-access.test.ts +280 -17
- package/__tests__/security-integration-env-names.test.ts +74 -0
- package/__tests__/security-lists-parity.test.ts +245 -0
- package/__tests__/security-runtime-shadow.test.ts +224 -1
- package/__tests__/security-runtime.test.ts +893 -0
- package/__tests__/segment-rate-limit-error-branch.test.ts +284 -0
- package/__tests__/segment-route-abuse-gate.test.ts +309 -0
- package/__tests__/server-job-hops-real-data-api.test.ts +669 -0
- package/__tests__/server-session-identity.test.ts +522 -0
- package/__tests__/server-step-chain.test.ts +222 -0
- package/__tests__/server-step-signing.test.ts +107 -2
- package/__tests__/session-cookie-resolver.test.ts +62 -106
- package/__tests__/signup-event.test.ts +649 -0
- package/__tests__/signup-reply-identical.test.ts +144 -0
- package/__tests__/slack-message-escaping.test.ts +123 -0
- package/__tests__/visitor-step-limits.test.ts +318 -0
- package/__tests__/webhook-delivery-lease.test.ts +4 -1
- package/__tests__/webpack-safe-handlers.test.ts +57 -8
- package/__tests__/workflow-auth-guard.test.ts +9 -1
- package/dist/cjs/account-delete-route-generator.d.ts +1 -0
- package/dist/cjs/account-delete-route-generator.d.ts.map +1 -1
- package/dist/cjs/account-delete-route-generator.js +18 -3
- package/dist/cjs/account-delete-route-generator.js.map +1 -1
- package/dist/cjs/api-route-generator.d.ts +52 -3
- package/dist/cjs/api-route-generator.d.ts.map +1 -1
- package/dist/cjs/api-route-generator.js +600 -145
- package/dist/cjs/api-route-generator.js.map +1 -1
- package/dist/cjs/auth-generator.d.ts +126 -3
- package/dist/cjs/auth-generator.d.ts.map +1 -1
- package/dist/cjs/auth-generator.js +1353 -139
- package/dist/cjs/auth-generator.js.map +1 -1
- package/dist/cjs/automations/activity-kicks.d.ts +12 -0
- package/dist/cjs/automations/activity-kicks.d.ts.map +1 -0
- package/dist/cjs/automations/activity-kicks.js +123 -0
- package/dist/cjs/automations/activity-kicks.js.map +1 -0
- package/dist/cjs/automations/app-events-source.d.ts +33 -0
- package/dist/cjs/automations/app-events-source.d.ts.map +1 -0
- package/dist/cjs/automations/app-events-source.js +109 -0
- package/dist/cjs/automations/app-events-source.js.map +1 -0
- package/dist/cjs/automations/automations-project-plugin.d.ts +21 -0
- package/dist/cjs/automations/automations-project-plugin.d.ts.map +1 -0
- package/dist/cjs/automations/automations-project-plugin.js +102 -0
- package/dist/cjs/automations/automations-project-plugin.js.map +1 -0
- package/dist/cjs/automations/automations-scope.d.ts +104 -0
- package/dist/cjs/automations/automations-scope.d.ts.map +1 -0
- package/dist/cjs/automations/automations-scope.js +176 -0
- package/dist/cjs/automations/automations-scope.js.map +1 -0
- package/dist/cjs/automations/dispatcher-source.d.ts +72 -0
- package/dist/cjs/automations/dispatcher-source.d.ts.map +1 -0
- package/dist/cjs/automations/dispatcher-source.js +1008 -0
- package/dist/cjs/automations/dispatcher-source.js.map +1 -0
- package/dist/cjs/automations/event-bus-source.d.ts +44 -0
- package/dist/cjs/automations/event-bus-source.d.ts.map +1 -0
- package/dist/cjs/automations/event-bus-source.js +427 -0
- package/dist/cjs/automations/event-bus-source.js.map +1 -0
- package/dist/cjs/automations/handler-module-generator.d.ts +25 -0
- package/dist/cjs/automations/handler-module-generator.d.ts.map +1 -0
- package/dist/cjs/automations/handler-module-generator.js +78 -0
- package/dist/cjs/automations/handler-module-generator.js.map +1 -0
- package/dist/cjs/automations/hydrators-source.d.ts +33 -0
- package/dist/cjs/automations/hydrators-source.d.ts.map +1 -0
- package/dist/cjs/automations/hydrators-source.js +571 -0
- package/dist/cjs/automations/hydrators-source.js.map +1 -0
- package/dist/cjs/booking-calendar-feed-route-generator.d.ts.map +1 -1
- package/dist/cjs/booking-calendar-feed-route-generator.js +8 -0
- package/dist/cjs/booking-calendar-feed-route-generator.js.map +1 -1
- package/dist/cjs/configured-nextauth-url.d.ts +17 -0
- package/dist/cjs/configured-nextauth-url.d.ts.map +1 -0
- package/dist/cjs/configured-nextauth-url.js +20 -0
- package/dist/cjs/configured-nextauth-url.js.map +1 -0
- package/dist/cjs/cron-request-verification.d.ts +22 -1
- package/dist/cjs/cron-request-verification.d.ts.map +1 -1
- package/dist/cjs/cron-request-verification.js +50 -6
- package/dist/cjs/cron-request-verification.js.map +1 -1
- package/dist/cjs/data-api-route-generator.d.ts +19 -0
- package/dist/cjs/data-api-route-generator.d.ts.map +1 -1
- package/dist/cjs/data-api-route-generator.js +711 -43
- package/dist/cjs/data-api-route-generator.js.map +1 -1
- package/dist/cjs/ecommerce/parameterized-stock-chain.d.ts +3 -1
- package/dist/cjs/ecommerce/parameterized-stock-chain.d.ts.map +1 -1
- package/dist/cjs/ecommerce/parameterized-stock-chain.js +45 -5
- package/dist/cjs/ecommerce/parameterized-stock-chain.js.map +1 -1
- package/dist/cjs/ecommerce/place-order-guards.d.ts +126 -0
- package/dist/cjs/ecommerce/place-order-guards.d.ts.map +1 -0
- package/dist/cjs/ecommerce/place-order-guards.js +670 -0
- package/dist/cjs/ecommerce/place-order-guards.js.map +1 -0
- package/dist/cjs/ecommerce-customhandler-rewriter.d.ts +2 -0
- package/dist/cjs/ecommerce-customhandler-rewriter.d.ts.map +1 -1
- package/dist/cjs/ecommerce-customhandler-rewriter.js +38 -2
- package/dist/cjs/ecommerce-customhandler-rewriter.js.map +1 -1
- package/dist/cjs/executor-generator.d.ts.map +1 -1
- package/dist/cjs/executor-generator.js +368 -60
- package/dist/cjs/executor-generator.js.map +1 -1
- package/dist/cjs/graph-utils.d.ts +9 -0
- package/dist/cjs/graph-utils.d.ts.map +1 -1
- package/dist/cjs/graph-utils.js +32 -1
- package/dist/cjs/graph-utils.js.map +1 -1
- package/dist/cjs/index.d.ts +20 -1
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +72 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/invoice/api-routes-code.d.ts +9 -3
- package/dist/cjs/invoice/api-routes-code.d.ts.map +1 -1
- package/dist/cjs/invoice/api-routes-code.js +9 -7
- package/dist/cjs/invoice/api-routes-code.js.map +1 -1
- package/dist/cjs/invoice/index.d.ts.map +1 -1
- package/dist/cjs/invoice/index.js +12 -7
- package/dist/cjs/invoice/index.js.map +1 -1
- package/dist/cjs/invoice/invoice-assembly-code.d.ts.map +1 -1
- package/dist/cjs/invoice/invoice-assembly-code.js +8 -3
- package/dist/cjs/invoice/invoice-assembly-code.js.map +1 -1
- package/dist/cjs/invoice/pdf-generator-code.d.ts.map +1 -1
- package/dist/cjs/invoice/pdf-generator-code.js +2 -1
- package/dist/cjs/invoice/pdf-generator-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 +15 -7
- package/dist/cjs/invoice/pdf-service-client-code.js.map +1 -1
- package/dist/cjs/newsletter/admin-route-code.d.ts +60 -0
- package/dist/cjs/newsletter/admin-route-code.d.ts.map +1 -0
- package/dist/cjs/newsletter/admin-route-code.js +300 -0
- package/dist/cjs/newsletter/admin-route-code.js.map +1 -0
- package/dist/cjs/newsletter/helper-code.d.ts +109 -0
- package/dist/cjs/newsletter/helper-code.d.ts.map +1 -0
- package/dist/cjs/newsletter/helper-code.js +662 -0
- package/dist/cjs/newsletter/helper-code.js.map +1 -0
- package/dist/cjs/newsletter/newsletter-scope.d.ts +65 -0
- package/dist/cjs/newsletter/newsletter-scope.d.ts.map +1 -0
- package/dist/cjs/newsletter/newsletter-scope.js +103 -0
- package/dist/cjs/newsletter/newsletter-scope.js.map +1 -0
- package/dist/cjs/newsletter/project-plugin.d.ts +18 -0
- package/dist/cjs/newsletter/project-plugin.d.ts.map +1 -0
- package/dist/cjs/newsletter/project-plugin.js +97 -0
- package/dist/cjs/newsletter/project-plugin.js.map +1 -0
- package/dist/cjs/newsletter/routes-code.d.ts +6 -0
- package/dist/cjs/newsletter/routes-code.d.ts.map +1 -0
- package/dist/cjs/newsletter/routes-code.js +181 -0
- package/dist/cjs/newsletter/routes-code.js.map +1 -0
- package/dist/cjs/nodes/account/account-compare-passwords.d.ts.map +1 -1
- package/dist/cjs/nodes/account/account-compare-passwords.js +16 -6
- package/dist/cjs/nodes/account/account-compare-passwords.js.map +1 -1
- package/dist/cjs/nodes/account/account-delete-current.js +1 -1
- package/dist/cjs/nodes/account/account-get-current.js +1 -1
- package/dist/cjs/nodes/account/account-hash-password.d.ts.map +1 -1
- package/dist/cjs/nodes/account/account-hash-password.js +15 -3
- package/dist/cjs/nodes/account/account-hash-password.js.map +1 -1
- package/dist/cjs/nodes/account/account-login.d.ts.map +1 -1
- package/dist/cjs/nodes/account/account-login.js +23 -6
- package/dist/cjs/nodes/account/account-login.js.map +1 -1
- package/dist/cjs/nodes/account/account-logout.js +1 -1
- package/dist/cjs/nodes/account/account-refresh-session.js +1 -1
- package/dist/cjs/nodes/account/account-request-password-reset.d.ts +3 -0
- package/dist/cjs/nodes/account/account-request-password-reset.d.ts.map +1 -0
- package/dist/cjs/nodes/account/account-request-password-reset.js +46 -0
- package/dist/cjs/nodes/account/account-request-password-reset.js.map +1 -0
- package/dist/cjs/nodes/account/account-reset-password.d.ts +3 -0
- package/dist/cjs/nodes/account/account-reset-password.d.ts.map +1 -0
- package/dist/cjs/nodes/account/account-reset-password.js +44 -0
- package/dist/cjs/nodes/account/account-reset-password.js.map +1 -0
- package/dist/cjs/nodes/account/account-signup.d.ts.map +1 -1
- package/dist/cjs/nodes/account/account-signup.js +82 -19
- package/dist/cjs/nodes/account/account-signup.js.map +1 -1
- package/dist/cjs/nodes/account/account-social-login.js +1 -1
- package/dist/cjs/nodes/ai/ai-custom-prompt.d.ts.map +1 -1
- package/dist/cjs/nodes/ai/ai-custom-prompt.js +20 -5
- package/dist/cjs/nodes/ai/ai-custom-prompt.js.map +1 -1
- package/dist/cjs/nodes/ai/ai-detect-language.d.ts.map +1 -1
- package/dist/cjs/nodes/ai/ai-detect-language.js +20 -5
- package/dist/cjs/nodes/ai/ai-detect-language.js.map +1 -1
- package/dist/cjs/nodes/ai/ai-generate-text-embedding.d.ts.map +1 -1
- package/dist/cjs/nodes/ai/ai-generate-text-embedding.js +10 -2
- package/dist/cjs/nodes/ai/ai-generate-text-embedding.js.map +1 -1
- package/dist/cjs/nodes/ai/ai-provider-utils-sources.generated.js +2 -2
- package/dist/cjs/nodes/ai/ai-provider-utils-sources.generated.js.map +1 -1
- package/dist/cjs/nodes/ai/ai-provider-utils.d.ts +31 -2
- package/dist/cjs/nodes/ai/ai-provider-utils.d.ts.map +1 -1
- package/dist/cjs/nodes/ai/ai-provider-utils.js +125 -11
- package/dist/cjs/nodes/ai/ai-provider-utils.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 -2
- package/dist/cjs/nodes/ai/ai-select-database-data.js.map +1 -1
- package/dist/cjs/nodes/ai/ai-sentiment-analysis.d.ts.map +1 -1
- package/dist/cjs/nodes/ai/ai-sentiment-analysis.js +20 -5
- package/dist/cjs/nodes/ai/ai-sentiment-analysis.js.map +1 -1
- package/dist/cjs/nodes/ai/ai-summarization.d.ts.map +1 -1
- package/dist/cjs/nodes/ai/ai-summarization.js +20 -5
- package/dist/cjs/nodes/ai/ai-summarization.js.map +1 -1
- package/dist/cjs/nodes/ai/ai-text-classifier.d.ts.map +1 -1
- package/dist/cjs/nodes/ai/ai-text-classifier.js +20 -5
- package/dist/cjs/nodes/ai/ai-text-classifier.js.map +1 -1
- package/dist/cjs/nodes/ai/ai-text-transform.d.ts.map +1 -1
- package/dist/cjs/nodes/ai/ai-text-transform.js +20 -5
- package/dist/cjs/nodes/ai/ai-text-transform.js.map +1 -1
- package/dist/cjs/nodes/analytics/analytics-track-outcome.d.ts +3 -0
- package/dist/cjs/nodes/analytics/analytics-track-outcome.d.ts.map +1 -0
- package/dist/cjs/nodes/analytics/analytics-track-outcome.js +110 -0
- package/dist/cjs/nodes/analytics/analytics-track-outcome.js.map +1 -0
- package/dist/cjs/nodes/cart/cart-price-order.d.ts.map +1 -1
- package/dist/cjs/nodes/cart/cart-price-order.js +161 -2
- package/dist/cjs/nodes/cart/cart-price-order.js.map +1 -1
- package/dist/cjs/nodes/cost-bearing-node-types.d.ts +4 -0
- package/dist/cjs/nodes/cost-bearing-node-types.d.ts.map +1 -0
- package/dist/cjs/nodes/cost-bearing-node-types.js +43 -0
- package/dist/cjs/nodes/cost-bearing-node-types.js.map +1 -0
- package/dist/cjs/nodes/data/data-select.d.ts.map +1 -1
- package/dist/cjs/nodes/data/data-select.js +12 -2
- package/dist/cjs/nodes/data/data-select.js.map +1 -1
- package/dist/cjs/nodes/email/email-mailersend.d.ts.map +1 -1
- package/dist/cjs/nodes/email/email-mailersend.js +15 -11
- package/dist/cjs/nodes/email/email-mailersend.js.map +1 -1
- package/dist/cjs/nodes/email/email-mailgun.d.ts.map +1 -1
- package/dist/cjs/nodes/email/email-mailgun.js +15 -15
- package/dist/cjs/nodes/email/email-mailgun.js.map +1 -1
- package/dist/cjs/nodes/email/email-postmark.d.ts.map +1 -1
- package/dist/cjs/nodes/email/email-postmark.js +15 -15
- package/dist/cjs/nodes/email/email-postmark.js.map +1 -1
- package/dist/cjs/nodes/email/email-resend.d.ts.map +1 -1
- package/dist/cjs/nodes/email/email-resend.js +15 -15
- package/dist/cjs/nodes/email/email-resend.js.map +1 -1
- package/dist/cjs/nodes/email/email-sendgrid.d.ts.map +1 -1
- package/dist/cjs/nodes/email/email-sendgrid.js +15 -15
- package/dist/cjs/nodes/email/email-sendgrid.js.map +1 -1
- package/dist/cjs/nodes/email/html-escape-code.d.ts +3 -0
- package/dist/cjs/nodes/email/html-escape-code.d.ts.map +1 -0
- package/dist/cjs/nodes/email/html-escape-code.js +23 -0
- package/dist/cjs/nodes/email/html-escape-code.js.map +1 -0
- package/dist/cjs/nodes/email/message-trust.d.ts +40 -0
- package/dist/cjs/nodes/email/message-trust.d.ts.map +1 -0
- package/dist/cjs/nodes/email/message-trust.js +167 -0
- package/dist/cjs/nodes/email/message-trust.js.map +1 -0
- package/dist/cjs/nodes/email/outbound-message-guard.d.ts +113 -0
- package/dist/cjs/nodes/email/outbound-message-guard.d.ts.map +1 -0
- package/dist/cjs/nodes/email/outbound-message-guard.js +460 -0
- package/dist/cjs/nodes/email/outbound-message-guard.js.map +1 -0
- package/dist/cjs/nodes/email/trusted-html-code.d.ts +22 -0
- package/dist/cjs/nodes/email/trusted-html-code.d.ts.map +1 -0
- package/dist/cjs/nodes/email/trusted-html-code.js +52 -0
- package/dist/cjs/nodes/email/trusted-html-code.js.map +1 -0
- package/dist/cjs/nodes/general/general-custom-js.d.ts.map +1 -1
- package/dist/cjs/nodes/general/general-custom-js.js +44 -7
- package/dist/cjs/nodes/general/general-custom-js.js.map +1 -1
- package/dist/cjs/nodes/general/general-http-request.d.ts.map +1 -1
- package/dist/cjs/nodes/general/general-http-request.js +431 -45
- package/dist/cjs/nodes/general/general-http-request.js.map +1 -1
- package/dist/cjs/nodes/general/general-rate-limiter.d.ts.map +1 -1
- package/dist/cjs/nodes/general/general-rate-limiter.js +46 -78
- package/dist/cjs/nodes/general/general-rate-limiter.js.map +1 -1
- package/dist/cjs/nodes/general/general-wait.d.ts +3 -0
- package/dist/cjs/nodes/general/general-wait.d.ts.map +1 -0
- package/dist/cjs/nodes/general/general-wait.js +81 -0
- package/dist/cjs/nodes/general/general-wait.js.map +1 -0
- package/dist/cjs/nodes/general/visitor-request.d.ts +44 -0
- package/dist/cjs/nodes/general/visitor-request.d.ts.map +1 -0
- package/dist/cjs/nodes/general/visitor-request.js +72 -0
- package/dist/cjs/nodes/general/visitor-request.js.map +1 -0
- package/dist/cjs/nodes/index.d.ts.map +1 -1
- package/dist/cjs/nodes/index.js +7 -1
- package/dist/cjs/nodes/index.js.map +1 -1
- package/dist/cjs/nodes/integrations/integration-slack.d.ts.map +1 -1
- package/dist/cjs/nodes/integrations/integration-slack.js +17 -6
- package/dist/cjs/nodes/integrations/integration-slack.js.map +1 -1
- package/dist/cjs/nodes/newsletter/newsletter-confirm.d.ts +3 -0
- package/dist/cjs/nodes/newsletter/newsletter-confirm.d.ts.map +1 -0
- package/dist/cjs/nodes/newsletter/newsletter-confirm.js +41 -0
- package/dist/cjs/nodes/newsletter/newsletter-confirm.js.map +1 -0
- package/dist/cjs/nodes/newsletter/newsletter-subscribe.d.ts +7 -0
- package/dist/cjs/nodes/newsletter/newsletter-subscribe.d.ts.map +1 -0
- package/dist/cjs/nodes/newsletter/newsletter-subscribe.js +69 -0
- package/dist/cjs/nodes/newsletter/newsletter-subscribe.js.map +1 -0
- package/dist/cjs/nodes/newsletter/newsletter-unsubscribe.d.ts +3 -0
- package/dist/cjs/nodes/newsletter/newsletter-unsubscribe.d.ts.map +1 -0
- package/dist/cjs/nodes/newsletter/newsletter-unsubscribe.js +42 -0
- package/dist/cjs/nodes/newsletter/newsletter-unsubscribe.js.map +1 -0
- package/dist/cjs/nodes/realtime/realtime-join-channel.d.ts.map +1 -1
- package/dist/cjs/nodes/realtime/realtime-join-channel.js +5 -4
- package/dist/cjs/nodes/realtime/realtime-join-channel.js.map +1 -1
- package/dist/cjs/nodes/realtime/realtime-send-channel-event.d.ts.map +1 -1
- package/dist/cjs/nodes/realtime/realtime-send-channel-event.js +11 -2
- package/dist/cjs/nodes/realtime/realtime-send-channel-event.js.map +1 -1
- package/dist/cjs/nodes/realtime/realtime-send-channel-message.d.ts.map +1 -1
- package/dist/cjs/nodes/realtime/realtime-send-channel-message.js +11 -2
- package/dist/cjs/nodes/realtime/realtime-send-channel-message.js.map +1 -1
- package/dist/cjs/nodes/sms/sms-infobip.d.ts.map +1 -1
- package/dist/cjs/nodes/sms/sms-infobip.js +11 -8
- package/dist/cjs/nodes/sms/sms-infobip.js.map +1 -1
- package/dist/cjs/nodes/sms/sms-smsapi.d.ts.map +1 -1
- package/dist/cjs/nodes/sms/sms-smsapi.js +11 -8
- package/dist/cjs/nodes/sms/sms-smsapi.js.map +1 -1
- package/dist/cjs/nodes/sms/sms-textmagic.d.ts.map +1 -1
- package/dist/cjs/nodes/sms/sms-textmagic.js +11 -8
- package/dist/cjs/nodes/sms/sms-textmagic.js.map +1 -1
- package/dist/cjs/nodes/sms/sms-twilio.d.ts.map +1 -1
- package/dist/cjs/nodes/sms/sms-twilio.js +12 -10
- package/dist/cjs/nodes/sms/sms-twilio.js.map +1 -1
- package/dist/cjs/nodes/types.d.ts +8 -1
- package/dist/cjs/nodes/types.d.ts.map +1 -1
- package/dist/cjs/nodes/utility/utility-similarity-scoring.d.ts.map +1 -1
- package/dist/cjs/nodes/utility/utility-similarity-scoring.js +29 -10
- package/dist/cjs/nodes/utility/utility-similarity-scoring.js.map +1 -1
- package/dist/cjs/page-access-guard-generator.d.ts +23 -0
- package/dist/cjs/page-access-guard-generator.d.ts.map +1 -0
- package/dist/cjs/page-access-guard-generator.js +135 -0
- package/dist/cjs/page-access-guard-generator.js.map +1 -0
- package/dist/cjs/password-reset-route-generator.d.ts +119 -0
- package/dist/cjs/password-reset-route-generator.d.ts.map +1 -0
- package/dist/cjs/password-reset-route-generator.js +460 -0
- package/dist/cjs/password-reset-route-generator.js.map +1 -0
- package/dist/cjs/payments/payment-core-code.d.ts.map +1 -1
- package/dist/cjs/payments/payment-core-code.js +12 -7
- package/dist/cjs/payments/payment-core-code.js.map +1 -1
- package/dist/cjs/project-code-scanner.d.ts +11 -0
- package/dist/cjs/project-code-scanner.d.ts.map +1 -0
- package/dist/cjs/project-code-scanner.js +80 -0
- package/dist/cjs/project-code-scanner.js.map +1 -0
- package/dist/cjs/public-step-guards.d.ts +122 -0
- package/dist/cjs/public-step-guards.d.ts.map +1 -0
- package/dist/cjs/public-step-guards.js +288 -0
- package/dist/cjs/public-step-guards.js.map +1 -0
- package/dist/cjs/publish-refusals.d.ts +66 -0
- package/dist/cjs/publish-refusals.d.ts.map +1 -0
- package/dist/cjs/publish-refusals.js +278 -0
- package/dist/cjs/publish-refusals.js.map +1 -0
- package/dist/cjs/realtime-generator.d.ts +63 -1
- package/dist/cjs/realtime-generator.d.ts.map +1 -1
- package/dist/cjs/realtime-generator.js +404 -230
- package/dist/cjs/realtime-generator.js.map +1 -1
- package/dist/cjs/runtime-storage-generator.d.ts +32 -1
- package/dist/cjs/runtime-storage-generator.d.ts.map +1 -1
- package/dist/cjs/runtime-storage-generator.js +265 -12
- package/dist/cjs/runtime-storage-generator.js.map +1 -1
- package/dist/cjs/security-runtime/index.d.ts +14 -0
- package/dist/cjs/security-runtime/index.d.ts.map +1 -0
- package/dist/cjs/security-runtime/index.js +48 -0
- package/dist/cjs/security-runtime/index.js.map +1 -0
- package/dist/cjs/security-runtime/security-runtime-code.d.ts +53 -0
- package/dist/cjs/security-runtime/security-runtime-code.d.ts.map +1 -0
- package/dist/cjs/security-runtime/security-runtime-code.js +580 -0
- package/dist/cjs/security-runtime/security-runtime-code.js.map +1 -0
- package/dist/cjs/security-scanner.d.ts +72 -3
- package/dist/cjs/security-scanner.d.ts.map +1 -1
- package/dist/cjs/security-scanner.js +220 -8
- package/dist/cjs/security-scanner.js.map +1 -1
- package/dist/cjs/segment-splitter.d.ts.map +1 -1
- package/dist/cjs/segment-splitter.js +10 -2
- package/dist/cjs/segment-splitter.js.map +1 -1
- package/dist/cjs/segment-trust.d.ts +36 -0
- package/dist/cjs/segment-trust.d.ts.map +1 -1
- package/dist/cjs/segment-trust.js +147 -3
- package/dist/cjs/segment-trust.js.map +1 -1
- package/dist/cjs/self-call-headers.d.ts +31 -0
- package/dist/cjs/self-call-headers.d.ts.map +1 -0
- package/dist/cjs/self-call-headers.js +48 -0
- package/dist/cjs/self-call-headers.js.map +1 -0
- package/dist/cjs/sent-email-log/index.d.ts +7 -0
- package/dist/cjs/sent-email-log/index.d.ts.map +1 -1
- package/dist/cjs/sent-email-log/index.js +17 -1
- package/dist/cjs/sent-email-log/index.js.map +1 -1
- package/dist/cjs/sent-email-log/sent-email-log-code.d.ts +7 -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 +17 -3
- package/dist/cjs/sent-email-log/sent-email-log-code.js.map +1 -1
- package/dist/cjs/server-custom-node-call.d.ts +79 -0
- package/dist/cjs/server-custom-node-call.d.ts.map +1 -0
- package/dist/cjs/server-custom-node-call.js +285 -0
- package/dist/cjs/server-custom-node-call.js.map +1 -0
- package/dist/cjs/server-runtime-code.d.ts +39 -12
- package/dist/cjs/server-runtime-code.d.ts.map +1 -1
- package/dist/cjs/server-runtime-code.js +484 -41
- package/dist/cjs/server-runtime-code.js.map +1 -1
- package/dist/cjs/session-cookie-resolver.d.ts +3 -1
- package/dist/cjs/session-cookie-resolver.d.ts.map +1 -1
- package/dist/cjs/session-revocation-generator.d.ts +39 -0
- package/dist/cjs/session-revocation-generator.d.ts.map +1 -0
- package/dist/cjs/session-revocation-generator.js +177 -0
- package/dist/cjs/session-revocation-generator.js.map +1 -0
- package/dist/cjs/slack-message-values.d.ts +6 -0
- package/dist/cjs/slack-message-values.d.ts.map +1 -0
- package/dist/cjs/slack-message-values.js +73 -0
- package/dist/cjs/slack-message-values.js.map +1 -0
- package/dist/cjs/transactional-email-code.d.ts +11 -0
- package/dist/cjs/transactional-email-code.d.ts.map +1 -1
- package/dist/cjs/transactional-email-code.js +29 -5
- package/dist/cjs/transactional-email-code.js.map +1 -1
- package/dist/cjs/trigger-generator.d.ts +2 -0
- package/dist/cjs/trigger-generator.d.ts.map +1 -1
- package/dist/cjs/trigger-generator.js +17 -4
- package/dist/cjs/trigger-generator.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/visitor-step-limits.d.ts +66 -0
- package/dist/cjs/visitor-step-limits.d.ts.map +1 -0
- package/dist/cjs/visitor-step-limits.js +187 -0
- package/dist/cjs/visitor-step-limits.js.map +1 -0
- package/dist/cjs/webhook-generator.d.ts.map +1 -1
- package/dist/cjs/webhook-generator.js +93 -15
- package/dist/cjs/webhook-generator.js.map +1 -1
- package/dist/cjs/webhook-signature-verification.d.ts.map +1 -1
- package/dist/cjs/webhook-signature-verification.js +13 -3
- package/dist/cjs/webhook-signature-verification.js.map +1 -1
- package/dist/cjs/workflow-auth-generator.d.ts +4 -1
- package/dist/cjs/workflow-auth-generator.d.ts.map +1 -1
- package/dist/cjs/workflow-auth-generator.js +8 -3
- package/dist/cjs/workflow-auth-generator.js.map +1 -1
- package/dist/cjs/workflow-component-plugin.js +11 -3
- package/dist/cjs/workflow-component-plugin.js.map +1 -1
- package/dist/cjs/workflow-project-plugin.d.ts.map +1 -1
- package/dist/cjs/workflow-project-plugin.js +302 -56
- package/dist/cjs/workflow-project-plugin.js.map +1 -1
- package/dist/cjs/workflow-scope.d.ts.map +1 -1
- package/dist/cjs/workflow-scope.js +5 -0
- package/dist/cjs/workflow-scope.js.map +1 -1
- package/dist/esm/account-delete-route-generator.d.ts +1 -0
- package/dist/esm/account-delete-route-generator.d.ts.map +1 -1
- package/dist/esm/account-delete-route-generator.js +18 -3
- package/dist/esm/account-delete-route-generator.js.map +1 -1
- package/dist/esm/api-route-generator.d.ts +52 -3
- package/dist/esm/api-route-generator.d.ts.map +1 -1
- package/dist/esm/api-route-generator.js +595 -142
- package/dist/esm/api-route-generator.js.map +1 -1
- package/dist/esm/auth-generator.d.ts +126 -3
- package/dist/esm/auth-generator.d.ts.map +1 -1
- package/dist/esm/auth-generator.js +1350 -140
- package/dist/esm/auth-generator.js.map +1 -1
- package/dist/esm/automations/activity-kicks.d.ts +12 -0
- package/dist/esm/automations/activity-kicks.d.ts.map +1 -0
- package/dist/esm/automations/activity-kicks.js +118 -0
- package/dist/esm/automations/activity-kicks.js.map +1 -0
- package/dist/esm/automations/app-events-source.d.ts +33 -0
- package/dist/esm/automations/app-events-source.d.ts.map +1 -0
- package/dist/esm/automations/app-events-source.js +104 -0
- package/dist/esm/automations/app-events-source.js.map +1 -0
- package/dist/esm/automations/automations-project-plugin.d.ts +21 -0
- package/dist/esm/automations/automations-project-plugin.d.ts.map +1 -0
- package/dist/esm/automations/automations-project-plugin.js +98 -0
- package/dist/esm/automations/automations-project-plugin.js.map +1 -0
- package/dist/esm/automations/automations-scope.d.ts +104 -0
- package/dist/esm/automations/automations-scope.d.ts.map +1 -0
- package/dist/esm/automations/automations-scope.js +165 -0
- package/dist/esm/automations/automations-scope.js.map +1 -0
- package/dist/esm/automations/dispatcher-source.d.ts +72 -0
- package/dist/esm/automations/dispatcher-source.d.ts.map +1 -0
- package/dist/esm/automations/dispatcher-source.js +999 -0
- package/dist/esm/automations/dispatcher-source.js.map +1 -0
- package/dist/esm/automations/event-bus-source.d.ts +44 -0
- package/dist/esm/automations/event-bus-source.d.ts.map +1 -0
- package/dist/esm/automations/event-bus-source.js +421 -0
- package/dist/esm/automations/event-bus-source.js.map +1 -0
- package/dist/esm/automations/handler-module-generator.d.ts +25 -0
- package/dist/esm/automations/handler-module-generator.d.ts.map +1 -0
- package/dist/esm/automations/handler-module-generator.js +71 -0
- package/dist/esm/automations/handler-module-generator.js.map +1 -0
- package/dist/esm/automations/hydrators-source.d.ts +33 -0
- package/dist/esm/automations/hydrators-source.d.ts.map +1 -0
- package/dist/esm/automations/hydrators-source.js +567 -0
- package/dist/esm/automations/hydrators-source.js.map +1 -0
- package/dist/esm/booking-calendar-feed-route-generator.d.ts.map +1 -1
- package/dist/esm/booking-calendar-feed-route-generator.js +8 -0
- package/dist/esm/booking-calendar-feed-route-generator.js.map +1 -1
- package/dist/esm/configured-nextauth-url.d.ts +17 -0
- package/dist/esm/configured-nextauth-url.d.ts.map +1 -0
- package/dist/esm/configured-nextauth-url.js +17 -0
- package/dist/esm/configured-nextauth-url.js.map +1 -0
- package/dist/esm/cron-request-verification.d.ts +22 -1
- package/dist/esm/cron-request-verification.d.ts.map +1 -1
- package/dist/esm/cron-request-verification.js +48 -5
- package/dist/esm/cron-request-verification.js.map +1 -1
- package/dist/esm/data-api-route-generator.d.ts +19 -0
- package/dist/esm/data-api-route-generator.d.ts.map +1 -1
- package/dist/esm/data-api-route-generator.js +710 -43
- package/dist/esm/data-api-route-generator.js.map +1 -1
- package/dist/esm/ecommerce/parameterized-stock-chain.d.ts +3 -1
- package/dist/esm/ecommerce/parameterized-stock-chain.d.ts.map +1 -1
- package/dist/esm/ecommerce/parameterized-stock-chain.js +43 -4
- package/dist/esm/ecommerce/parameterized-stock-chain.js.map +1 -1
- package/dist/esm/ecommerce/place-order-guards.d.ts +126 -0
- package/dist/esm/ecommerce/place-order-guards.d.ts.map +1 -0
- package/dist/esm/ecommerce/place-order-guards.js +655 -0
- package/dist/esm/ecommerce/place-order-guards.js.map +1 -0
- package/dist/esm/ecommerce-customhandler-rewriter.d.ts +2 -0
- package/dist/esm/ecommerce-customhandler-rewriter.d.ts.map +1 -1
- package/dist/esm/ecommerce-customhandler-rewriter.js +38 -2
- package/dist/esm/ecommerce-customhandler-rewriter.js.map +1 -1
- package/dist/esm/executor-generator.d.ts.map +1 -1
- package/dist/esm/executor-generator.js +368 -60
- package/dist/esm/executor-generator.js.map +1 -1
- package/dist/esm/graph-utils.d.ts +9 -0
- package/dist/esm/graph-utils.d.ts.map +1 -1
- package/dist/esm/graph-utils.js +30 -0
- package/dist/esm/graph-utils.js.map +1 -1
- package/dist/esm/index.d.ts +20 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +27 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/invoice/api-routes-code.d.ts +9 -3
- package/dist/esm/invoice/api-routes-code.d.ts.map +1 -1
- package/dist/esm/invoice/api-routes-code.js +9 -7
- package/dist/esm/invoice/api-routes-code.js.map +1 -1
- package/dist/esm/invoice/index.d.ts.map +1 -1
- package/dist/esm/invoice/index.js +12 -7
- package/dist/esm/invoice/index.js.map +1 -1
- package/dist/esm/invoice/invoice-assembly-code.d.ts.map +1 -1
- package/dist/esm/invoice/invoice-assembly-code.js +8 -3
- package/dist/esm/invoice/invoice-assembly-code.js.map +1 -1
- package/dist/esm/invoice/pdf-generator-code.d.ts.map +1 -1
- package/dist/esm/invoice/pdf-generator-code.js +2 -1
- package/dist/esm/invoice/pdf-generator-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 +15 -7
- package/dist/esm/invoice/pdf-service-client-code.js.map +1 -1
- package/dist/esm/newsletter/admin-route-code.d.ts +60 -0
- package/dist/esm/newsletter/admin-route-code.d.ts.map +1 -0
- package/dist/esm/newsletter/admin-route-code.js +295 -0
- package/dist/esm/newsletter/admin-route-code.js.map +1 -0
- package/dist/esm/newsletter/helper-code.d.ts +109 -0
- package/dist/esm/newsletter/helper-code.d.ts.map +1 -0
- package/dist/esm/newsletter/helper-code.js +656 -0
- package/dist/esm/newsletter/helper-code.js.map +1 -0
- package/dist/esm/newsletter/newsletter-scope.d.ts +65 -0
- package/dist/esm/newsletter/newsletter-scope.d.ts.map +1 -0
- package/dist/esm/newsletter/newsletter-scope.js +97 -0
- package/dist/esm/newsletter/newsletter-scope.js.map +1 -0
- package/dist/esm/newsletter/project-plugin.d.ts +18 -0
- package/dist/esm/newsletter/project-plugin.d.ts.map +1 -0
- package/dist/esm/newsletter/project-plugin.js +93 -0
- package/dist/esm/newsletter/project-plugin.js.map +1 -0
- package/dist/esm/newsletter/routes-code.d.ts +6 -0
- package/dist/esm/newsletter/routes-code.d.ts.map +1 -0
- package/dist/esm/newsletter/routes-code.js +175 -0
- package/dist/esm/newsletter/routes-code.js.map +1 -0
- package/dist/esm/nodes/account/account-compare-passwords.d.ts.map +1 -1
- package/dist/esm/nodes/account/account-compare-passwords.js +16 -6
- package/dist/esm/nodes/account/account-compare-passwords.js.map +1 -1
- package/dist/esm/nodes/account/account-delete-current.js +1 -1
- package/dist/esm/nodes/account/account-get-current.js +1 -1
- package/dist/esm/nodes/account/account-hash-password.d.ts.map +1 -1
- package/dist/esm/nodes/account/account-hash-password.js +15 -3
- package/dist/esm/nodes/account/account-hash-password.js.map +1 -1
- package/dist/esm/nodes/account/account-login.d.ts.map +1 -1
- package/dist/esm/nodes/account/account-login.js +23 -6
- package/dist/esm/nodes/account/account-login.js.map +1 -1
- package/dist/esm/nodes/account/account-logout.js +1 -1
- package/dist/esm/nodes/account/account-refresh-session.js +1 -1
- package/dist/esm/nodes/account/account-request-password-reset.d.ts +3 -0
- package/dist/esm/nodes/account/account-request-password-reset.d.ts.map +1 -0
- package/dist/esm/nodes/account/account-request-password-reset.js +43 -0
- package/dist/esm/nodes/account/account-request-password-reset.js.map +1 -0
- package/dist/esm/nodes/account/account-reset-password.d.ts +3 -0
- package/dist/esm/nodes/account/account-reset-password.d.ts.map +1 -0
- package/dist/esm/nodes/account/account-reset-password.js +41 -0
- package/dist/esm/nodes/account/account-reset-password.js.map +1 -0
- package/dist/esm/nodes/account/account-signup.d.ts.map +1 -1
- package/dist/esm/nodes/account/account-signup.js +82 -19
- package/dist/esm/nodes/account/account-signup.js.map +1 -1
- package/dist/esm/nodes/account/account-social-login.js +1 -1
- package/dist/esm/nodes/ai/ai-custom-prompt.d.ts.map +1 -1
- package/dist/esm/nodes/ai/ai-custom-prompt.js +20 -5
- package/dist/esm/nodes/ai/ai-custom-prompt.js.map +1 -1
- package/dist/esm/nodes/ai/ai-detect-language.d.ts.map +1 -1
- package/dist/esm/nodes/ai/ai-detect-language.js +20 -5
- package/dist/esm/nodes/ai/ai-detect-language.js.map +1 -1
- package/dist/esm/nodes/ai/ai-generate-text-embedding.d.ts.map +1 -1
- package/dist/esm/nodes/ai/ai-generate-text-embedding.js +10 -2
- package/dist/esm/nodes/ai/ai-generate-text-embedding.js.map +1 -1
- package/dist/esm/nodes/ai/ai-provider-utils-sources.generated.js +2 -2
- package/dist/esm/nodes/ai/ai-provider-utils-sources.generated.js.map +1 -1
- package/dist/esm/nodes/ai/ai-provider-utils.d.ts +31 -2
- package/dist/esm/nodes/ai/ai-provider-utils.d.ts.map +1 -1
- package/dist/esm/nodes/ai/ai-provider-utils.js +124 -10
- package/dist/esm/nodes/ai/ai-provider-utils.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 -2
- package/dist/esm/nodes/ai/ai-select-database-data.js.map +1 -1
- package/dist/esm/nodes/ai/ai-sentiment-analysis.d.ts.map +1 -1
- package/dist/esm/nodes/ai/ai-sentiment-analysis.js +20 -5
- package/dist/esm/nodes/ai/ai-sentiment-analysis.js.map +1 -1
- package/dist/esm/nodes/ai/ai-summarization.d.ts.map +1 -1
- package/dist/esm/nodes/ai/ai-summarization.js +20 -5
- package/dist/esm/nodes/ai/ai-summarization.js.map +1 -1
- package/dist/esm/nodes/ai/ai-text-classifier.d.ts.map +1 -1
- package/dist/esm/nodes/ai/ai-text-classifier.js +20 -5
- package/dist/esm/nodes/ai/ai-text-classifier.js.map +1 -1
- package/dist/esm/nodes/ai/ai-text-transform.d.ts.map +1 -1
- package/dist/esm/nodes/ai/ai-text-transform.js +20 -5
- package/dist/esm/nodes/ai/ai-text-transform.js.map +1 -1
- package/dist/esm/nodes/analytics/analytics-track-outcome.d.ts +3 -0
- package/dist/esm/nodes/analytics/analytics-track-outcome.d.ts.map +1 -0
- package/dist/esm/nodes/analytics/analytics-track-outcome.js +107 -0
- package/dist/esm/nodes/analytics/analytics-track-outcome.js.map +1 -0
- package/dist/esm/nodes/cart/cart-price-order.d.ts.map +1 -1
- package/dist/esm/nodes/cart/cart-price-order.js +161 -2
- package/dist/esm/nodes/cart/cart-price-order.js.map +1 -1
- package/dist/esm/nodes/cost-bearing-node-types.d.ts +4 -0
- package/dist/esm/nodes/cost-bearing-node-types.d.ts.map +1 -0
- package/dist/esm/nodes/cost-bearing-node-types.js +39 -0
- package/dist/esm/nodes/cost-bearing-node-types.js.map +1 -0
- package/dist/esm/nodes/data/data-select.d.ts.map +1 -1
- package/dist/esm/nodes/data/data-select.js +12 -2
- package/dist/esm/nodes/data/data-select.js.map +1 -1
- package/dist/esm/nodes/email/email-mailersend.d.ts.map +1 -1
- package/dist/esm/nodes/email/email-mailersend.js +15 -11
- package/dist/esm/nodes/email/email-mailersend.js.map +1 -1
- package/dist/esm/nodes/email/email-mailgun.d.ts.map +1 -1
- package/dist/esm/nodes/email/email-mailgun.js +15 -15
- package/dist/esm/nodes/email/email-mailgun.js.map +1 -1
- package/dist/esm/nodes/email/email-postmark.d.ts.map +1 -1
- package/dist/esm/nodes/email/email-postmark.js +15 -15
- package/dist/esm/nodes/email/email-postmark.js.map +1 -1
- package/dist/esm/nodes/email/email-resend.d.ts.map +1 -1
- package/dist/esm/nodes/email/email-resend.js +15 -15
- package/dist/esm/nodes/email/email-resend.js.map +1 -1
- package/dist/esm/nodes/email/email-sendgrid.d.ts.map +1 -1
- package/dist/esm/nodes/email/email-sendgrid.js +15 -15
- package/dist/esm/nodes/email/email-sendgrid.js.map +1 -1
- package/dist/esm/nodes/email/html-escape-code.d.ts +3 -0
- package/dist/esm/nodes/email/html-escape-code.d.ts.map +1 -0
- package/dist/esm/nodes/email/html-escape-code.js +18 -0
- package/dist/esm/nodes/email/html-escape-code.js.map +1 -0
- package/dist/esm/nodes/email/message-trust.d.ts +40 -0
- package/dist/esm/nodes/email/message-trust.d.ts.map +1 -0
- package/dist/esm/nodes/email/message-trust.js +161 -0
- package/dist/esm/nodes/email/message-trust.js.map +1 -0
- package/dist/esm/nodes/email/outbound-message-guard.d.ts +113 -0
- package/dist/esm/nodes/email/outbound-message-guard.d.ts.map +1 -0
- package/dist/esm/nodes/email/outbound-message-guard.js +452 -0
- package/dist/esm/nodes/email/outbound-message-guard.js.map +1 -0
- package/dist/esm/nodes/email/trusted-html-code.d.ts +22 -0
- package/dist/esm/nodes/email/trusted-html-code.d.ts.map +1 -0
- package/dist/esm/nodes/email/trusted-html-code.js +49 -0
- package/dist/esm/nodes/email/trusted-html-code.js.map +1 -0
- package/dist/esm/nodes/general/general-custom-js.d.ts.map +1 -1
- package/dist/esm/nodes/general/general-custom-js.js +44 -7
- package/dist/esm/nodes/general/general-custom-js.js.map +1 -1
- package/dist/esm/nodes/general/general-http-request.d.ts.map +1 -1
- package/dist/esm/nodes/general/general-http-request.js +431 -45
- package/dist/esm/nodes/general/general-http-request.js.map +1 -1
- package/dist/esm/nodes/general/general-rate-limiter.d.ts.map +1 -1
- package/dist/esm/nodes/general/general-rate-limiter.js +46 -78
- package/dist/esm/nodes/general/general-rate-limiter.js.map +1 -1
- package/dist/esm/nodes/general/general-wait.d.ts +3 -0
- package/dist/esm/nodes/general/general-wait.d.ts.map +1 -0
- package/dist/esm/nodes/general/general-wait.js +78 -0
- package/dist/esm/nodes/general/general-wait.js.map +1 -0
- package/dist/esm/nodes/general/visitor-request.d.ts +44 -0
- package/dist/esm/nodes/general/visitor-request.d.ts.map +1 -0
- package/dist/esm/nodes/general/visitor-request.js +65 -0
- package/dist/esm/nodes/general/visitor-request.js.map +1 -0
- package/dist/esm/nodes/index.d.ts.map +1 -1
- package/dist/esm/nodes/index.js +7 -1
- package/dist/esm/nodes/index.js.map +1 -1
- package/dist/esm/nodes/integrations/integration-slack.d.ts.map +1 -1
- package/dist/esm/nodes/integrations/integration-slack.js +17 -6
- package/dist/esm/nodes/integrations/integration-slack.js.map +1 -1
- package/dist/esm/nodes/newsletter/newsletter-confirm.d.ts +3 -0
- package/dist/esm/nodes/newsletter/newsletter-confirm.d.ts.map +1 -0
- package/dist/esm/nodes/newsletter/newsletter-confirm.js +38 -0
- package/dist/esm/nodes/newsletter/newsletter-confirm.js.map +1 -0
- package/dist/esm/nodes/newsletter/newsletter-subscribe.d.ts +7 -0
- package/dist/esm/nodes/newsletter/newsletter-subscribe.d.ts.map +1 -0
- package/dist/esm/nodes/newsletter/newsletter-subscribe.js +66 -0
- package/dist/esm/nodes/newsletter/newsletter-subscribe.js.map +1 -0
- package/dist/esm/nodes/newsletter/newsletter-unsubscribe.d.ts +3 -0
- package/dist/esm/nodes/newsletter/newsletter-unsubscribe.d.ts.map +1 -0
- package/dist/esm/nodes/newsletter/newsletter-unsubscribe.js +39 -0
- package/dist/esm/nodes/newsletter/newsletter-unsubscribe.js.map +1 -0
- package/dist/esm/nodes/realtime/realtime-join-channel.d.ts.map +1 -1
- package/dist/esm/nodes/realtime/realtime-join-channel.js +5 -4
- package/dist/esm/nodes/realtime/realtime-join-channel.js.map +1 -1
- package/dist/esm/nodes/realtime/realtime-send-channel-event.d.ts.map +1 -1
- package/dist/esm/nodes/realtime/realtime-send-channel-event.js +11 -2
- package/dist/esm/nodes/realtime/realtime-send-channel-event.js.map +1 -1
- package/dist/esm/nodes/realtime/realtime-send-channel-message.d.ts.map +1 -1
- package/dist/esm/nodes/realtime/realtime-send-channel-message.js +11 -2
- package/dist/esm/nodes/realtime/realtime-send-channel-message.js.map +1 -1
- package/dist/esm/nodes/sms/sms-infobip.d.ts.map +1 -1
- package/dist/esm/nodes/sms/sms-infobip.js +11 -8
- package/dist/esm/nodes/sms/sms-infobip.js.map +1 -1
- package/dist/esm/nodes/sms/sms-smsapi.d.ts.map +1 -1
- package/dist/esm/nodes/sms/sms-smsapi.js +11 -8
- package/dist/esm/nodes/sms/sms-smsapi.js.map +1 -1
- package/dist/esm/nodes/sms/sms-textmagic.d.ts.map +1 -1
- package/dist/esm/nodes/sms/sms-textmagic.js +11 -8
- package/dist/esm/nodes/sms/sms-textmagic.js.map +1 -1
- package/dist/esm/nodes/sms/sms-twilio.d.ts.map +1 -1
- package/dist/esm/nodes/sms/sms-twilio.js +12 -10
- package/dist/esm/nodes/sms/sms-twilio.js.map +1 -1
- package/dist/esm/nodes/types.d.ts +8 -1
- package/dist/esm/nodes/types.d.ts.map +1 -1
- package/dist/esm/nodes/utility/utility-similarity-scoring.d.ts.map +1 -1
- package/dist/esm/nodes/utility/utility-similarity-scoring.js +29 -10
- package/dist/esm/nodes/utility/utility-similarity-scoring.js.map +1 -1
- package/dist/esm/page-access-guard-generator.d.ts +23 -0
- package/dist/esm/page-access-guard-generator.d.ts.map +1 -0
- package/dist/esm/page-access-guard-generator.js +131 -0
- package/dist/esm/page-access-guard-generator.js.map +1 -0
- package/dist/esm/password-reset-route-generator.d.ts +119 -0
- package/dist/esm/password-reset-route-generator.d.ts.map +1 -0
- package/dist/esm/password-reset-route-generator.js +448 -0
- package/dist/esm/password-reset-route-generator.js.map +1 -0
- package/dist/esm/payments/payment-core-code.d.ts.map +1 -1
- package/dist/esm/payments/payment-core-code.js +12 -7
- package/dist/esm/payments/payment-core-code.js.map +1 -1
- package/dist/esm/project-code-scanner.d.ts +11 -0
- package/dist/esm/project-code-scanner.d.ts.map +1 -0
- package/dist/esm/project-code-scanner.js +75 -0
- package/dist/esm/project-code-scanner.js.map +1 -0
- package/dist/esm/public-step-guards.d.ts +122 -0
- package/dist/esm/public-step-guards.d.ts.map +1 -0
- package/dist/esm/public-step-guards.js +280 -0
- package/dist/esm/public-step-guards.js.map +1 -0
- package/dist/esm/publish-refusals.d.ts +66 -0
- package/dist/esm/publish-refusals.d.ts.map +1 -0
- package/dist/esm/publish-refusals.js +271 -0
- package/dist/esm/publish-refusals.js.map +1 -0
- package/dist/esm/realtime-generator.d.ts +63 -1
- package/dist/esm/realtime-generator.d.ts.map +1 -1
- package/dist/esm/realtime-generator.js +401 -229
- package/dist/esm/realtime-generator.js.map +1 -1
- package/dist/esm/runtime-storage-generator.d.ts +32 -1
- package/dist/esm/runtime-storage-generator.d.ts.map +1 -1
- package/dist/esm/runtime-storage-generator.js +264 -11
- package/dist/esm/runtime-storage-generator.js.map +1 -1
- package/dist/esm/security-runtime/index.d.ts +14 -0
- package/dist/esm/security-runtime/index.d.ts.map +1 -0
- package/dist/esm/security-runtime/index.js +37 -0
- package/dist/esm/security-runtime/index.js.map +1 -0
- package/dist/esm/security-runtime/security-runtime-code.d.ts +53 -0
- package/dist/esm/security-runtime/security-runtime-code.d.ts.map +1 -0
- package/dist/esm/security-runtime/security-runtime-code.js +575 -0
- package/dist/esm/security-runtime/security-runtime-code.js.map +1 -0
- package/dist/esm/security-scanner.d.ts +72 -3
- package/dist/esm/security-scanner.d.ts.map +1 -1
- package/dist/esm/security-scanner.js +217 -8
- package/dist/esm/security-scanner.js.map +1 -1
- package/dist/esm/segment-splitter.d.ts.map +1 -1
- package/dist/esm/segment-splitter.js +10 -2
- package/dist/esm/segment-splitter.js.map +1 -1
- package/dist/esm/segment-trust.d.ts +36 -0
- package/dist/esm/segment-trust.d.ts.map +1 -1
- package/dist/esm/segment-trust.js +146 -2
- package/dist/esm/segment-trust.js.map +1 -1
- package/dist/esm/self-call-headers.d.ts +31 -0
- package/dist/esm/self-call-headers.d.ts.map +1 -0
- package/dist/esm/self-call-headers.js +43 -0
- package/dist/esm/self-call-headers.js.map +1 -0
- package/dist/esm/sent-email-log/index.d.ts +7 -0
- package/dist/esm/sent-email-log/index.d.ts.map +1 -1
- package/dist/esm/sent-email-log/index.js +15 -0
- package/dist/esm/sent-email-log/index.js.map +1 -1
- package/dist/esm/sent-email-log/sent-email-log-code.d.ts +7 -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 +17 -3
- package/dist/esm/sent-email-log/sent-email-log-code.js.map +1 -1
- package/dist/esm/server-custom-node-call.d.ts +79 -0
- package/dist/esm/server-custom-node-call.d.ts.map +1 -0
- package/dist/esm/server-custom-node-call.js +278 -0
- package/dist/esm/server-custom-node-call.js.map +1 -0
- package/dist/esm/server-runtime-code.d.ts +39 -12
- package/dist/esm/server-runtime-code.d.ts.map +1 -1
- package/dist/esm/server-runtime-code.js +483 -40
- package/dist/esm/server-runtime-code.js.map +1 -1
- package/dist/esm/session-cookie-resolver.d.ts +3 -1
- package/dist/esm/session-cookie-resolver.d.ts.map +1 -1
- package/dist/esm/session-revocation-generator.d.ts +39 -0
- package/dist/esm/session-revocation-generator.d.ts.map +1 -0
- package/dist/esm/session-revocation-generator.js +172 -0
- package/dist/esm/session-revocation-generator.js.map +1 -0
- package/dist/esm/slack-message-values.d.ts +6 -0
- package/dist/esm/slack-message-values.d.ts.map +1 -0
- package/dist/esm/slack-message-values.js +68 -0
- package/dist/esm/slack-message-values.js.map +1 -0
- package/dist/esm/transactional-email-code.d.ts +11 -0
- package/dist/esm/transactional-email-code.d.ts.map +1 -1
- package/dist/esm/transactional-email-code.js +28 -4
- package/dist/esm/transactional-email-code.js.map +1 -1
- package/dist/esm/trigger-generator.d.ts +2 -0
- package/dist/esm/trigger-generator.d.ts.map +1 -1
- package/dist/esm/trigger-generator.js +15 -3
- package/dist/esm/trigger-generator.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/visitor-step-limits.d.ts +66 -0
- package/dist/esm/visitor-step-limits.d.ts.map +1 -0
- package/dist/esm/visitor-step-limits.js +181 -0
- package/dist/esm/visitor-step-limits.js.map +1 -0
- package/dist/esm/webhook-generator.d.ts.map +1 -1
- package/dist/esm/webhook-generator.js +93 -15
- package/dist/esm/webhook-generator.js.map +1 -1
- package/dist/esm/webhook-signature-verification.d.ts.map +1 -1
- package/dist/esm/webhook-signature-verification.js +13 -3
- package/dist/esm/webhook-signature-verification.js.map +1 -1
- package/dist/esm/workflow-auth-generator.d.ts +4 -1
- package/dist/esm/workflow-auth-generator.d.ts.map +1 -1
- package/dist/esm/workflow-auth-generator.js +8 -3
- package/dist/esm/workflow-auth-generator.js.map +1 -1
- package/dist/esm/workflow-component-plugin.js +12 -4
- package/dist/esm/workflow-component-plugin.js.map +1 -1
- package/dist/esm/workflow-project-plugin.d.ts.map +1 -1
- package/dist/esm/workflow-project-plugin.js +306 -60
- package/dist/esm/workflow-project-plugin.js.map +1 -1
- package/dist/esm/workflow-scope.d.ts.map +1 -1
- package/dist/esm/workflow-scope.js +5 -0
- package/dist/esm/workflow-scope.js.map +1 -1
- package/package.json +4 -4
- package/src/account-delete-route-generator.ts +28 -4
- package/src/api-route-generator.ts +712 -134
- package/src/auth-generator.ts +1471 -142
- package/src/automations/activity-kicks.ts +139 -0
- package/src/automations/app-events-source.ts +117 -0
- package/src/automations/automations-project-plugin.ts +202 -0
- package/src/automations/automations-scope.ts +196 -0
- package/src/automations/dispatcher-source.ts +1072 -0
- package/src/automations/event-bus-source.ts +428 -0
- package/src/automations/handler-module-generator.ts +107 -0
- package/src/automations/hydrators-source.ts +647 -0
- package/src/booking-calendar-feed-route-generator.ts +8 -0
- package/src/configured-nextauth-url.ts +17 -0
- package/src/cron-request-verification.ts +55 -5
- package/src/data-api-route-generator.ts +780 -43
- package/src/ecommerce/parameterized-stock-chain.ts +52 -5
- package/src/ecommerce/place-order-guards.ts +785 -0
- package/src/ecommerce-customhandler-rewriter.ts +55 -2
- package/src/executor-generator.ts +372 -60
- package/src/graph-utils.ts +33 -0
- package/src/index.ts +70 -0
- package/src/invoice/api-routes-code.ts +20 -7
- package/src/invoice/index.ts +11 -6
- package/src/invoice/invoice-assembly-code.ts +8 -3
- package/src/invoice/pdf-generator-code.ts +2 -1
- package/src/invoice/pdf-service-client-code.ts +15 -7
- package/src/newsletter/admin-route-code.ts +319 -0
- package/src/newsletter/helper-code.ts +748 -0
- package/src/newsletter/newsletter-scope.ts +116 -0
- package/src/newsletter/project-plugin.ts +119 -0
- package/src/newsletter/routes-code.ts +186 -0
- package/src/nodes/account/account-compare-passwords.ts +17 -6
- package/src/nodes/account/account-delete-current.ts +1 -1
- package/src/nodes/account/account-get-current.ts +1 -1
- package/src/nodes/account/account-hash-password.ts +19 -3
- package/src/nodes/account/account-login.ts +24 -7
- package/src/nodes/account/account-logout.ts +1 -1
- package/src/nodes/account/account-refresh-session.ts +1 -1
- package/src/nodes/account/account-request-password-reset.ts +47 -0
- package/src/nodes/account/account-reset-password.ts +45 -0
- package/src/nodes/account/account-signup.ts +86 -20
- package/src/nodes/account/account-social-login.ts +1 -1
- package/src/nodes/ai/ai-custom-prompt.ts +25 -6
- package/src/nodes/ai/ai-detect-language.ts +25 -6
- package/src/nodes/ai/ai-generate-text-embedding.ts +16 -3
- package/src/nodes/ai/ai-provider-utils-sources.generated.ts +2 -2
- package/src/nodes/ai/ai-provider-utils.ts +135 -10
- package/src/nodes/ai/ai-select-database-data.ts +8 -3
- package/src/nodes/ai/ai-sentiment-analysis.ts +25 -6
- package/src/nodes/ai/ai-summarization.ts +25 -6
- package/src/nodes/ai/ai-text-classifier.ts +25 -6
- package/src/nodes/ai/ai-text-transform.ts +25 -6
- package/src/nodes/analytics/analytics-track-outcome.ts +111 -0
- package/src/nodes/cart/cart-price-order.ts +200 -2
- package/src/nodes/cost-bearing-node-types.ts +45 -0
- package/src/nodes/data/data-select.ts +11 -2
- package/src/nodes/email/email-mailersend.ts +16 -8
- package/src/nodes/email/email-mailgun.ts +17 -12
- package/src/nodes/email/email-postmark.ts +17 -12
- package/src/nodes/email/email-resend.ts +17 -12
- package/src/nodes/email/email-sendgrid.ts +17 -12
- package/src/nodes/email/html-escape-code.ts +21 -0
- package/src/nodes/email/message-trust.ts +198 -0
- package/src/nodes/email/outbound-message-guard.ts +572 -0
- package/src/nodes/email/trusted-html-code.ts +49 -0
- package/src/nodes/general/general-custom-js.ts +46 -7
- package/src/nodes/general/general-http-request.ts +449 -46
- package/src/nodes/general/general-rate-limiter.ts +54 -81
- package/src/nodes/general/general-wait.ts +80 -0
- package/src/nodes/general/visitor-request.ts +79 -0
- package/src/nodes/index.ts +12 -0
- package/src/nodes/integrations/integration-slack.ts +21 -6
- package/src/nodes/newsletter/newsletter-confirm.ts +44 -0
- package/src/nodes/newsletter/newsletter-subscribe.ts +78 -0
- package/src/nodes/newsletter/newsletter-unsubscribe.ts +43 -0
- package/src/nodes/realtime/realtime-join-channel.ts +5 -4
- package/src/nodes/realtime/realtime-send-channel-event.ts +13 -2
- package/src/nodes/realtime/realtime-send-channel-message.ts +13 -2
- package/src/nodes/sms/sms-infobip.ts +14 -4
- package/src/nodes/sms/sms-smsapi.ts +14 -4
- package/src/nodes/sms/sms-textmagic.ts +14 -4
- package/src/nodes/sms/sms-twilio.ts +14 -4
- package/src/nodes/types.ts +9 -1
- package/src/nodes/utility/utility-similarity-scoring.ts +33 -12
- package/src/page-access-guard-generator.ts +154 -0
- package/src/password-reset-route-generator.ts +531 -0
- package/src/payments/payment-core-code.ts +12 -7
- package/src/project-code-scanner.ts +98 -0
- package/src/public-step-guards.ts +448 -0
- package/src/publish-refusals.ts +459 -0
- package/src/realtime-generator.ts +457 -234
- package/src/runtime-storage-generator.ts +270 -11
- package/src/security-runtime/index.ts +53 -0
- package/src/security-runtime/security-runtime-code.ts +579 -0
- package/src/security-scanner.ts +253 -10
- package/src/segment-splitter.ts +10 -2
- package/src/segment-trust.ts +205 -2
- package/src/self-call-headers.ts +46 -0
- package/src/sent-email-log/index.ts +16 -0
- package/src/sent-email-log/sent-email-log-code.ts +30 -4
- package/src/server-custom-node-call.ts +331 -0
- package/src/server-runtime-code.ts +488 -40
- package/src/session-revocation-generator.ts +177 -0
- package/src/slack-message-values.ts +84 -0
- package/src/transactional-email-code.ts +30 -4
- package/src/trigger-generator.ts +19 -3
- package/src/visitor-step-limits.ts +228 -0
- package/src/webhook-generator.ts +94 -14
- package/src/webhook-signature-verification.ts +13 -3
- package/src/workflow-auth-generator.ts +9 -4
- package/src/workflow-component-plugin.ts +14 -4
- package/src/workflow-project-plugin.ts +374 -61
- package/src/workflow-scope.ts +6 -0
|
@@ -0,0 +1,1008 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateAutomationsUnavailableRouteCode = exports.generateAutomationDispatchRouteCode = exports.generateAutomationDispatcherCode = exports.AUTOMATION_DELIVERY_GUARANTEE = exports.dueWaitsSql = exports.retriableEventsSql = exports.staleEventSql = void 0;
|
|
4
|
+
const cron_request_verification_1 = require("../cron-request-verification");
|
|
5
|
+
const automations_scope_1 = require("./automations-scope");
|
|
6
|
+
/** The largest body the dispatch route reads (64 KB); a larger one is refused (413). */
|
|
7
|
+
const DISPATCH_MAX_BODY_BYTES = 64 * 1024;
|
|
8
|
+
/**
|
|
9
|
+
* The queue worker (`lib/automations/dispatcher.js`) and the route that runs
|
|
10
|
+
* it for the app itself (`pages/api/automations/dispatch.js`). The table is
|
|
11
|
+
* the queue: a pass claims due events with FOR UPDATE SKIP LOCKED, so two
|
|
12
|
+
* dispatchers never take the same event, and a delivery row per (event,
|
|
13
|
+
* automation) — unique — keeps a handler from running twice at once.
|
|
14
|
+
*/
|
|
15
|
+
const { batchSize, maxAttempts, maxAgeDays, handlerTimeoutMs, passDeadlineMs, staleClaimMinutes, routeMaxDurationSeconds, } = automations_scope_1.AUTOMATION_QUEUE_LIMITS;
|
|
16
|
+
const STALE = `interval '${staleClaimMinutes} minutes'`;
|
|
17
|
+
const EVENT_COLUMNS = 'e.id, e.event_type, e.order_id, e.entity_type, e.entity_id, e.payload, e.actor, e.actor_type, e.status, e.attempts, e.claimed_at, e.created_at';
|
|
18
|
+
// A `pending` event is left over by a dispatcher that stopped once nothing
|
|
19
|
+
// has touched it for the stale window: neither its claim nor the latest start
|
|
20
|
+
// of one of its deliveries. Its running deliveries are then stale too, so the
|
|
21
|
+
// takeover never has to wait a second window for them. An event with a run
|
|
22
|
+
// parked at a Wait (a `waiting` delivery) is pending on purpose and never
|
|
23
|
+
// stale: the resume settles it. Only a run that can resume holds it: one of
|
|
24
|
+
// an automation of this build that is on (a switched-off, deleted or
|
|
25
|
+
// unpublished one's stays parked, and never resumes while it is so).
|
|
26
|
+
// `workflowIds` is the statement's parameter holding this build's workflow
|
|
27
|
+
// ids. The fragments below are shared with the activity kick's due check
|
|
28
|
+
// (activity-kicks.ts), so the kick wakes a pass exactly when it has work.
|
|
29
|
+
const staleEventSql = (workflowIds) => '(GREATEST(COALESCE(e.claimed_at, e.created_at), ' +
|
|
30
|
+
'COALESCE((SELECT max(d.started_at) FROM teleport_event_deliveries d WHERE d.event_id = e.id), e.created_at)) ' +
|
|
31
|
+
`< now() - ${STALE} ` +
|
|
32
|
+
"AND NOT EXISTS (SELECT 1 FROM teleport_event_deliveries d WHERE d.event_id = e.id AND d.status = 'waiting' " +
|
|
33
|
+
`AND d.workflow_id = ANY(${workflowIds}::text[]) ` +
|
|
34
|
+
'AND EXISTS (SELECT 1 FROM teleport_automations a WHERE a.workflow_id = d.workflow_id AND a.enabled)))';
|
|
35
|
+
exports.staleEventSql = staleEventSql;
|
|
36
|
+
const STALE_EVENT = (0, exports.staleEventSql)('$2');
|
|
37
|
+
// An automation of this build of the event's type, on, and on when it happened.
|
|
38
|
+
const enabledForEventSql = (workflowIds) => 'EXISTS (SELECT 1 FROM teleport_automations a WHERE a.event_type = e.event_type ' +
|
|
39
|
+
`AND a.workflow_id = ANY(${workflowIds}::text[]) AND a.enabled AND COALESCE(a.enabled_at, a.created_at) <= e.created_at)`;
|
|
40
|
+
/**
|
|
41
|
+
* The events a pass takes besides the new ones: a failed one, and a stale
|
|
42
|
+
* `pending` one (below the attempt limit, of an automation that is on; or
|
|
43
|
+
* past it, only to be settled).
|
|
44
|
+
*/
|
|
45
|
+
const retriableEventsSql = (eventTypes, workflowIds) => `e.event_type = ANY(${eventTypes}::text[]) ` +
|
|
46
|
+
`AND ((e.attempts < ${maxAttempts} ` +
|
|
47
|
+
`AND (e.status = 'failed' OR (e.status = 'pending' AND ${(0, exports.staleEventSql)(workflowIds)})) ` +
|
|
48
|
+
`AND ${enabledForEventSql(workflowIds)}) ` +
|
|
49
|
+
`OR (e.status = 'pending' AND e.attempts >= ${maxAttempts} AND ${(0, exports.staleEventSql)(workflowIds)}))`;
|
|
50
|
+
exports.retriableEventsSql = retriableEventsSql;
|
|
51
|
+
/**
|
|
52
|
+
* The Waits a pass resumes: due ones of an automation that is on (a
|
|
53
|
+
* switched-off one's stay parked), and those whose resume was left running
|
|
54
|
+
* for longer than the stale window.
|
|
55
|
+
*/
|
|
56
|
+
const dueWaitsSql = (workflowIds) => `w.workflow_id = ANY(${workflowIds}::text[]) ` +
|
|
57
|
+
"AND ((w.status = 'waiting' AND w.run_at <= now()) " +
|
|
58
|
+
`OR (w.status = 'resuming' AND w.run_at < now() - ${STALE})) ` +
|
|
59
|
+
'AND EXISTS (SELECT 1 FROM teleport_automations a WHERE a.workflow_id = w.workflow_id AND a.enabled)';
|
|
60
|
+
exports.dueWaitsSql = dueWaitsSql;
|
|
61
|
+
// Due, below the attempt limit, of a type with an automation of this build
|
|
62
|
+
// that was on when it happened: a new event within the window, a failed one
|
|
63
|
+
// whatever its age, and a stale `pending` one. A stale `pending` event that
|
|
64
|
+
// used its last attempt is claimed too, only to be settled as failed. New
|
|
65
|
+
// events go first.
|
|
66
|
+
const CLAIM_EVENTS_SQL = `SELECT ${EVENT_COLUMNS} FROM teleport_events e ` +
|
|
67
|
+
'WHERE e.event_type = ANY($1::text[]) ' +
|
|
68
|
+
`AND ((e.attempts < ${maxAttempts} ` +
|
|
69
|
+
`AND ((e.status = 'recorded' AND e.created_at > now() - interval '${maxAgeDays} days') ` +
|
|
70
|
+
"OR e.status = 'failed' " +
|
|
71
|
+
`OR (e.status = 'pending' AND ${STALE_EVENT})) ` +
|
|
72
|
+
`AND ${enabledForEventSql('$2')}) ` +
|
|
73
|
+
`OR (e.status = 'pending' AND e.attempts >= ${maxAttempts} AND ${STALE_EVENT})) ` +
|
|
74
|
+
"ORDER BY CASE WHEN e.status = 'recorded' THEN 0 ELSE 1 END, e.created_at " +
|
|
75
|
+
`LIMIT ${batchSize} FOR UPDATE SKIP LOCKED`;
|
|
76
|
+
// claimed_at is the claim's token (to the millisecond, so it reads back
|
|
77
|
+
// exactly): every later write of this claim names it, so a run that froze and
|
|
78
|
+
// woke after a takeover writes nothing over the dispatcher that took over.
|
|
79
|
+
const MARK_PENDING_SQL = "UPDATE teleport_events SET status = 'pending', claimed_at = date_trunc('milliseconds', now()) " +
|
|
80
|
+
'WHERE id = ANY($1::uuid[]) RETURNING id, claimed_at';
|
|
81
|
+
const CLAIM_GUARD = "status = 'pending' AND claimed_at = ";
|
|
82
|
+
// An attempt is counted when a handler of the event actually starts.
|
|
83
|
+
const COUNT_ATTEMPT_SQL = `UPDATE teleport_events SET attempts = attempts + 1 WHERE id = $1 AND ${CLAIM_GUARD}$2`;
|
|
84
|
+
// Read when the event is delivered, so an automation switched off since the
|
|
85
|
+
// claim is skipped.
|
|
86
|
+
const EVENT_AUTOMATIONS_SQL = 'SELECT a.workflow_id FROM teleport_automations a JOIN teleport_events e ON e.event_type = a.event_type ' +
|
|
87
|
+
'WHERE e.id = $1 AND a.workflow_id = ANY($2::text[]) AND a.enabled ' +
|
|
88
|
+
'AND COALESCE(a.enabled_at, a.created_at) <= e.created_at';
|
|
89
|
+
// The (event, automation) pair is unique: a pair delivered, or running and
|
|
90
|
+
// not yet stale, returns no row and is left alone; a failed one (or one whose
|
|
91
|
+
// run was left running for longer than the stale window) is taken again.
|
|
92
|
+
const CLAIM_DELIVERY_SQL = 'INSERT INTO teleport_event_deliveries AS d (event_id, workflow_id, status, attempts, started_at) ' +
|
|
93
|
+
"VALUES ($1, $2, 'running', 1, now()) " +
|
|
94
|
+
"ON CONFLICT (event_id, workflow_id) DO UPDATE SET status = 'running', attempts = d.attempts + 1, " +
|
|
95
|
+
'started_at = now(), finished_at = NULL, error = NULL ' +
|
|
96
|
+
`WHERE d.status = 'failed' OR (d.status = 'running' AND d.started_at < now() - ${STALE}) ` +
|
|
97
|
+
'RETURNING d.id, d.attempts';
|
|
98
|
+
// A run's outcome, written only while that same claim (its attempt number)
|
|
99
|
+
// still holds the row: the run awaited, and one the dispatcher stopped
|
|
100
|
+
// waiting for, alike.
|
|
101
|
+
// An automation that did not run because the event has no record behind it:
|
|
102
|
+
// its delivery says why (a delivered or running one is left alone).
|
|
103
|
+
const REFUSE_DELIVERY_SQL = 'INSERT INTO teleport_event_deliveries AS d (event_id, workflow_id, status, attempts, error, started_at, finished_at) ' +
|
|
104
|
+
"VALUES ($1, $2, 'failed', 0, $3, now(), now()) " +
|
|
105
|
+
"ON CONFLICT (event_id, workflow_id) DO UPDATE SET status = 'failed', error = $3, finished_at = now() " +
|
|
106
|
+
"WHERE d.status = 'failed'";
|
|
107
|
+
const FINISH_DELIVERY_SQL = 'UPDATE teleport_event_deliveries SET status = $2, error = $3, finished_at = now() ' +
|
|
108
|
+
"WHERE id = $1 AND status = 'running' AND attempts = $4";
|
|
109
|
+
// An event that used its last attempt: the runs it left running are over.
|
|
110
|
+
const TIME_OUT_DELIVERIES_SQL = "UPDATE teleport_event_deliveries SET status = 'failed', error = 'Timed out', finished_at = now() " +
|
|
111
|
+
`WHERE event_id = $1 AND status = 'running' AND started_at < now() - ${STALE}`;
|
|
112
|
+
// A resume's outcome, in ONE statement: the Wait is settled ('done' or
|
|
113
|
+
// 'failed') only while this claim (its run_at token) still holds it, and the
|
|
114
|
+
// run's delivery takes the resumed run's outcome ('delivered', 'failed', or
|
|
115
|
+
// 'waiting' again at a later Wait) only when it was. Two statements could be
|
|
116
|
+
// cut apart by the process dying between them, leaving the Wait done, the
|
|
117
|
+
// delivery waiting and the event pending for good. The delivery's started_at
|
|
118
|
+
// becomes the resume's, so the History's duration is the resumed part; its
|
|
119
|
+
// attempts stay those of the run. Its row count says whether the claim held
|
|
120
|
+
// (and the delivery was still waiting for it).
|
|
121
|
+
const FINISH_RESUME_SQL = 'WITH w AS (UPDATE teleport_automation_waits SET status = $1 ' +
|
|
122
|
+
"WHERE id = $2 AND status = 'resuming' AND run_at = $3 RETURNING id) " +
|
|
123
|
+
'UPDATE teleport_event_deliveries SET status = $4, error = $5, started_at = $6, finished_at = now() ' +
|
|
124
|
+
"WHERE event_id = $7 AND workflow_id = $8 AND status = 'waiting' AND EXISTS (SELECT 1 FROM w)";
|
|
125
|
+
const EVENT_DELIVERIES_SQL = 'SELECT workflow_id, status FROM teleport_event_deliveries WHERE event_id = $1';
|
|
126
|
+
// Settles (or hands back) the event of this claim.
|
|
127
|
+
const FINISH_EVENT_SQL = `UPDATE teleport_events SET status = $2 WHERE id = $1 AND ${CLAIM_GUARD}$3`;
|
|
128
|
+
// The ledger itself failed for this event (not a handler): retried, counted.
|
|
129
|
+
const FAIL_EVENT_SQL = "UPDATE teleport_events SET status = 'failed', attempts = attempts + 1 " +
|
|
130
|
+
`WHERE id = $1 AND ${CLAIM_GUARD}$2`;
|
|
131
|
+
// A test is recorded already settled, so the queue never claims it.
|
|
132
|
+
const INSERT_TEST_EVENT_SQL = 'INSERT INTO teleport_events (event_type, dedupe_key, payload, actor, actor_type, status) ' +
|
|
133
|
+
"VALUES ($1, $2, $3, $4, $5, 'test') RETURNING id, created_at";
|
|
134
|
+
const START_TEST_DELIVERY_SQL = 'INSERT INTO teleport_event_deliveries (event_id, workflow_id, status, attempts, started_at) ' +
|
|
135
|
+
"VALUES ($1, $2, 'running', 1, now()) RETURNING id, attempts";
|
|
136
|
+
// The Waits due (dueWaitsSql), oldest first.
|
|
137
|
+
const CLAIM_WAITS_SQL = 'SELECT w.id, w.event_id, w.workflow_id, w.resume_node_id, w.context FROM teleport_automation_waits w ' +
|
|
138
|
+
`WHERE ${(0, exports.dueWaitsSql)('$1')} ` +
|
|
139
|
+
`ORDER BY w.run_at LIMIT ${batchSize} FOR UPDATE SKIP LOCKED`;
|
|
140
|
+
// run_at becomes the claim time (to the millisecond, so it reads back exactly).
|
|
141
|
+
const MARK_WAITS_SQL = "UPDATE teleport_automation_waits SET status = 'resuming', run_at = date_trunc('milliseconds', now()) " +
|
|
142
|
+
'WHERE id = ANY($1::int[]) RETURNING id, run_at';
|
|
143
|
+
// Hands a claimed Wait back, only while that same claim (its run_at token) holds it.
|
|
144
|
+
const RELEASE_WAIT_SQL = "UPDATE teleport_automation_waits SET status = 'waiting' WHERE id = $1 AND status = 'resuming' AND run_at = $2";
|
|
145
|
+
// Where a retried run picks up: the latest Wait of this (event, automation)
|
|
146
|
+
// whose resumed part failed. Everything before it ran already (its emails were
|
|
147
|
+
// sent), so the retry starts at the step after it, with the context it stored.
|
|
148
|
+
const FAILED_WAIT_SQL = 'SELECT id, resume_node_id, context FROM teleport_automation_waits ' +
|
|
149
|
+
"WHERE event_id = $1 AND workflow_id = $2 AND status = 'failed' ORDER BY id DESC LIMIT 1";
|
|
150
|
+
// A retry that got past its Wait (to the end, or to a later Wait): that Wait is done.
|
|
151
|
+
const SETTLE_FAILED_WAIT_SQL = "UPDATE teleport_automation_waits SET status = 'done' WHERE id = $1 AND status = 'failed'";
|
|
152
|
+
const EVENT_BY_ID_SQL = `SELECT ${EVENT_COLUMNS} FROM teleport_events e WHERE e.id = $1`;
|
|
153
|
+
const ENTITY_LABELS = {
|
|
154
|
+
giftCards: 'order',
|
|
155
|
+
giftCard: 'order',
|
|
156
|
+
cart: 'abandoned cart',
|
|
157
|
+
waitlist: 'waitlist entry',
|
|
158
|
+
};
|
|
159
|
+
const STATEMENTS = [
|
|
160
|
+
['CLAIM_EVENTS_SQL', CLAIM_EVENTS_SQL],
|
|
161
|
+
['MARK_PENDING_SQL', MARK_PENDING_SQL],
|
|
162
|
+
['COUNT_ATTEMPT_SQL', COUNT_ATTEMPT_SQL],
|
|
163
|
+
['EVENT_AUTOMATIONS_SQL', EVENT_AUTOMATIONS_SQL],
|
|
164
|
+
['CLAIM_DELIVERY_SQL', CLAIM_DELIVERY_SQL],
|
|
165
|
+
['REFUSE_DELIVERY_SQL', REFUSE_DELIVERY_SQL],
|
|
166
|
+
['FINISH_DELIVERY_SQL', FINISH_DELIVERY_SQL],
|
|
167
|
+
['TIME_OUT_DELIVERIES_SQL', TIME_OUT_DELIVERIES_SQL],
|
|
168
|
+
['FINISH_RESUME_SQL', FINISH_RESUME_SQL],
|
|
169
|
+
['EVENT_DELIVERIES_SQL', EVENT_DELIVERIES_SQL],
|
|
170
|
+
['FINISH_EVENT_SQL', FINISH_EVENT_SQL],
|
|
171
|
+
['FAIL_EVENT_SQL', FAIL_EVENT_SQL],
|
|
172
|
+
['INSERT_TEST_EVENT_SQL', INSERT_TEST_EVENT_SQL],
|
|
173
|
+
['START_TEST_DELIVERY_SQL', START_TEST_DELIVERY_SQL],
|
|
174
|
+
['CLAIM_WAITS_SQL', CLAIM_WAITS_SQL],
|
|
175
|
+
['MARK_WAITS_SQL', MARK_WAITS_SQL],
|
|
176
|
+
['RELEASE_WAIT_SQL', RELEASE_WAIT_SQL],
|
|
177
|
+
['FAILED_WAIT_SQL', FAILED_WAIT_SQL],
|
|
178
|
+
['SETTLE_FAILED_WAIT_SQL', SETTLE_FAILED_WAIT_SQL],
|
|
179
|
+
['EVENT_BY_ID_SQL', EVENT_BY_ID_SQL],
|
|
180
|
+
];
|
|
181
|
+
/**
|
|
182
|
+
* The delivery guarantee, worded for the editor's History drawer:
|
|
183
|
+
*
|
|
184
|
+
* Every automation runs at least once for each event of its type recorded
|
|
185
|
+
* while it is on, and normally exactly once. A run that fails is retried the
|
|
186
|
+
* next time the site is active, up to 5 attempts per event. A run that is
|
|
187
|
+
* still going after 25 seconds is left to finish; if it never reports back
|
|
188
|
+
* (its server stopped), it is run again 15 minutes later — so an automation
|
|
189
|
+
* that is slow or interrupted can run twice for the same event. A run that
|
|
190
|
+
* fails after a Wait is retried from the step after that Wait. A new event is
|
|
191
|
+
* picked up within 3 days; a Wait resumes the next time the site is active
|
|
192
|
+
* after its time has passed.
|
|
193
|
+
*/
|
|
194
|
+
exports.AUTOMATION_DELIVERY_GUARANTEE = 'Every automation runs at least once for each event of its type recorded while it is on, and normally exactly once. ' +
|
|
195
|
+
'A run that fails is retried the next time the site is active, up to 5 attempts per event. ' +
|
|
196
|
+
'A run that is still going after 25 seconds is left to finish; if it never reports back, it is run again 15 minutes later, ' +
|
|
197
|
+
'so an automation that is slow or interrupted can run twice for the same event. ' +
|
|
198
|
+
'A run that fails after a Wait is retried from the step after that Wait: the steps before it do not run again. ' +
|
|
199
|
+
'A new event is picked up within 3 days; a Wait resumes the next time the site is active after its time has passed.';
|
|
200
|
+
/**
|
|
201
|
+
* `lib/automations/dispatcher.js`. `entityByType` maps every event type of
|
|
202
|
+
* the registry to its envelope key, `envelopeKeysByType` to its catalog blocks
|
|
203
|
+
* (null: keep the payload whole); `hydratedEntities` are the entities a
|
|
204
|
+
* `hydrate/<entity>.js` module was generated for.
|
|
205
|
+
*/
|
|
206
|
+
const generateAutomationDispatcherCode = (options) => {
|
|
207
|
+
const hydrators = options.hydratedEntities
|
|
208
|
+
.map((entity) => ` ${JSON.stringify(entity)}: require('./hydrate/${entity}.js').hydrate,`)
|
|
209
|
+
.join('\n');
|
|
210
|
+
return `'use strict';
|
|
211
|
+
/**
|
|
212
|
+
* Automations: the queue worker (generated). teleport_events is the queue;
|
|
213
|
+
* every pass claims due events, delivers each to the automations of its type
|
|
214
|
+
* that are on, records every delivery, marks the event from its delivery
|
|
215
|
+
* rows, then resumes the Waits that are due. Runs in-process, one handler at
|
|
216
|
+
* a time, and starts nothing once its time budget is spent.
|
|
217
|
+
*
|
|
218
|
+
* At least once: ${exports.AUTOMATION_DELIVERY_GUARANTEE}
|
|
219
|
+
*/
|
|
220
|
+
var crypto = require('crypto');
|
|
221
|
+
var store = require('./store');
|
|
222
|
+
var registry = require('./registry');
|
|
223
|
+
|
|
224
|
+
var HANDLER_TIMEOUT_MS = ${handlerTimeoutMs};
|
|
225
|
+
var PASS_DEADLINE_MS = ${passDeadlineMs};
|
|
226
|
+
var MAX_ATTEMPTS = ${maxAttempts};
|
|
227
|
+
|
|
228
|
+
var ENTITY_BY_TYPE = ${JSON.stringify(options.entityByType, null, 2)};
|
|
229
|
+
|
|
230
|
+
var ENVELOPE_KEYS = ${JSON.stringify(options.envelopeKeysByType, null, 2)};
|
|
231
|
+
|
|
232
|
+
// How a refusal names a missing record ("No such order").
|
|
233
|
+
var ENTITY_LABELS = ${JSON.stringify(ENTITY_LABELS, null, 2)};
|
|
234
|
+
|
|
235
|
+
var HYDRATORS = {
|
|
236
|
+
${hydrators}
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
${STATEMENTS.map(([name, text]) => `var ${name} = ${JSON.stringify(text)};`).join('\n')}
|
|
240
|
+
|
|
241
|
+
var TIMED_OUT = {};
|
|
242
|
+
|
|
243
|
+
function own(map, key) {
|
|
244
|
+
return Object.prototype.hasOwnProperty.call(map, key) ? map[key] : null;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
function registryTypes() {
|
|
248
|
+
return Object.keys(registry);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
function registryWorkflowIds() {
|
|
252
|
+
var ids = [];
|
|
253
|
+
registryTypes().forEach(function (type) {
|
|
254
|
+
(registry[type] || []).forEach(function (entry) { ids.push(entry.workflowId); });
|
|
255
|
+
});
|
|
256
|
+
return ids;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
function findAutomation(workflowId) {
|
|
260
|
+
var types = registryTypes();
|
|
261
|
+
for (var i = 0; i < types.length; i++) {
|
|
262
|
+
var entries = registry[types[i]] || [];
|
|
263
|
+
for (var j = 0; j < entries.length; j++) {
|
|
264
|
+
if (entries[j].workflowId === workflowId) return { type: types[i], entry: entries[j] };
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return null;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Runs one handler, waiting at most timeoutMs for it. One still going then is
|
|
271
|
+
// left to finish: onLate gets its outcome when it settles.
|
|
272
|
+
async function runEntry(start, timeoutMs, onLate) {
|
|
273
|
+
var timer;
|
|
274
|
+
var running = Promise.resolve().then(start);
|
|
275
|
+
var timeout = new Promise(function (resolve) {
|
|
276
|
+
timer = setTimeout(function () { resolve(TIMED_OUT); }, timeoutMs);
|
|
277
|
+
});
|
|
278
|
+
try {
|
|
279
|
+
var value = await Promise.race([running, timeout]);
|
|
280
|
+
if (value === TIMED_OUT) {
|
|
281
|
+
running.then(function (late) { onLate(null, late); }, function (error) { onLate(error, null); });
|
|
282
|
+
return { timedOut: true };
|
|
283
|
+
}
|
|
284
|
+
return { timedOut: false, value: value };
|
|
285
|
+
} catch (error) {
|
|
286
|
+
return { timedOut: false, error: error };
|
|
287
|
+
} finally {
|
|
288
|
+
clearTimeout(timer);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// What a run's delivery records: a run that stopped at a Wait is waiting.
|
|
293
|
+
function runStatus(error, value) {
|
|
294
|
+
if (error) return 'failed';
|
|
295
|
+
return value && value.waiting === true ? 'waiting' : 'delivered';
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Whether a guarded write found its row (the claim it names still held it).
|
|
299
|
+
function wrote(result) {
|
|
300
|
+
return !!result && result.rowCount > 0;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
function lateDeliveryWriter(delivery, testRun, resumePoint) {
|
|
304
|
+
return function (error, value) {
|
|
305
|
+
var message = error ? store.errorMessage(error) : null;
|
|
306
|
+
var status = testRun ? 'test' : runStatus(error, value);
|
|
307
|
+
store.withClient(async function (client) {
|
|
308
|
+
var finished = await client.query(FINISH_DELIVERY_SQL, [delivery.id, status, message, delivery.attempts]);
|
|
309
|
+
// Taken over meanwhile: the run that took it over owns the Wait too.
|
|
310
|
+
if (resumePoint && !error && wrote(finished)) await client.query(SETTLE_FAILED_WAIT_SQL, [resumePoint.id]);
|
|
311
|
+
}).catch(function (writeError) {
|
|
312
|
+
console.error('[automations] could not record a late run: ' + store.errorMessage(writeError));
|
|
313
|
+
});
|
|
314
|
+
};
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function lateWaitWriter(wait, resumedAt) {
|
|
318
|
+
return function (error, value) {
|
|
319
|
+
if (error) console.error('[automations] ' + wait.workflow_id + ' failed after its Wait: ' + store.errorMessage(error));
|
|
320
|
+
// Nothing is written once another dispatcher took the stale resume over:
|
|
321
|
+
// that run records the outcome.
|
|
322
|
+
store.withClient(function (client) {
|
|
323
|
+
return finishResume(client, wait, runStatus(error, value), error ? store.errorMessage(error) : null, resumedAt);
|
|
324
|
+
}).catch(function (writeError) {
|
|
325
|
+
console.error('[automations] could not record a late resume: ' + store.errorMessage(writeError));
|
|
326
|
+
});
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
async function inTransaction(client, work) {
|
|
331
|
+
await client.query('BEGIN');
|
|
332
|
+
try {
|
|
333
|
+
var value = await work();
|
|
334
|
+
await client.query('COMMIT');
|
|
335
|
+
return value;
|
|
336
|
+
} catch (error) {
|
|
337
|
+
try { await client.query('ROLLBACK'); } catch (_e) {}
|
|
338
|
+
throw error;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
// The catalog blocks of the type out of source (an envelope or a payload):
|
|
343
|
+
// everything but event and actor when the catalog does not describe the type.
|
|
344
|
+
function envelopeBlocks(type, source) {
|
|
345
|
+
var keys = own(ENVELOPE_KEYS, type);
|
|
346
|
+
var blocks = {};
|
|
347
|
+
Object.keys(source || {}).forEach(function (key) {
|
|
348
|
+
if (key === 'event' || key === 'actor' || key === '__test') return;
|
|
349
|
+
if (keys && keys.indexOf(key) === -1) return;
|
|
350
|
+
blocks[key] = source[key];
|
|
351
|
+
});
|
|
352
|
+
return blocks;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
// The person a record names: an order's or a booking's customer, an
|
|
356
|
+
// account's or a subscriber's address, a review's author, a waitlist entry.
|
|
357
|
+
function entityEmail(block) {
|
|
358
|
+
if (!store.isPlainObject(block)) return null;
|
|
359
|
+
if (store.isPlainObject(block.customer) && block.customer.email) return String(block.customer.email);
|
|
360
|
+
if (store.isPlainObject(block.entry) && block.entry.email) return String(block.entry.email);
|
|
361
|
+
if (block.email) return String(block.email);
|
|
362
|
+
if (block.authorEmail) return String(block.authorEmail);
|
|
363
|
+
return null;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// Who caused it. For an event with a record, the address is the record's
|
|
367
|
+
// own: the ledger row (and its actor) can be written by a caller, the record
|
|
368
|
+
// cannot. The recorded actor is used only when the record names nobody.
|
|
369
|
+
function actorOf(row, envelope, entity, hydrated) {
|
|
370
|
+
var recorded = typeof row.actor === 'string' && row.actor.indexOf('@') !== -1 ? row.actor : null;
|
|
371
|
+
var recordEmail = hydrated ? entityEmail(envelope[entity]) : null;
|
|
372
|
+
return { type: row.actor_type || 'system', email: recordEmail || recorded };
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
// top laid over base, one level deep. A key top could not fill (undefined or
|
|
376
|
+
// null: the record has no such value) keeps base's value when base has one.
|
|
377
|
+
function overlay(base, top) {
|
|
378
|
+
var merged = Object.assign({}, base);
|
|
379
|
+
Object.keys(top).forEach(function (key) {
|
|
380
|
+
var value = top[key];
|
|
381
|
+
if (value === undefined) return;
|
|
382
|
+
if (value === null && merged[key] !== undefined && merged[key] !== null) return;
|
|
383
|
+
merged[key] = value;
|
|
384
|
+
});
|
|
385
|
+
return merged;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
function refusal(message) {
|
|
389
|
+
var error = new Error(message);
|
|
390
|
+
error.refusal = true;
|
|
391
|
+
return error;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
// The envelope every handler receives: { event, actor, <entity>, ... }. The
|
|
395
|
+
// record is read afresh and is the truth: laid OVER what the ledger row
|
|
396
|
+
// recorded (a caller could have written that row), whose other keys, and the
|
|
397
|
+
// values the record has none for, are kept.
|
|
398
|
+
// An event whose record is not there is refused ("No such <entity>"): the
|
|
399
|
+
// automations never act on a row nothing in the database stands behind.
|
|
400
|
+
// A read that fails (other than a table or column the project lacks) throws:
|
|
401
|
+
// the event is retried rather than delivered without its record.
|
|
402
|
+
async function buildEnvelope(client, row, context) {
|
|
403
|
+
var payload = store.parseJson(row.payload) || {};
|
|
404
|
+
var entity = own(ENTITY_BY_TYPE, row.event_type);
|
|
405
|
+
var hydrate = entity ? own(HYDRATORS, entity) : null;
|
|
406
|
+
var envelope = {
|
|
407
|
+
event: {
|
|
408
|
+
id: String(row.id),
|
|
409
|
+
type: row.event_type,
|
|
410
|
+
version: 1,
|
|
411
|
+
occurredAt: store.toIso(row.created_at),
|
|
412
|
+
test: false,
|
|
413
|
+
},
|
|
414
|
+
};
|
|
415
|
+
if (hydrate) {
|
|
416
|
+
Object.assign(envelope, (await hydrate(client, row, payload, { baseUrl: context.baseUrl })) || {});
|
|
417
|
+
if (!store.isPlainObject(envelope[entity]) && !Array.isArray(envelope[entity])) {
|
|
418
|
+
throw refusal('No such ' + (own(ENTITY_LABELS, entity) || entity));
|
|
419
|
+
}
|
|
420
|
+
}
|
|
421
|
+
var blocks = envelopeBlocks(row.event_type, payload);
|
|
422
|
+
Object.keys(blocks).forEach(function (key) {
|
|
423
|
+
var value = blocks[key];
|
|
424
|
+
if (store.isPlainObject(value) && store.isPlainObject(envelope[key])) {
|
|
425
|
+
envelope[key] = overlay(value, envelope[key]);
|
|
426
|
+
return;
|
|
427
|
+
}
|
|
428
|
+
// A hydrated event's flat values (an order's from / to) were read into
|
|
429
|
+
// its blocks by the hydrator.
|
|
430
|
+
if (hydrate && !store.isPlainObject(value) && !Array.isArray(value)) return;
|
|
431
|
+
if (!hydrate || !(key in envelope)) envelope[key] = value;
|
|
432
|
+
});
|
|
433
|
+
envelope.actor = actorOf(row, envelope, entity, !!hydrate);
|
|
434
|
+
return envelope;
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
async function claimEvents(client) {
|
|
438
|
+
return inTransaction(client, async function () {
|
|
439
|
+
var result = await client.query(CLAIM_EVENTS_SQL, [registryTypes(), registryWorkflowIds()]);
|
|
440
|
+
var rows = (result && result.rows) || [];
|
|
441
|
+
if (rows.length > 0) {
|
|
442
|
+
var marked = (await client.query(MARK_PENDING_SQL, [rows.map(function (row) { return row.id; })])).rows || [];
|
|
443
|
+
rows.forEach(function (row) {
|
|
444
|
+
var mark = marked.filter(function (m) { return String(m.id) === String(row.id); })[0];
|
|
445
|
+
row.claimedAt = mark ? mark.claimed_at : null;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
return rows;
|
|
449
|
+
});
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
// The automations of the event that are on now, by workflow id.
|
|
453
|
+
async function enabledAutomations(client, row) {
|
|
454
|
+
var result = await client.query(EVENT_AUTOMATIONS_SQL, [row.id, registryWorkflowIds()]);
|
|
455
|
+
return ((result && result.rows) || []).map(function (a) { return a.workflow_id; });
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
// A stale event that used its last attempt: the runs it left running are
|
|
459
|
+
// timed out, then it settles from its delivery rows like any other (a 5th
|
|
460
|
+
// attempt that finished late, successfully, ends delivered). No handler starts.
|
|
461
|
+
async function settleExhausted(client, row) {
|
|
462
|
+
await client.query(TIME_OUT_DELIVERIES_SQL, [row.id]);
|
|
463
|
+
var enabled = await enabledAutomations(client, row);
|
|
464
|
+
await client.query(FINISH_EVENT_SQL, [row.id, await settledStatus(client, row, enabled), row.claimedAt]);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// What a claimed event goes back to when none of its automations ran.
|
|
468
|
+
function releasedStatus(row) {
|
|
469
|
+
return row.status === 'recorded' ? 'recorded' : 'failed';
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
// From the delivery rows of the automations that are on: pending while one
|
|
473
|
+
// is still running, failed when one failed, delivered when all were; an
|
|
474
|
+
// event the pass ran out of time for goes back to where it was.
|
|
475
|
+
async function settledStatus(client, row, workflowIds) {
|
|
476
|
+
var rows = ((await client.query(EVENT_DELIVERIES_SQL, [row.id])).rows) || [];
|
|
477
|
+
var byWorkflow = {};
|
|
478
|
+
rows.forEach(function (delivery) { byWorkflow[delivery.workflow_id] = delivery.status; });
|
|
479
|
+
var statuses = workflowIds.map(function (id) { return byWorkflow[id] || null; });
|
|
480
|
+
// Still open: a run going on, or one parked at a Wait.
|
|
481
|
+
if (statuses.indexOf('running') !== -1 || statuses.indexOf('waiting') !== -1) return 'pending';
|
|
482
|
+
if (statuses.indexOf('failed') !== -1) return 'failed';
|
|
483
|
+
// None on any more (all switched off since the claim): nothing was delivered.
|
|
484
|
+
if (statuses.length > 0 && statuses.every(function (status) { return status === 'delivered'; })) return 'delivered';
|
|
485
|
+
return releasedStatus(row);
|
|
486
|
+
}
|
|
487
|
+
|
|
488
|
+
async function failedWaitOf(client, eventId, workflowId) {
|
|
489
|
+
var result = await client.query(FAILED_WAIT_SQL, [eventId, workflowId]);
|
|
490
|
+
return (result && result.rows && result.rows[0]) || null;
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
// A run from its first step, or, for a retry of one that failed after a
|
|
494
|
+
// Wait, from the step after that Wait with the context the Wait stored.
|
|
495
|
+
function startRun(entry, envelope, resumePoint, baseUrl) {
|
|
496
|
+
return function () {
|
|
497
|
+
if (!resumePoint) return entry.run(envelope, { __baseUrl: baseUrl }, undefined);
|
|
498
|
+
var saved = store.parseJson(resumePoint.context) || {};
|
|
499
|
+
saved.__baseUrl = baseUrl;
|
|
500
|
+
return entry.run(envelope, saved, resumePoint.resume_node_id);
|
|
501
|
+
};
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
async function deliverEvent(client, row, context) {
|
|
505
|
+
var outcome = { delivered: 0, failed: 0 };
|
|
506
|
+
var enabled = await enabledAutomations(client, row);
|
|
507
|
+
// All switched off since the claim: nothing runs, so nothing is read or
|
|
508
|
+
// counted, and the event goes back as it was.
|
|
509
|
+
if (enabled.length === 0) {
|
|
510
|
+
await client.query(FINISH_EVENT_SQL, [row.id, releasedStatus(row), row.claimedAt]);
|
|
511
|
+
return outcome;
|
|
512
|
+
}
|
|
513
|
+
var envelope;
|
|
514
|
+
try {
|
|
515
|
+
envelope = await buildEnvelope(client, row, context);
|
|
516
|
+
} catch (error) {
|
|
517
|
+
if (!error || !error.refusal) throw error;
|
|
518
|
+
// No record behind the row: no automation runs. Each one's delivery says
|
|
519
|
+
// why; the event fails like any other (retried, in case the record was
|
|
520
|
+
// not committed yet, then given up).
|
|
521
|
+
console.warn('[automations] event ' + row.id + ' refused: ' + error.message);
|
|
522
|
+
for (var r = 0; r < enabled.length; r++) {
|
|
523
|
+
await client.query(REFUSE_DELIVERY_SQL, [row.id, enabled[r], error.message]);
|
|
524
|
+
}
|
|
525
|
+
await client.query(FAIL_EVENT_SQL, [row.id, row.claimedAt]);
|
|
526
|
+
outcome.failed = enabled.length;
|
|
527
|
+
return outcome;
|
|
528
|
+
}
|
|
529
|
+
var entries = (registry[row.event_type] || []).filter(function (entry) {
|
|
530
|
+
return enabled.indexOf(entry.workflowId) !== -1;
|
|
531
|
+
});
|
|
532
|
+
var counted = false;
|
|
533
|
+
for (var i = 0; i < entries.length; i++) {
|
|
534
|
+
if (Date.now() >= context.deadline) break;
|
|
535
|
+
var entry = entries[i];
|
|
536
|
+
var claimed = await client.query(CLAIM_DELIVERY_SQL, [row.id, entry.workflowId]);
|
|
537
|
+
var delivery = claimed && claimed.rows && claimed.rows[0];
|
|
538
|
+
if (!delivery) continue;
|
|
539
|
+
if (!counted) {
|
|
540
|
+
await client.query(COUNT_ATTEMPT_SQL, [row.id, row.claimedAt]);
|
|
541
|
+
counted = true;
|
|
542
|
+
}
|
|
543
|
+
// A retry of a run that failed after a Wait resumes after that Wait. A
|
|
544
|
+
// first attempt has no earlier run to resume.
|
|
545
|
+
var resumePoint = delivery.attempts > 1 ? await failedWaitOf(client, row.id, entry.workflowId) : null;
|
|
546
|
+
// Each handler gets its own copy: one run cannot change what the next reads.
|
|
547
|
+
var ran = await runEntry(
|
|
548
|
+
startRun(entry, JSON.parse(JSON.stringify(envelope)), resumePoint, context.baseUrl),
|
|
549
|
+
context.timeoutMs,
|
|
550
|
+
lateDeliveryWriter(delivery, false, resumePoint)
|
|
551
|
+
);
|
|
552
|
+
// Still running: its row stays running, so no dispatcher starts it again
|
|
553
|
+
// until the claim is stale.
|
|
554
|
+
if (ran.timedOut) {
|
|
555
|
+
console.warn('[automations] ' + entry.name + ' is still running for event ' + row.id + '; its outcome is recorded when it ends');
|
|
556
|
+
continue;
|
|
557
|
+
}
|
|
558
|
+
var error = ran.error ? store.errorMessage(ran.error) : null;
|
|
559
|
+
if (error) console.error('[automations] ' + entry.name + ' failed for event ' + row.id + ': ' + error);
|
|
560
|
+
// A run that stopped at a Wait is not finished: its delivery waits too.
|
|
561
|
+
var finished = await client.query(FINISH_DELIVERY_SQL, [delivery.id, runStatus(ran.error, ran.value), error, delivery.attempts]);
|
|
562
|
+
if (resumePoint && !error && wrote(finished)) await client.query(SETTLE_FAILED_WAIT_SQL, [resumePoint.id]);
|
|
563
|
+
if (error) outcome.failed += 1;
|
|
564
|
+
else outcome.delivered += 1;
|
|
565
|
+
}
|
|
566
|
+
await client.query(FINISH_EVENT_SQL, [row.id, await settledStatus(client, row, enabled), row.claimedAt]);
|
|
567
|
+
return outcome;
|
|
568
|
+
}
|
|
569
|
+
|
|
570
|
+
async function resumeWaits(client, context) {
|
|
571
|
+
var workflowIds = registryWorkflowIds();
|
|
572
|
+
if (workflowIds.length === 0 || Date.now() >= context.deadline) return 0;
|
|
573
|
+
var waits = await inTransaction(client, async function () {
|
|
574
|
+
var result = await client.query(CLAIM_WAITS_SQL, [workflowIds]);
|
|
575
|
+
var rows = (result && result.rows) || [];
|
|
576
|
+
if (rows.length === 0) return rows;
|
|
577
|
+
var marked = (await client.query(MARK_WAITS_SQL, [rows.map(function (wait) { return wait.id; })])).rows || [];
|
|
578
|
+
rows.forEach(function (wait) {
|
|
579
|
+
var mark = marked.filter(function (m) { return m.id === wait.id; })[0];
|
|
580
|
+
wait.claimedRunAt = mark ? mark.run_at : null;
|
|
581
|
+
});
|
|
582
|
+
return rows;
|
|
583
|
+
});
|
|
584
|
+
var resumed = 0;
|
|
585
|
+
for (var i = 0; i < waits.length; i++) {
|
|
586
|
+
var wait = waits[i];
|
|
587
|
+
if (Date.now() >= context.deadline) {
|
|
588
|
+
await client.query(RELEASE_WAIT_SQL, [wait.id, wait.claimedRunAt]);
|
|
589
|
+
continue;
|
|
590
|
+
}
|
|
591
|
+
var found = findAutomation(wait.workflow_id);
|
|
592
|
+
var envelope = null;
|
|
593
|
+
var eventRow = null;
|
|
594
|
+
var resumedAt = new Date();
|
|
595
|
+
try {
|
|
596
|
+
eventRow = ((await client.query(EVENT_BY_ID_SQL, [wait.event_id])).rows || [])[0] || null;
|
|
597
|
+
envelope = eventRow ? await buildEnvelope(client, eventRow, context) : null;
|
|
598
|
+
} catch (error) {
|
|
599
|
+
// Its record is gone: the parked run cannot go on.
|
|
600
|
+
if (error && error.refusal) {
|
|
601
|
+
console.warn('[automations] a Wait of ' + wait.workflow_id + ' cannot resume: ' + error.message);
|
|
602
|
+
await finishResumedRun(client, wait, eventRow, 'failed', error.message, resumedAt);
|
|
603
|
+
continue;
|
|
604
|
+
}
|
|
605
|
+
// The ledger, not the automation, failed: the Wait is resumed at the next kick.
|
|
606
|
+
console.error('[automations] could not read the event of a Wait: ' + store.errorMessage(error));
|
|
607
|
+
await client.query(RELEASE_WAIT_SQL, [wait.id, wait.claimedRunAt]);
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
var saved = store.parseJson(wait.context) || {};
|
|
611
|
+
saved.__baseUrl = context.baseUrl;
|
|
612
|
+
var ran = await runEntry(function () {
|
|
613
|
+
if (!found) throw new Error('This automation is no longer published');
|
|
614
|
+
return found.entry.run(envelope, saved, wait.resume_node_id);
|
|
615
|
+
}, context.timeoutMs, lateWaitWriter(wait, resumedAt));
|
|
616
|
+
if (ran.timedOut) continue;
|
|
617
|
+
if (ran.error) {
|
|
618
|
+
console.error('[automations] could not resume ' + wait.workflow_id + ' after its Wait: ' + store.errorMessage(ran.error));
|
|
619
|
+
} else {
|
|
620
|
+
resumed += 1;
|
|
621
|
+
}
|
|
622
|
+
await finishResumedRun(
|
|
623
|
+
client,
|
|
624
|
+
wait,
|
|
625
|
+
eventRow,
|
|
626
|
+
runStatus(ran.error, ran.value),
|
|
627
|
+
ran.error ? store.errorMessage(ran.error) : null,
|
|
628
|
+
resumedAt
|
|
629
|
+
);
|
|
630
|
+
}
|
|
631
|
+
return resumed;
|
|
632
|
+
}
|
|
633
|
+
|
|
634
|
+
// Settles the Wait and records the resumed run's outcome on its delivery, in
|
|
635
|
+
// one statement, only while this claim still holds the Wait; whether it did.
|
|
636
|
+
async function finishResume(client, wait, status, error, resumedAt) {
|
|
637
|
+
var waitStatus = status === 'failed' ? 'failed' : 'done';
|
|
638
|
+
return wrote(await client.query(FINISH_RESUME_SQL, [
|
|
639
|
+
waitStatus, wait.id, wait.claimedRunAt, status, error, resumedAt, wait.event_id, wait.workflow_id,
|
|
640
|
+
]));
|
|
641
|
+
}
|
|
642
|
+
|
|
643
|
+
// The resume's outcome (see finishResume), then the event settled from its
|
|
644
|
+
// delivery rows like after any run (pending while something is still open,
|
|
645
|
+
// failed when a run failed, so Run again and the retries see it). Nothing
|
|
646
|
+
// when another dispatcher's claim holds the Wait now: that run settles it.
|
|
647
|
+
async function finishResumedRun(client, wait, eventRow, status, error, resumedAt) {
|
|
648
|
+
if (!(await finishResume(client, wait, status, error, resumedAt)) || !eventRow) return;
|
|
649
|
+
var enabled = await enabledAutomations(client, eventRow);
|
|
650
|
+
await client.query(FINISH_EVENT_SQL, [eventRow.id, await settledStatus(client, eventRow, enabled), eventRow.claimed_at]);
|
|
651
|
+
}
|
|
652
|
+
|
|
653
|
+
async function dispatchPass(context) {
|
|
654
|
+
var totals = { claimed: 0, delivered: 0, failed: 0, resumed: 0 };
|
|
655
|
+
if (registryTypes().length === 0) return totals;
|
|
656
|
+
await store.withClient(async function (client) {
|
|
657
|
+
var events = await claimEvents(client);
|
|
658
|
+
for (var i = 0; i < events.length; i++) {
|
|
659
|
+
var row = events[i];
|
|
660
|
+
// Settling starts no handler, so an exhausted event is settled even out
|
|
661
|
+
// of time: it never turns final with runs still marked running.
|
|
662
|
+
if (row.attempts >= MAX_ATTEMPTS) {
|
|
663
|
+
await settleExhausted(client, row);
|
|
664
|
+
continue;
|
|
665
|
+
}
|
|
666
|
+
// Out of time: the claims not started go back as they were.
|
|
667
|
+
if (Date.now() >= context.deadline) {
|
|
668
|
+
await client.query(FINISH_EVENT_SQL, [row.id, releasedStatus(row), row.claimedAt]);
|
|
669
|
+
continue;
|
|
670
|
+
}
|
|
671
|
+
totals.claimed += 1;
|
|
672
|
+
try {
|
|
673
|
+
var outcome = await deliverEvent(client, row, context);
|
|
674
|
+
totals.delivered += outcome.delivered;
|
|
675
|
+
totals.failed += outcome.failed;
|
|
676
|
+
} catch (error) {
|
|
677
|
+
console.error('[automations] could not deliver event ' + row.id + ': ' + store.errorMessage(error));
|
|
678
|
+
try { await client.query(FAIL_EVENT_SQL, [row.id, row.claimedAt]); } catch (_e) {}
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
totals.resumed = await resumeWaits(client, context);
|
|
682
|
+
});
|
|
683
|
+
return totals;
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
// One dispatcher per process at a time. A call while one runs joins it and
|
|
687
|
+
// asks for another pass, run while the time budget lasts. Once it is spent,
|
|
688
|
+
// nothing more starts in this call (the host stops it soon after): what the
|
|
689
|
+
// late caller recorded stays in the queue for the next kick.
|
|
690
|
+
var running = null;
|
|
691
|
+
var again = false;
|
|
692
|
+
|
|
693
|
+
function dispatch(options) {
|
|
694
|
+
if (running) {
|
|
695
|
+
again = true;
|
|
696
|
+
return running;
|
|
697
|
+
}
|
|
698
|
+
var settings = options || {};
|
|
699
|
+
var context = {
|
|
700
|
+
baseUrl: store.appBaseUrl(settings.req),
|
|
701
|
+
deadline: Date.now() + (settings.deadlineMs || PASS_DEADLINE_MS),
|
|
702
|
+
timeoutMs: settings.handlerTimeoutMs || HANDLER_TIMEOUT_MS,
|
|
703
|
+
};
|
|
704
|
+
running = (async function () {
|
|
705
|
+
var totals = { claimed: 0, delivered: 0, failed: 0, resumed: 0 };
|
|
706
|
+
do {
|
|
707
|
+
again = false;
|
|
708
|
+
var pass = await dispatchPass(context);
|
|
709
|
+
totals.claimed += pass.claimed;
|
|
710
|
+
totals.delivered += pass.delivered;
|
|
711
|
+
totals.failed += pass.failed;
|
|
712
|
+
totals.resumed += pass.resumed;
|
|
713
|
+
} while (again && Date.now() < context.deadline);
|
|
714
|
+
return totals;
|
|
715
|
+
})();
|
|
716
|
+
var current = running;
|
|
717
|
+
var settle = function () {
|
|
718
|
+
running = null;
|
|
719
|
+
again = false;
|
|
720
|
+
};
|
|
721
|
+
current.then(settle, settle);
|
|
722
|
+
return current;
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
function httpError(status, message) {
|
|
726
|
+
var error = new Error(message);
|
|
727
|
+
error.status = status;
|
|
728
|
+
return error;
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
// The editor's "send a test": runs ONE automation once, with the catalog
|
|
732
|
+
// blocks of the example it sends, switched on or not. It is recorded as a
|
|
733
|
+
// test (never claimed, never retried), and a Wait it meets stops the run and
|
|
734
|
+
// is reported as wouldWait instead of parking it.
|
|
735
|
+
async function runTest(input, options) {
|
|
736
|
+
var request = input || {};
|
|
737
|
+
var found = findAutomation(request.workflowId);
|
|
738
|
+
if (!found) throw httpError(404, 'This automation is not on the published site yet');
|
|
739
|
+
var source = store.isPlainObject(request.event) ? request.event : {};
|
|
740
|
+
var sourceType = source.event && source.event.type;
|
|
741
|
+
if (sourceType && sourceType !== found.type) {
|
|
742
|
+
throw httpError(400, 'The test is a ' + sourceType + ' event, and this automation reacts to ' + found.type);
|
|
743
|
+
}
|
|
744
|
+
var blocks = envelopeBlocks(found.type, source);
|
|
745
|
+
var actor = store.isPlainObject(source.actor) ? source.actor : {};
|
|
746
|
+
var settings = options || {};
|
|
747
|
+
var baseUrl = store.appBaseUrl(settings.req);
|
|
748
|
+
var timeoutMs = settings.handlerTimeoutMs || HANDLER_TIMEOUT_MS;
|
|
749
|
+
return store.withClient(async function (client) {
|
|
750
|
+
var event = (await client.query(INSERT_TEST_EVENT_SQL, [
|
|
751
|
+
found.type,
|
|
752
|
+
'test:' + crypto.randomUUID(),
|
|
753
|
+
JSON.stringify(Object.assign({}, blocks, { __test: true })),
|
|
754
|
+
store.toText(actor.email),
|
|
755
|
+
store.toText(actor.type) || 'system',
|
|
756
|
+
])).rows[0];
|
|
757
|
+
var delivery = (await client.query(START_TEST_DELIVERY_SQL, [event.id, found.entry.workflowId])).rows[0];
|
|
758
|
+
var envelope = Object.assign(
|
|
759
|
+
{
|
|
760
|
+
event: { id: String(event.id), type: found.type, version: 1, occurredAt: store.toIso(event.created_at), test: true },
|
|
761
|
+
actor: { type: store.toText(actor.type) || 'system', email: store.toText(actor.email) },
|
|
762
|
+
},
|
|
763
|
+
blocks
|
|
764
|
+
);
|
|
765
|
+
var totals = { claimed: 1, delivered: 0, failed: 0, resumed: 0 };
|
|
766
|
+
var ran = await runEntry(function () {
|
|
767
|
+
return found.entry.run(envelope, { __baseUrl: baseUrl }, undefined);
|
|
768
|
+
}, timeoutMs, lateDeliveryWriter(delivery, true));
|
|
769
|
+
if (ran.timedOut) return totals;
|
|
770
|
+
var wouldWait = ran.value && ran.value.wouldWait ? ran.value.wouldWait : null;
|
|
771
|
+
var note = ran.error ? store.errorMessage(ran.error) : wouldWait ? JSON.stringify({ wouldWait: wouldWait }) : null;
|
|
772
|
+
await client.query(FINISH_DELIVERY_SQL, [delivery.id, 'test', note, delivery.attempts]);
|
|
773
|
+
if (ran.error) totals.failed = 1;
|
|
774
|
+
else totals.delivered = 1;
|
|
775
|
+
if (wouldWait) totals.wouldWait = wouldWait;
|
|
776
|
+
return totals;
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
|
|
780
|
+
module.exports = { dispatch: dispatch, runTest: runTest };
|
|
781
|
+
`;
|
|
782
|
+
};
|
|
783
|
+
exports.generateAutomationDispatcherCode = generateAutomationDispatcherCode;
|
|
784
|
+
/**
|
|
785
|
+
* `pages/api/automations/dispatch.js`: POST, for this app's own server code
|
|
786
|
+
* (the app secret in `x-internal-data-secret`) or a signed request (the cron
|
|
787
|
+
* signature, see cron-request-verification.ts). Runs the queue and answers
|
|
788
|
+
* `{ claimed, delivered, failed, resumed }`.
|
|
789
|
+
*
|
|
790
|
+
* `{ test: true, workflowId, event }` runs that one automation once instead
|
|
791
|
+
* and answers the same, plus `wouldWait` when the test met a Wait. A test acts
|
|
792
|
+
* on what its body says, so it is taken only from a signed request whose
|
|
793
|
+
* signature covers the body (`x-teleport-body-sha256`): 400 "Unsigned body"
|
|
794
|
+
* otherwise, and 400 naming what is missing when `workflowId` or `event` is.
|
|
795
|
+
* The route reads its body itself (`bodyParser: false`) to hash exactly what
|
|
796
|
+
* was sent. A request that presents none of the credentials is refused (401)
|
|
797
|
+
* before a byte of its body is read, unless the site allows unsigned calls (a
|
|
798
|
+
* local run, `TELEPORT_CRON_ALLOW_UNSIGNED`); a body over 64 KB is refused
|
|
799
|
+
* (413) without reading past it.
|
|
800
|
+
*
|
|
801
|
+
* A signed request is taken once: its execution id, bound into the signature,
|
|
802
|
+
* is remembered (`takeSignedRequest`, table `teleport_automation_requests`)
|
|
803
|
+
* for as long as that signature could still verify, and the same request
|
|
804
|
+
* again is refused (409) before anything runs. A captured request cannot run
|
|
805
|
+
* an automation a second time. When the database cannot say whether it was
|
|
806
|
+
* seen, the request is refused (503). The app's own calls (the app secret)
|
|
807
|
+
* name no execution and are never remembered.
|
|
808
|
+
*/
|
|
809
|
+
const generateAutomationDispatchRouteCode = () => {
|
|
810
|
+
const rootPrefix = automations_scope_1.AUTOMATIONS_DISPATCH_ROUTE_PATH.map(() => '..').join('/');
|
|
811
|
+
return `/**
|
|
812
|
+
* Automations dispatch route (generated): runs lib/automations/dispatcher.js.
|
|
813
|
+
*/
|
|
814
|
+
var crypto = require('crypto');
|
|
815
|
+
var bus = require('${rootPrefix}/lib/automations/event-bus');
|
|
816
|
+
${(0, cron_request_verification_1.generateCronRequestVerificationCode)({ bodyDigest: true })}
|
|
817
|
+
|
|
818
|
+
// A test event's example is a few KB; nothing the route takes is near this.
|
|
819
|
+
var MAX_BODY_BYTES = ${DISPATCH_MAX_BODY_BYTES};
|
|
820
|
+
|
|
821
|
+
function tooLarge() {
|
|
822
|
+
var error = new Error('The request body is too large');
|
|
823
|
+
error.status = 413;
|
|
824
|
+
return error;
|
|
825
|
+
}
|
|
826
|
+
|
|
827
|
+
// The body exactly as sent, up to MAX_BODY_BYTES: past that the route stops
|
|
828
|
+
// reading and refuses it.
|
|
829
|
+
function readBody(req) {
|
|
830
|
+
return new Promise(function (resolve, reject) {
|
|
831
|
+
if (req.body && Buffer.isBuffer(req.body)) {
|
|
832
|
+
if (req.body.length > MAX_BODY_BYTES) reject(tooLarge());
|
|
833
|
+
else resolve(req.body);
|
|
834
|
+
return;
|
|
835
|
+
}
|
|
836
|
+
if (Number(req.headers && req.headers['content-length']) > MAX_BODY_BYTES) {
|
|
837
|
+
reject(tooLarge());
|
|
838
|
+
return;
|
|
839
|
+
}
|
|
840
|
+
var chunks = [];
|
|
841
|
+
var size = 0;
|
|
842
|
+
var done = false;
|
|
843
|
+
req.on('data', function (chunk) {
|
|
844
|
+
if (done) return;
|
|
845
|
+
size += chunk.length;
|
|
846
|
+
if (size > MAX_BODY_BYTES) {
|
|
847
|
+
done = true;
|
|
848
|
+
reject(tooLarge());
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
chunks.push(chunk);
|
|
852
|
+
});
|
|
853
|
+
req.on('end', function () {
|
|
854
|
+
if (done) return;
|
|
855
|
+
done = true;
|
|
856
|
+
resolve(Buffer.concat(chunks));
|
|
857
|
+
});
|
|
858
|
+
req.on('error', function (error) {
|
|
859
|
+
if (done) return;
|
|
860
|
+
done = true;
|
|
861
|
+
reject(error);
|
|
862
|
+
});
|
|
863
|
+
});
|
|
864
|
+
}
|
|
865
|
+
|
|
866
|
+
function parseBody(rawBody) {
|
|
867
|
+
try {
|
|
868
|
+
return JSON.parse(rawBody.toString('utf-8'));
|
|
869
|
+
} catch (_e) {
|
|
870
|
+
return {};
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
// What a caller can authenticate with: the app secret, the cron signature, or
|
|
875
|
+
// Vercel Cron's bearer token. One that presents none is refused unread.
|
|
876
|
+
function presentsCredentials(req) {
|
|
877
|
+
var headers = (req && req.headers) || {};
|
|
878
|
+
return !!(headers['x-internal-data-secret'] || headers['x-teleport-cron-signature'] || headers.authorization);
|
|
879
|
+
}
|
|
880
|
+
|
|
881
|
+
// Only server code can read NEXTAUTH_SECRET, so a browser cannot present it.
|
|
882
|
+
function presentsAppSecret(req) {
|
|
883
|
+
var given = req && req.headers ? req.headers['x-internal-data-secret'] : '';
|
|
884
|
+
var expected = process.env.NEXTAUTH_SECRET;
|
|
885
|
+
if (typeof given !== 'string' || !given || !expected) return false;
|
|
886
|
+
var a = Buffer.from(given);
|
|
887
|
+
var b = Buffer.from(String(expected));
|
|
888
|
+
return a.length === b.length && crypto.timingSafeEqual(a, b);
|
|
889
|
+
}
|
|
890
|
+
|
|
891
|
+
// A signature that covers this very body.
|
|
892
|
+
function signsBody(req, rawBody) {
|
|
893
|
+
return !!__cronHeader(req, '${cron_request_verification_1.CRON_BODY_DIGEST_HEADER}') && __verifyCronSignature(req, rawBody);
|
|
894
|
+
}
|
|
895
|
+
|
|
896
|
+
// A signed request is remembered for as long as its signature could verify
|
|
897
|
+
// (its timestamp may be that far off either way); after that it is refused
|
|
898
|
+
// as too old anyway.
|
|
899
|
+
var SIGNED_REQUEST_MEMORY_SECONDS = 2 * __CRON_SIGNATURE_TOLERANCE_SECONDS;
|
|
900
|
+
|
|
901
|
+
// What identifies a signed request: the execution it names, under its sender.
|
|
902
|
+
// A digest, so nothing a caller sent is stored as it was sent.
|
|
903
|
+
function signedRequestKey(req) {
|
|
904
|
+
var named = [
|
|
905
|
+
__cronHeader(req, 'x-teleport-project-id'),
|
|
906
|
+
__cronHeader(req, 'x-teleport-cron-id'),
|
|
907
|
+
__cronHeader(req, 'x-teleport-cron-execution-id'),
|
|
908
|
+
];
|
|
909
|
+
return crypto.createHash('sha256').update(JSON.stringify(named)).digest('hex');
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
module.exports = async function handler(req, res) {
|
|
913
|
+
if (req.method !== 'POST') {
|
|
914
|
+
res.setHeader('Allow', 'POST');
|
|
915
|
+
res.status(405).json({ error: 'Method not allowed' });
|
|
916
|
+
return;
|
|
917
|
+
}
|
|
918
|
+
if (!presentsCredentials(req) && process.env.TELEPORT_CRON_ALLOW_UNSIGNED !== 'true') {
|
|
919
|
+
res.status(401).json({ error: 'Unauthorized' });
|
|
920
|
+
return;
|
|
921
|
+
}
|
|
922
|
+
var rawBody;
|
|
923
|
+
try {
|
|
924
|
+
rawBody = await readBody(req);
|
|
925
|
+
} catch (error) {
|
|
926
|
+
if (error && error.status === 413) {
|
|
927
|
+
res.status(413).json({ error: error.message });
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
res.status(400).json({ error: 'The request body could not be read' });
|
|
931
|
+
return;
|
|
932
|
+
}
|
|
933
|
+
var signed = __verifyCronSignature(req, rawBody);
|
|
934
|
+
if (!signed && !presentsAppSecret(req) && !verifyCronRequest(req, rawBody)) {
|
|
935
|
+
res.status(401).json({ error: 'Unauthorized' });
|
|
936
|
+
return;
|
|
937
|
+
}
|
|
938
|
+
if (signed) {
|
|
939
|
+
var taken;
|
|
940
|
+
try {
|
|
941
|
+
taken = await bus.takeSignedRequest(
|
|
942
|
+
signedRequestKey(req),
|
|
943
|
+
Math.floor(Date.now() / 1000) + SIGNED_REQUEST_MEMORY_SECONDS
|
|
944
|
+
);
|
|
945
|
+
} catch (error) {
|
|
946
|
+
console.error('[automations] could not check a signed request:', error);
|
|
947
|
+
res.status(503).json({ error: 'The request could not be checked. Try again.' });
|
|
948
|
+
return;
|
|
949
|
+
}
|
|
950
|
+
if (!taken) {
|
|
951
|
+
res.status(409).json({ error: 'This request was already received' });
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
}
|
|
955
|
+
var body = parseBody(rawBody);
|
|
956
|
+
if (!body || typeof body !== 'object' || Array.isArray(body)) body = {};
|
|
957
|
+
try {
|
|
958
|
+
if (body.test === true) {
|
|
959
|
+
if (!signsBody(req, rawBody)) {
|
|
960
|
+
res.status(400).json({ error: 'Unsigned body' });
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
if (typeof body.workflowId !== 'string' || !body.workflowId) {
|
|
964
|
+
res.status(400).json({ error: 'A test names the automation to run: workflowId is missing' });
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
if (!body.event || typeof body.event !== 'object') {
|
|
968
|
+
res.status(400).json({ error: 'A test carries the event to send: event is missing' });
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
res.status(200).json(await bus.runTestEvent({ workflowId: body.workflowId, event: body.event }, req));
|
|
972
|
+
return;
|
|
973
|
+
}
|
|
974
|
+
res.status(200).json(await bus.dispatch({ req: req }));
|
|
975
|
+
} catch (error) {
|
|
976
|
+
if (error && (error.status === 400 || error.status === 404)) {
|
|
977
|
+
res.status(error.status).json({ error: error.message });
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
console.error('[automations] dispatch failed:', error);
|
|
981
|
+
res.status(500).json({ error: 'Dispatch failed' });
|
|
982
|
+
}
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
// The body is read raw (see above). maxDuration is read by hosts that take a
|
|
986
|
+
// function's time limit from its config (Vercel); Next.js itself reads only
|
|
987
|
+
// config.api, so that key is otherwise inert.
|
|
988
|
+
module.exports.config = { api: { bodyParser: false }, maxDuration: ${routeMaxDurationSeconds} };
|
|
989
|
+
`;
|
|
990
|
+
};
|
|
991
|
+
exports.generateAutomationDispatchRouteCode = generateAutomationDispatchRouteCode;
|
|
992
|
+
/**
|
|
993
|
+
* `pages/api/automations/dispatch.js` for a project whose automations cannot
|
|
994
|
+
* run (no bus was generated, see generateAutomationFiles): every request is
|
|
995
|
+
* answered 503 with the reason, so the editor's test-event proxy shows the
|
|
996
|
+
* owner that sentence instead of a missing page.
|
|
997
|
+
*/
|
|
998
|
+
const generateAutomationsUnavailableRouteCode = (reason) => `/**
|
|
999
|
+
* Automations dispatch route (generated): automations do not run on this site.
|
|
1000
|
+
*/
|
|
1001
|
+
var MESSAGE = ${JSON.stringify(`Automations are not set up on this site: ${reason}`)};
|
|
1002
|
+
|
|
1003
|
+
module.exports = function handler(req, res) {
|
|
1004
|
+
res.status(503).json({ error: MESSAGE });
|
|
1005
|
+
};
|
|
1006
|
+
`;
|
|
1007
|
+
exports.generateAutomationsUnavailableRouteCode = generateAutomationsUnavailableRouteCode;
|
|
1008
|
+
//# sourceMappingURL=dispatcher-source.js.map
|