@elevasis/core 0.7.1 → 0.8.2
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/dist/test-utils/index.d.ts +3122 -0
- package/dist/test-utils/index.js +386 -0
- package/package.json +6 -1
- package/src/README.md +39 -36
- package/src/__tests__/publish.test.ts +18 -13
- package/src/__tests__/{template-foundations-compatibility.test.ts → template-core-compatibility.test.ts} +99 -99
- package/src/_gen/__tests__/__snapshots__/contracts.md.snap +1135 -1131
- package/src/_gen/__tests__/scaffold-contracts.test.ts +47 -36
- package/src/_gen/scaffold-contracts.ts +45 -45
- package/src/auth/multi-tenancy/credentials/README.md +38 -38
- package/src/auth/multi-tenancy/credentials/index.ts +6 -6
- package/src/auth/multi-tenancy/credentials/server/encryption.ts +39 -39
- package/src/auth/multi-tenancy/credentials/server/service.ts +60 -60
- package/src/auth/multi-tenancy/index.ts +17 -17
- package/src/auth/multi-tenancy/invitations/api-schemas.ts +107 -107
- package/src/auth/multi-tenancy/invitations/index.ts +37 -37
- package/src/auth/multi-tenancy/invitations/invitation.ts +86 -86
- package/src/auth/multi-tenancy/invitations/server/index.ts +25 -25
- package/src/auth/multi-tenancy/invitations/server/transforms.ts +24 -24
- package/src/auth/multi-tenancy/invitations/server/workos.ts +24 -24
- package/src/auth/multi-tenancy/invitations/supabase.ts +50 -50
- package/src/auth/multi-tenancy/memberships/api-schemas.ts +126 -126
- package/src/auth/multi-tenancy/memberships/index.ts +21 -21
- package/src/auth/multi-tenancy/memberships/membership.ts +138 -138
- package/src/auth/multi-tenancy/memberships/server/index.ts +15 -15
- package/src/auth/multi-tenancy/memberships/server/transforms.ts +32 -32
- package/src/auth/multi-tenancy/memberships/server/workos.ts +21 -21
- package/src/auth/multi-tenancy/memberships/supabase.ts +46 -46
- package/src/auth/multi-tenancy/organizations/api-schemas.ts +128 -128
- package/src/auth/multi-tenancy/organizations/index.ts +23 -23
- package/src/auth/multi-tenancy/organizations/organization.ts +24 -24
- package/src/auth/multi-tenancy/organizations/server/index.ts +10 -10
- package/src/auth/multi-tenancy/organizations/server/transforms.ts +35 -35
- package/src/auth/multi-tenancy/organizations/server/workos.ts +20 -20
- package/src/auth/multi-tenancy/types.ts +83 -83
- package/src/auth/multi-tenancy/users/api-schemas.ts +194 -194
- package/src/auth/multi-tenancy/users/index.ts +27 -27
- package/src/auth/multi-tenancy/users/server/index.ts +19 -19
- package/src/auth/multi-tenancy/users/server/transforms.ts +21 -21
- package/src/auth/multi-tenancy/users/server/workos.ts +16 -16
- package/src/auth/multi-tenancy/users/user.ts +65 -65
- package/src/business/README.md +52 -52
- package/src/business/__tests__/entities-published.test.ts +33 -33
- package/src/business/acquisition/api-schemas.ts +759 -759
- package/src/business/acquisition/index.ts +109 -109
- package/src/business/acquisition/types.ts +402 -402
- package/src/business/base-entities.test.ts +481 -481
- package/src/business/base-entities.ts +241 -241
- package/src/business/entities-published.ts +24 -24
- package/src/business/index.ts +15 -15
- package/src/business/pdf/browser/pdfmake-browser.ts +229 -229
- package/src/business/pdf/index.ts +10 -10
- package/src/business/pdf/server/index.ts +21 -21
- package/src/business/pdf/server/themes/default.ts +8 -8
- package/src/business/pdf/server/themes/index.ts +9 -9
- package/src/business/pdf/server/themes/types.ts +8 -8
- package/src/business/pdf/types.ts +272 -272
- package/src/business/projects/index.ts +2 -2
- package/src/business/projects/sse-events.ts +21 -21
- package/src/business/projects/types.ts +89 -89
- package/src/business/sales/api-schemas.ts +75 -75
- package/src/business/seo/__tests__/linking.test.ts +549 -549
- package/src/business/seo/__tests__/types.test.ts +404 -404
- package/src/business/seo/index.ts +2 -2
- package/src/business/seo/linking.ts +281 -281
- package/src/business/seo/types.ts +199 -199
- package/src/commands/queue/index.ts +3 -3
- package/src/commands/queue/schemas.test.ts +593 -593
- package/src/commands/queue/schemas.ts +125 -125
- package/src/commands/queue/sse-events.ts +61 -61
- package/src/commands/queue/types/action.ts +52 -52
- package/src/commands/queue/types/checkpoint.ts +44 -44
- package/src/commands/queue/types/index.ts +7 -7
- package/src/commands/queue/types/task.ts +116 -116
- package/src/commands/queue/types.ts +14 -14
- package/src/content/distribution-metadata.ts +61 -61
- package/src/content/index.ts +10 -10
- package/src/deployments/index.ts +22 -22
- package/src/execution/core/__tests__/archived-logs.test.ts +72 -72
- package/src/execution/core/index.ts +11 -11
- package/src/execution/core/runner-types.ts +80 -80
- package/src/execution/core/server/environment.ts +31 -31
- package/src/execution/core/sse-executions.ts +119 -119
- package/src/execution/core/types.ts +29 -29
- package/src/execution/engine/__tests__/fixtures/test-agents.ts +4 -4
- package/src/execution/engine/__tests__/timeout.test.ts +565 -565
- package/src/execution/engine/agent/__tests__/errors.test.ts +508 -508
- package/src/execution/engine/agent/actions/__tests__/processor.test.ts +531 -531
- package/src/execution/engine/agent/actions/executor.ts +205 -205
- package/src/execution/engine/agent/actions/navigate-knowledge-executor.ts +230 -230
- package/src/execution/engine/agent/actions/processor.ts +116 -116
- package/src/execution/engine/agent/actions/types.ts +70 -70
- package/src/execution/engine/agent/core/agent.ts +810 -810
- package/src/execution/engine/agent/core/types.ts +155 -155
- package/src/execution/engine/agent/errors.ts +251 -251
- package/src/execution/engine/agent/index.ts +78 -78
- package/src/execution/engine/agent/knowledge-map/types.ts +106 -106
- package/src/execution/engine/agent/knowledge-map/utils.ts +101 -101
- package/src/execution/engine/agent/memory/__tests__/manager.test.ts +754 -754
- package/src/execution/engine/agent/memory/domains.ts +99 -99
- package/src/execution/engine/agent/memory/manager.ts +365 -365
- package/src/execution/engine/agent/memory/processor.ts +66 -66
- package/src/execution/engine/agent/memory/types.ts +90 -90
- package/src/execution/engine/agent/memory/utils.ts +134 -134
- package/src/execution/engine/agent/observability/logging.ts +467 -467
- package/src/execution/engine/agent/observability/types.ts +64 -64
- package/src/execution/engine/agent/reasoning/adapters/agent-adapter-helpers.ts +349 -349
- package/src/execution/engine/agent/reasoning/processor.ts +92 -92
- package/src/execution/engine/agent/reasoning/prompt-sections/base-actions.ts +134 -134
- package/src/execution/engine/agent/reasoning/prompt-sections/completion.ts +49 -49
- package/src/execution/engine/agent/reasoning/prompt-sections/knowledge-map.ts +93 -93
- package/src/execution/engine/agent/reasoning/prompt-sections/memory.ts +65 -65
- package/src/execution/engine/agent/reasoning/prompt-sections/tools.ts +44 -44
- package/src/execution/engine/agent/reasoning/request-builder.ts +169 -169
- package/src/execution/engine/agent/reasoning/types.ts +18 -18
- package/src/execution/engine/base/errors.ts +118 -118
- package/src/execution/engine/base/index.ts +2 -2
- package/src/execution/engine/base/logging.ts +31 -31
- package/src/execution/engine/base/serialization.ts +324 -324
- package/src/execution/engine/base/types.ts +126 -126
- package/src/execution/engine/base/utils.ts +41 -41
- package/src/execution/engine/index.ts +434 -434
- package/src/execution/engine/interface/index.ts +1 -1
- package/src/execution/engine/interface/types.ts +62 -62
- package/src/execution/engine/llm/__tests__/model-info.test.ts +50 -50
- package/src/execution/engine/llm/__tests__/model-validation.test.ts +321 -321
- package/src/execution/engine/llm/__tests__/response-schema-validator.test.ts +115 -115
- package/src/execution/engine/llm/adapters/__tests__/adapter-factory.test.ts +375 -375
- package/src/execution/engine/llm/adapters/__tests__/anthropic-adapter.test.ts +463 -463
- package/src/execution/engine/llm/adapters/__tests__/anthropic.integration.test.ts +177 -177
- package/src/execution/engine/llm/adapters/__tests__/google-adapter.test.ts +722 -722
- package/src/execution/engine/llm/adapters/__tests__/google.integration.test.ts +376 -376
- package/src/execution/engine/llm/adapters/__tests__/openai-adapter.test.ts +551 -551
- package/src/execution/engine/llm/adapters/__tests__/openrouter-adapter.test.ts +563 -563
- package/src/execution/engine/llm/adapters/__tests__/openrouter.integration.test.ts +105 -105
- package/src/execution/engine/llm/adapters/__tests__/universal-adapter.test.ts +537 -537
- package/src/execution/engine/llm/adapters/circuit-breaker.ts +147 -147
- package/src/execution/engine/llm/adapters/index.ts +17 -17
- package/src/execution/engine/llm/adapters/mock-adapter.ts +116 -116
- package/src/execution/engine/llm/adapters/server/adapter-factory.ts +130 -130
- package/src/execution/engine/llm/adapters/server/anthropic.ts +137 -137
- package/src/execution/engine/llm/adapters/server/google.ts +283 -283
- package/src/execution/engine/llm/adapters/server/index.ts +12 -12
- package/src/execution/engine/llm/adapters/server/openai.ts +206 -206
- package/src/execution/engine/llm/adapters/server/openrouter.ts +235 -235
- package/src/execution/engine/llm/adapters/universal-adapter.ts +230 -230
- package/src/execution/engine/llm/errors.ts +186 -186
- package/src/execution/engine/llm/model-info.ts +332 -332
- package/src/execution/engine/llm/response-schema-validator.ts +113 -113
- package/src/execution/engine/llm/types.ts +86 -86
- package/src/execution/engine/test-utils/index.ts +6 -6
- package/src/execution/engine/test-utils/mocks.ts +56 -56
- package/src/execution/engine/tools/integration/base-integration-adapter.ts +50 -50
- package/src/execution/engine/tools/integration/index.ts +53 -53
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/anymailfinder-adapter.ts +73 -73
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/anymailfinder-tools.ts +209 -209
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-company-email/index.ts +82 -82
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-decision-maker-email/index.ts +122 -122
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/find-person-email/index.ts +89 -89
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/fetch/verify-email/index.ts +84 -84
- package/src/execution/engine/tools/integration/server/adapters/anymailfinder/index.ts +16 -16
- package/src/execution/engine/tools/integration/server/adapters/apify/__tests__/apify-run-actor.integration.test.ts +293 -293
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-adapter.ts +100 -100
- package/src/execution/engine/tools/integration/server/adapters/apify/apify-tools.ts +217 -217
- package/src/execution/engine/tools/integration/server/adapters/apify/fetch/get-dataset-items/index.ts +92 -92
- package/src/execution/engine/tools/integration/server/adapters/apify/fetch/run-actor/index.ts +218 -218
- package/src/execution/engine/tools/integration/server/adapters/apify/fetch/start-actor/index.ts +87 -87
- package/src/execution/engine/tools/integration/server/adapters/apify/index.ts +11 -11
- package/src/execution/engine/tools/integration/server/adapters/attio/__tests__/attio-crud.integration.test.ts +361 -361
- package/src/execution/engine/tools/integration/server/adapters/attio/attio-adapter.ts +162 -162
- package/src/execution/engine/tools/integration/server/adapters/attio/attio-tools.ts +594 -594
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-attribute/index.ts +214 -214
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-note/index.ts +152 -152
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/create-record/index.ts +141 -141
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/delete-note/index.ts +86 -86
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/delete-record/index.ts +105 -105
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/get-record/index.ts +118 -118
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-attributes/index.ts +165 -165
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-notes/index.ts +96 -96
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-objects/index.ts +104 -104
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/list-records/index.ts +156 -156
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/update-attribute/index.ts +220 -220
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/update-record/index.ts +140 -140
- package/src/execution/engine/tools/integration/server/adapters/attio/fetch/utils/types.ts +146 -146
- package/src/execution/engine/tools/integration/server/adapters/attio/index.ts +31 -31
- package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-adapter.ts +210 -210
- package/src/execution/engine/tools/integration/server/adapters/gmail/gmail-tools.ts +104 -104
- package/src/execution/engine/tools/integration/server/adapters/google-sheets/__tests__/google-sheets.integration.test.ts +261 -261
- package/src/execution/engine/tools/integration/server/adapters/google-sheets/google-sheets-adapter.ts +1189 -1189
- package/src/execution/engine/tools/integration/server/adapters/google-sheets/google-sheets-tools.ts +641 -641
- package/src/execution/engine/tools/integration/server/adapters/google-sheets/index.ts +18 -18
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/activate-campaign/index.ts +86 -86
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/add-to-campaign/__tests__/index.test.ts +289 -289
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/add-to-campaign/index.ts +154 -154
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-add-leads/__tests__/index.test.ts +325 -325
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-add-leads/index.ts +153 -153
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/bulk-delete-leads/index.ts +84 -84
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/create-campaign/index.ts +125 -125
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/create-inbox-test/index.ts +107 -107
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/delete-campaign/index.ts +85 -85
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-account-health/index.ts +91 -91
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign/index.ts +92 -92
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign-analytics/__tests__/index.test.ts +195 -195
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-campaign-analytics/index.ts +113 -113
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-daily-campaign-analytics/index.ts +104 -104
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-emails/index.ts +155 -155
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-step-analytics/__tests__/index.test.ts +196 -196
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/get-step-analytics/index.ts +102 -102
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-campaigns/__tests__/index.test.ts +189 -189
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-campaigns/index.ts +87 -87
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/list-leads/index.ts +112 -112
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/patch-lead/index.ts +76 -76
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/pause-campaign/index.ts +86 -86
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/remove-from-subsequence/index.ts +98 -98
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/send-reply/index.ts +126 -126
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-campaign/__tests__/index.test.ts +193 -193
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-campaign/index.ts +99 -99
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-interest-status/__tests__/index.test.ts +621 -621
- package/src/execution/engine/tools/integration/server/adapters/instantly/fetch/update-interest-status/index.ts +125 -125
- package/src/execution/engine/tools/integration/server/adapters/instantly/index.ts +29 -29
- package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-adapter.ts +178 -178
- package/src/execution/engine/tools/integration/server/adapters/instantly/instantly-tools.ts +1473 -1473
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/fetch/check-credits/index.ts +59 -59
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/fetch/verify-email/index.ts +102 -102
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/index.ts +17 -17
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-adapter.ts +80 -80
- package/src/execution/engine/tools/integration/server/adapters/millionverifier/millionverifier-tools.ts +102 -102
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/get-email/index.ts +102 -102
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/send-email/index.ts +134 -134
- package/src/execution/engine/tools/integration/server/adapters/resend/fetch/utils/types.ts +75 -75
- package/src/execution/engine/tools/integration/server/adapters/resend/index.ts +27 -27
- package/src/execution/engine/tools/integration/server/adapters/resend/resend-adapter.ts +108 -108
- package/src/execution/engine/tools/integration/server/adapters/resend/resend-tools.ts +132 -132
- package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/create-envelope/index.ts +274 -274
- package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/download-document/index.ts +230 -230
- package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/get-envelope/index.ts +133 -133
- package/src/execution/engine/tools/integration/server/adapters/signature-api/fetch/void-envelope/index.ts +90 -90
- package/src/execution/engine/tools/integration/server/adapters/stripe/fetch/utils/types.ts +210 -210
- package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-adapter.ts +517 -517
- package/src/execution/engine/tools/integration/server/adapters/stripe/stripe-tools.ts +309 -309
- package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/domain-search/index.ts +133 -133
- package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/email-finder/index.ts +122 -122
- package/src/execution/engine/tools/integration/server/adapters/tomba/fetch/email-verifier/index.ts +111 -111
- package/src/execution/engine/tools/integration/server/adapters/tomba/index.ts +11 -11
- package/src/execution/engine/tools/integration/server/adapters/tomba/tomba-adapter.ts +78 -78
- package/src/execution/engine/tools/integration/server/adapters/tomba/tomba-tools.ts +222 -222
- package/src/execution/engine/tools/integration/server/index.ts +61 -61
- package/src/execution/engine/tools/integration/service.ts +161 -161
- package/src/execution/engine/tools/integration/tool.ts +253 -253
- package/src/execution/engine/tools/integration/types/anymailfinder.ts +74 -74
- package/src/execution/engine/tools/integration/types/apify.ts +92 -92
- package/src/execution/engine/tools/integration/types/index.ts +19 -19
- package/src/execution/engine/tools/integration/types/instantly.ts +557 -557
- package/src/execution/engine/tools/integration/types/millionverifier.ts +56 -56
- package/src/execution/engine/tools/integration/types/stripe.ts +162 -162
- package/src/execution/engine/tools/integration/types/tomba.ts +94 -94
- package/src/execution/engine/tools/lead-service-types.ts +884 -884
- package/src/execution/engine/tools/llm/index.ts +11 -11
- package/src/execution/engine/tools/llm/server/index.ts +8 -8
- package/src/execution/engine/tools/llm/server/llm-call-tool.ts +118 -118
- package/src/execution/engine/tools/platform/__tests__/pdf.test.ts +441 -441
- package/src/execution/engine/tools/platform/acquisition/company-tools.ts +248 -248
- package/src/execution/engine/tools/platform/acquisition/contact-tools.ts +319 -319
- package/src/execution/engine/tools/platform/acquisition/index.ts +43 -43
- package/src/execution/engine/tools/platform/acquisition/list-tools.ts +148 -148
- package/src/execution/engine/tools/platform/acquisition/types.ts +260 -260
- package/src/execution/engine/tools/platform/email/index.ts +122 -122
- package/src/execution/engine/tools/platform/email/types.ts +96 -96
- package/src/execution/engine/tools/platform/index.ts +157 -157
- package/src/execution/engine/tools/platform/notification.ts +81 -81
- package/src/execution/engine/tools/platform/pdf/index.ts +110 -110
- package/src/execution/engine/tools/platform/pdf/types.ts +77 -77
- package/src/execution/engine/tools/platform/scheduler.ts +87 -87
- package/src/execution/engine/tools/platform/storage/index.ts +370 -370
- package/src/execution/engine/tools/platform/types.ts +148 -148
- package/src/execution/engine/tools/registry.ts +700 -700
- package/src/execution/engine/tools/tool-maps.ts +786 -786
- package/src/execution/engine/tools/types.ts +233 -233
- package/src/execution/engine/workflow/__tests__/errors.test.ts +139 -139
- package/src/execution/engine/workflow/errors.ts +63 -63
- package/src/execution/engine/workflow/helpers/index.ts +11 -11
- package/src/execution/engine/workflow/helpers/server/index.ts +8 -8
- package/src/execution/engine/workflow/helpers/server/llm-call.ts +93 -93
- package/src/execution/engine/workflow/index.ts +19 -19
- package/src/execution/engine/workflow/log-truncate.ts +26 -26
- package/src/execution/engine/workflow/logging.ts +191 -191
- package/src/execution/engine/workflow/types.ts +182 -182
- package/src/execution/engine/workflow/utils.ts +280 -280
- package/src/execution/engine/workflow/workflow.ts +168 -168
- package/src/execution/index.ts +3 -3
- package/src/execution/scheduler/__tests__/api-schemas.test.ts +733 -733
- package/src/execution/scheduler/__tests__/utils.test.ts +1009 -1009
- package/src/execution/scheduler/api-schemas.ts +296 -296
- package/src/execution/scheduler/index.ts +50 -50
- package/src/execution/scheduler/schemas.ts +264 -264
- package/src/execution/scheduler/types.ts +111 -111
- package/src/execution/scheduler/utils.ts +364 -364
- package/src/forms/index.ts +7 -7
- package/src/forms/schemas.ts +69 -69
- package/src/forms/types.ts +70 -70
- package/src/index.ts +71 -60
- package/src/integrations/credentials/__tests__/schemas.test.ts +82 -82
- package/src/integrations/credentials/__tests__/utils.test.ts +144 -144
- package/src/integrations/credentials/api-schemas.ts +143 -143
- package/src/integrations/credentials/index.ts +32 -32
- package/src/integrations/credentials/schemas.ts +164 -164
- package/src/integrations/credentials/utils.ts +59 -59
- package/src/integrations/oauth/__tests__/provider-registry.test.ts +59 -59
- package/src/integrations/oauth/api-schemas.ts +92 -92
- package/src/integrations/oauth/index.ts +19 -19
- package/src/integrations/oauth/provider-registry.ts +61 -61
- package/src/integrations/oauth/server/__tests__/refresh-concurrent.test.ts +183 -183
- package/src/integrations/oauth/server/__tests__/refresh.test.ts +577 -577
- package/src/integrations/oauth/server/credentials.ts +39 -39
- package/src/integrations/oauth/server/refresh.ts +214 -214
- package/src/integrations/oauth/types.ts +34 -34
- package/src/integrations/webhook-endpoints/__tests__/api-schemas.test.ts +318 -318
- package/src/integrations/webhook-endpoints/api-schemas.ts +102 -102
- package/src/integrations/webhook-endpoints/index.ts +28 -28
- package/src/integrations/webhook-endpoints/types.ts +51 -51
- package/src/operations/activities/api-schemas.ts +79 -79
- package/src/operations/activities/index.ts +9 -9
- package/src/operations/activities/sse-events.ts +30 -30
- package/src/operations/activities/types.ts +63 -63
- package/src/operations/debug-logs/client.ts +60 -60
- package/src/operations/debug-logs/debug-logger.ts +83 -83
- package/src/operations/debug-logs/index.ts +8 -8
- package/src/operations/debug-logs/server.ts +19 -19
- package/src/operations/debug-logs/types.ts +33 -33
- package/src/operations/index.ts +50 -50
- package/src/operations/notifications/api-schemas.ts +91 -91
- package/src/operations/notifications/index.ts +3 -3
- package/src/operations/notifications/sse-events.ts +21 -21
- package/src/operations/notifications/types.ts +47 -47
- package/src/operations/observability/__tests__/openrouter-cost-flow.test.ts +297 -297
- package/src/operations/observability/__tests__/utils.test.ts +54 -54
- package/src/operations/observability/ai-usage-collector.ts +64 -64
- package/src/operations/observability/index.ts +13 -13
- package/src/operations/observability/metrics-collector.ts +49 -49
- package/src/operations/observability/schemas.ts +39 -39
- package/src/operations/observability/types.ts +463 -463
- package/src/operations/observability/utils.ts +77 -77
- package/src/operations/sessions/__tests__/manager.test.ts +821 -821
- package/src/operations/sessions/index.ts +26 -26
- package/src/operations/sessions/server/manager.ts +90 -90
- package/src/operations/sessions/server/session.ts +180 -180
- package/src/operations/sessions/types.ts +98 -98
- package/src/operations/triggers/index.ts +12 -12
- package/src/operations/triggers/webhook/definitions/instantly-account-error.ts +44 -44
- package/src/operations/triggers/webhook/definitions/instantly-auto-reply-received.ts +51 -51
- package/src/operations/triggers/webhook/definitions/instantly-campaign-completed.ts +45 -45
- package/src/operations/triggers/webhook/definitions/instantly-email-bounced.ts +49 -49
- package/src/operations/triggers/webhook/definitions/instantly-lead-unsubscribed.ts +45 -45
- package/src/operations/triggers/webhook/definitions/instantly-reply-received.ts +54 -54
- package/src/operations/triggers/webhook/index.ts +35 -35
- package/src/operations/triggers/webhook/types.ts +74 -74
- package/src/organization-model/README.md +97 -97
- package/src/organization-model/__tests__/defaults.test.ts +175 -175
- package/src/organization-model/__tests__/domains/customers.test.ts +295 -295
- package/src/organization-model/__tests__/domains/goals.test.ts +479 -479
- package/src/organization-model/__tests__/domains/identity.test.ts +279 -279
- package/src/organization-model/__tests__/domains/navigation.test.ts +212 -212
- package/src/organization-model/__tests__/domains/offerings.test.ts +419 -419
- package/src/organization-model/__tests__/domains/operations.test.ts +203 -203
- package/src/organization-model/__tests__/domains/resource-mappings.test.ts +362 -362
- package/src/organization-model/__tests__/domains/roles.test.ts +347 -347
- package/src/organization-model/__tests__/domains/statuses.test.ts +243 -243
- package/src/organization-model/__tests__/foundation.test.ts +105 -105
- package/src/organization-model/__tests__/graph.test.ts +894 -894
- package/src/organization-model/__tests__/resolve.test.ts +690 -690
- package/src/organization-model/__tests__/schema.test.ts +407 -407
- package/src/organization-model/contracts.ts +14 -14
- package/src/organization-model/defaults.ts +148 -148
- package/src/organization-model/domains/branding.ts +22 -22
- package/src/organization-model/domains/customers.ts +75 -75
- package/src/organization-model/domains/features.ts +22 -22
- package/src/organization-model/domains/goals.ts +80 -80
- package/src/organization-model/domains/identity.ts +94 -94
- package/src/organization-model/domains/navigation.ts +391 -391
- package/src/organization-model/domains/offerings.ts +66 -66
- package/src/organization-model/domains/operations.ts +85 -85
- package/src/organization-model/domains/projects.ts +48 -48
- package/src/organization-model/domains/prospecting.ts +33 -33
- package/src/organization-model/domains/roles.ts +55 -55
- package/src/organization-model/domains/sales.ts +94 -94
- package/src/organization-model/domains/shared.ts +62 -62
- package/src/organization-model/domains/statuses.ts +130 -130
- package/src/organization-model/foundation.ts +97 -97
- package/src/organization-model/graph/build.ts +399 -399
- package/src/organization-model/graph/index.ts +4 -4
- package/src/organization-model/graph/schema.ts +48 -48
- package/src/organization-model/graph/types.ts +40 -40
- package/src/organization-model/index.ts +13 -13
- package/src/organization-model/organization-graph.mdx +272 -272
- package/src/organization-model/organization-model.mdx +320 -320
- package/src/organization-model/published.ts +85 -85
- package/src/organization-model/resolve.ts +66 -66
- package/src/organization-model/schema.ts +287 -287
- package/src/organization-model/types.ts +46 -46
- package/src/platform/api/index.ts +1 -1
- package/src/platform/api/types.ts +35 -35
- package/src/platform/constants/http.ts +37 -37
- package/src/platform/constants/index.ts +5 -5
- package/src/platform/constants/limits.ts +32 -32
- package/src/platform/constants/resilience.ts +51 -51
- package/src/platform/constants/timeouts.ts +20 -20
- package/src/platform/constants/versions.ts +3 -3
- package/src/platform/registry/__tests__/resource-registry-static.test.ts +347 -347
- package/src/platform/registry/__tests__/resource-registry.integration.test.ts +1028 -1028
- package/src/platform/registry/__tests__/resource-registry.list-executable.test.ts +393 -393
- package/src/platform/registry/__tests__/resource-registry.test.ts +2005 -2005
- package/src/platform/registry/__tests__/serialization.test.ts +1127 -1127
- package/src/platform/registry/command-view.ts +180 -180
- package/src/platform/registry/domains.ts +165 -165
- package/src/platform/registry/index.ts +93 -93
- package/src/platform/registry/reserved.ts +24 -24
- package/src/platform/registry/resource-metadata.ts +59 -59
- package/src/platform/registry/resource-registry.command-queue-groups.test.ts +129 -129
- package/src/platform/registry/resource-registry.ts +876 -876
- package/src/platform/registry/serialization.ts +273 -273
- package/src/platform/registry/serialized-types.ts +231 -231
- package/src/platform/registry/stats-types.ts +66 -66
- package/src/platform/registry/types.ts +404 -404
- package/src/platform/registry/validation.ts +513 -513
- package/src/platform/resilience/__tests__/rate-limiter.test.ts +471 -471
- package/src/platform/resilience/circuit-breaker.ts +164 -164
- package/src/platform/resilience/errors.ts +68 -68
- package/src/platform/resilience/http-error-mapper.ts +129 -129
- package/src/platform/resilience/index.ts +93 -93
- package/src/platform/resilience/rate-limiter-types.ts +46 -46
- package/src/platform/resilience/rate-limiter.ts +140 -140
- package/src/platform/resilience/retry.ts +89 -89
- package/src/platform/resilience/timeout.ts +63 -63
- package/src/platform/sse/events.ts +37 -37
- package/src/platform/sse/index.ts +7 -7
- package/src/platform/utils/__tests__/validation.test.ts +1083 -1083
- package/src/platform/utils/currency.ts +96 -96
- package/src/platform/utils/debounce.ts +52 -52
- package/src/platform/utils/error.ts +41 -41
- package/src/platform/utils/hmac.test.ts +97 -97
- package/src/platform/utils/index.ts +32 -32
- package/src/platform/utils/server/betterstack-logger.ts +210 -210
- package/src/platform/utils/server/hmac.ts +44 -44
- package/src/platform/utils/server/unsubscribe.ts +111 -111
- package/src/platform/utils/token-counter.ts +96 -96
- package/src/platform/utils/validation.ts +425 -425
- package/src/projects/api-schemas.ts +268 -268
- package/src/published.ts +1 -1
- package/src/reference/_generated/contracts.md +607 -607
- package/src/reference/glossary.md +105 -105
- package/src/requests/__tests__/api-schemas.test.ts +277 -277
- package/src/requests/api-schemas.ts +83 -83
- package/src/requests/index.ts +1 -1
- package/src/scaffold-registry/__tests__/index.test.ts +17 -0
- package/src/scaffold-registry/__tests__/schema.test.ts +329 -230
- package/src/scaffold-registry/index.ts +205 -189
- package/src/scaffold-registry/schema.ts +196 -128
- package/src/server.ts +272 -272
- package/src/supabase/database.types.ts +2719 -2719
- package/src/supabase/helpers.ts +20 -20
- package/src/supabase/index.ts +52 -52
- package/src/supabase/server/client.ts +58 -58
- package/src/test-utils/README.md +30 -138
- package/src/test-utils/browser-mocks.ts +54 -54
- package/src/test-utils/fixtures/api-keys.ts +52 -52
- package/src/test-utils/fixtures/index.ts +4 -4
- package/src/test-utils/fixtures/memberships.ts +80 -80
- package/src/test-utils/fixtures/organizations.ts +69 -69
- package/src/test-utils/fixtures/users.ts +79 -79
- package/src/test-utils/index.ts +7 -8
- package/src/test-utils/mocks/index.ts +2 -2
- package/src/test-utils/mocks/supabase.ts +142 -142
- package/src/test-utils/mocks/workos.ts +108 -108
- package/src/test-utils/published.ts +4 -0
- package/src/test-utils/rls/RLSTestContext.ts +554 -554
- package/src/test-utils/rls/index.ts +1 -1
|
@@ -1,364 +1,364 @@
|
|
|
1
|
-
import { toZonedTime, fromZonedTime } from 'date-fns-tz'
|
|
2
|
-
import { Cron } from 'croner'
|
|
3
|
-
import type {
|
|
4
|
-
TaskScheduleConfig,
|
|
5
|
-
RelativeScheduleConfig,
|
|
6
|
-
AbsoluteScheduleConfig,
|
|
7
|
-
RecurringScheduleConfig
|
|
8
|
-
} from './types'
|
|
9
|
-
|
|
10
|
-
/**
|
|
11
|
-
* Parsed offset result
|
|
12
|
-
*/
|
|
13
|
-
export interface ParsedOffset {
|
|
14
|
-
/** Can be negative for "before" offsets */
|
|
15
|
-
value: number
|
|
16
|
-
unit: 'd' | 'h' | 'm'
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
/**
|
|
20
|
-
* Parse offset strings like '+3d', '-2h', '+30m', '-14d'
|
|
21
|
-
*
|
|
22
|
-
* @param offset - Offset string (e.g., '+3d', '-2h', '+30m')
|
|
23
|
-
* @returns Parsed offset with value and unit
|
|
24
|
-
* @throws Error if format is invalid
|
|
25
|
-
*
|
|
26
|
-
* @example
|
|
27
|
-
* parseOffset('+3d') // { value: 3, unit: 'd' }
|
|
28
|
-
* parseOffset('-2h') // { value: -2, unit: 'h' }
|
|
29
|
-
* parseOffset('+30m') // { value: 30, unit: 'm' }
|
|
30
|
-
*/
|
|
31
|
-
export function parseOffset(offset: string): ParsedOffset {
|
|
32
|
-
const match = offset.match(/^([+-])(\d+)([dhm])$/)
|
|
33
|
-
if (!match) {
|
|
34
|
-
throw new Error(`Invalid offset format: "${offset}". Expected format: +3d, -2h, +30m, etc.`)
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
const sign = match[1] === '+' ? 1 : -1
|
|
38
|
-
const value = parseInt(match[2], 10) * sign
|
|
39
|
-
const unit = match[3] as 'd' | 'h' | 'm'
|
|
40
|
-
|
|
41
|
-
return { value, unit }
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
/**
|
|
45
|
-
* Apply an offset to an anchor date
|
|
46
|
-
*
|
|
47
|
-
* @param anchor - The anchor date to apply offset to
|
|
48
|
-
* @param offset - Offset string (e.g., '+3d', '-2h')
|
|
49
|
-
* @returns New Date with offset applied
|
|
50
|
-
*
|
|
51
|
-
* @example
|
|
52
|
-
* const anchor = new Date('2026-01-15T10:00:00Z')
|
|
53
|
-
* applyOffset(anchor, '+3d') // 2026-01-18T10:00:00Z
|
|
54
|
-
* applyOffset(anchor, '-2h') // 2026-01-15T08:00:00Z
|
|
55
|
-
*/
|
|
56
|
-
export function applyOffset(anchor: Date, offset: string): Date {
|
|
57
|
-
const { value, unit } = parseOffset(offset)
|
|
58
|
-
const result = new Date(anchor)
|
|
59
|
-
|
|
60
|
-
switch (unit) {
|
|
61
|
-
case 'd':
|
|
62
|
-
result.setDate(result.getDate() + value)
|
|
63
|
-
break
|
|
64
|
-
case 'h':
|
|
65
|
-
result.setHours(result.getHours() + value)
|
|
66
|
-
break
|
|
67
|
-
case 'm':
|
|
68
|
-
result.setMinutes(result.getMinutes() + value)
|
|
69
|
-
break
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
return result
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* Calculate next retry time using exponential backoff.
|
|
77
|
-
* Formula: (retryCount + 1)^2 minutes
|
|
78
|
-
* Results: 1 min (retry 0), 4 min (retry 1), 9 min (retry 2), 16 min (retry 3)
|
|
79
|
-
*
|
|
80
|
-
* @param retryCount - Current retry attempt (0-based)
|
|
81
|
-
* @returns Date for when the next retry should occur
|
|
82
|
-
*
|
|
83
|
-
* @example
|
|
84
|
-
* computeRetryNextRunAt(0) // 1 minute from now
|
|
85
|
-
* computeRetryNextRunAt(1) // 4 minutes from now
|
|
86
|
-
* computeRetryNextRunAt(2) // 9 minutes from now
|
|
87
|
-
* computeRetryNextRunAt(3) // 16 minutes from now
|
|
88
|
-
*/
|
|
89
|
-
export function computeRetryNextRunAt(retryCount: number): Date {
|
|
90
|
-
const delayMinutes = Math.pow(retryCount + 1, 2)
|
|
91
|
-
const nextRun = new Date()
|
|
92
|
-
nextRun.setMinutes(nextRun.getMinutes() + delayMinutes)
|
|
93
|
-
return nextRun
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Compute next run for recurring schedule.
|
|
98
|
-
* Supports both cron expressions (via croner) and interval-based (daily/weekly/monthly).
|
|
99
|
-
*
|
|
100
|
-
* Timezone handling:
|
|
101
|
-
* - config.time / config.cron are interpreted in config.timezone
|
|
102
|
-
* - fromTime is UTC, converted to target timezone for comparison
|
|
103
|
-
* - Returns UTC Date for storage
|
|
104
|
-
*/
|
|
105
|
-
function computeRecurringNextRun(config: RecurringScheduleConfig, fromTime: Date): Date | null {
|
|
106
|
-
const timezone = config.timezone || 'UTC'
|
|
107
|
-
|
|
108
|
-
// Check if schedule has ended
|
|
109
|
-
if (config.endAt) {
|
|
110
|
-
const endDate = new Date(config.endAt)
|
|
111
|
-
if (fromTime >= endDate) {
|
|
112
|
-
return null
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
// Cron-based schedules
|
|
117
|
-
if (config.cron) {
|
|
118
|
-
const job = new Cron(config.cron, { timezone })
|
|
119
|
-
const next = job.nextRun(fromTime)
|
|
120
|
-
|
|
121
|
-
if (!next) return null
|
|
122
|
-
|
|
123
|
-
// Check end date
|
|
124
|
-
if (config.endAt && next > new Date(config.endAt)) {
|
|
125
|
-
return null
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
return next
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
// Interval-based schedules
|
|
132
|
-
if (config.interval && config.time) {
|
|
133
|
-
const [hours, minutes] = config.time.split(':').map(Number)
|
|
134
|
-
|
|
135
|
-
// Convert fromTime (UTC) to the target timezone for comparison
|
|
136
|
-
const fromTimeInTz = toZonedTime(fromTime, timezone)
|
|
137
|
-
|
|
138
|
-
// Create next run time in target timezone
|
|
139
|
-
const nextInTz = new Date(fromTimeInTz)
|
|
140
|
-
|
|
141
|
-
// Set the time in target timezone
|
|
142
|
-
nextInTz.setHours(hours, minutes, 0, 0)
|
|
143
|
-
|
|
144
|
-
// If that time has passed today in target timezone, move to next interval
|
|
145
|
-
if (nextInTz <= fromTimeInTz) {
|
|
146
|
-
switch (config.interval) {
|
|
147
|
-
case 'daily':
|
|
148
|
-
nextInTz.setDate(nextInTz.getDate() + 1)
|
|
149
|
-
break
|
|
150
|
-
case 'weekly':
|
|
151
|
-
nextInTz.setDate(nextInTz.getDate() + 7)
|
|
152
|
-
break
|
|
153
|
-
case 'monthly':
|
|
154
|
-
nextInTz.setMonth(nextInTz.getMonth() + 1)
|
|
155
|
-
break
|
|
156
|
-
}
|
|
157
|
-
}
|
|
158
|
-
|
|
159
|
-
// Convert back to UTC for storage
|
|
160
|
-
const nextUtc = fromZonedTime(nextInTz, timezone)
|
|
161
|
-
|
|
162
|
-
// Check end date again (compare UTC times)
|
|
163
|
-
if (config.endAt && nextUtc > new Date(config.endAt)) {
|
|
164
|
-
return null
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
return nextUtc
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
throw new Error('Invalid recurring schedule: must have either cron or interval+time')
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
/**
|
|
174
|
-
* Compute next run for relative schedule (anchor + offset)
|
|
175
|
-
*/
|
|
176
|
-
function computeRelativeNextRun(config: RelativeScheduleConfig, currentStep: number): Date | null {
|
|
177
|
-
if (currentStep >= config.items.length) {
|
|
178
|
-
return null // Sequence complete
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const item = config.items[currentStep]
|
|
182
|
-
const anchor = new Date(config.anchorAt)
|
|
183
|
-
|
|
184
|
-
return applyOffset(anchor, item.offset)
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
/**
|
|
188
|
-
* Compute next run for absolute schedule (specific datetimes)
|
|
189
|
-
*/
|
|
190
|
-
function computeAbsoluteNextRun(config: AbsoluteScheduleConfig, currentStep: number): Date | null {
|
|
191
|
-
if (currentStep >= config.items.length) {
|
|
192
|
-
return null // Sequence complete
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
return new Date(config.items[currentStep].runAt)
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Compute the next run time for a schedule based on its config and current step
|
|
200
|
-
*
|
|
201
|
-
* @param config - The schedule configuration
|
|
202
|
-
* @param currentStep - Current step index (0-based, for sequences)
|
|
203
|
-
* @param fromTime - Optional reference time for recurring (defaults to now)
|
|
204
|
-
* @returns Next run Date, or null if schedule is complete
|
|
205
|
-
*
|
|
206
|
-
* @example
|
|
207
|
-
* // Relative schedule
|
|
208
|
-
* const config = { type: 'relative', anchorAt: '2026-01-15T10:00:00Z', items: [...] }
|
|
209
|
-
* computeNextRunAt(config, 0) // Returns anchor + items[0].offset
|
|
210
|
-
*
|
|
211
|
-
* // Absolute schedule
|
|
212
|
-
* const config = { type: 'absolute', items: [{ runAt: '2026-01-20T09:00:00Z', ... }] }
|
|
213
|
-
* computeNextRunAt(config, 0) // Returns items[0].runAt as Date
|
|
214
|
-
*
|
|
215
|
-
* // Returns null when sequence is complete
|
|
216
|
-
* computeNextRunAt(config, items.length) // null
|
|
217
|
-
*/
|
|
218
|
-
export function computeNextRunAt(config: TaskScheduleConfig, currentStep: number, fromTime?: Date): Date | null {
|
|
219
|
-
switch (config.type) {
|
|
220
|
-
case 'recurring':
|
|
221
|
-
return computeRecurringNextRun(config, fromTime || new Date())
|
|
222
|
-
|
|
223
|
-
case 'relative':
|
|
224
|
-
return computeRelativeNextRun(config, currentStep)
|
|
225
|
-
|
|
226
|
-
case 'absolute':
|
|
227
|
-
return computeAbsoluteNextRun(config, currentStep)
|
|
228
|
-
|
|
229
|
-
default: {
|
|
230
|
-
// TypeScript exhaustiveness check
|
|
231
|
-
const _exhaustive: never = config
|
|
232
|
-
throw new Error(`Unknown schedule type: ${(_exhaustive as { type: string }).type}`)
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
|
|
237
|
-
/**
|
|
238
|
-
* Get the payload for current step
|
|
239
|
-
*
|
|
240
|
-
* @param config - The schedule configuration
|
|
241
|
-
* @param currentStep - Current step index (0-based)
|
|
242
|
-
* @returns Payload for the current step, or null if step is out of range
|
|
243
|
-
*
|
|
244
|
-
* @example
|
|
245
|
-
* const config = { type: 'relative', items: [{ offset: '+1d', payload: { tone: 'grateful' } }] }
|
|
246
|
-
* getCurrentPayload(config, 0) // { tone: 'grateful' }
|
|
247
|
-
* getCurrentPayload(config, 1) // null (out of range)
|
|
248
|
-
*/
|
|
249
|
-
export function getCurrentPayload(config: TaskScheduleConfig, currentStep: number): Record<string, unknown> | null {
|
|
250
|
-
switch (config.type) {
|
|
251
|
-
case 'recurring':
|
|
252
|
-
return config.payload
|
|
253
|
-
|
|
254
|
-
case 'relative':
|
|
255
|
-
if (currentStep >= config.items.length) return null
|
|
256
|
-
return config.items[currentStep].payload
|
|
257
|
-
|
|
258
|
-
case 'absolute':
|
|
259
|
-
if (currentStep >= config.items.length) return null
|
|
260
|
-
return config.items[currentStep].payload
|
|
261
|
-
}
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Get the label for current step (if any)
|
|
266
|
-
*
|
|
267
|
-
* @param config - The schedule configuration
|
|
268
|
-
* @param currentStep - Current step index (0-based)
|
|
269
|
-
* @returns Label for the current step, or undefined if none
|
|
270
|
-
*
|
|
271
|
-
* @example
|
|
272
|
-
* const config = { type: 'relative', items: [{ offset: '+1d', label: 'Thank you', payload: {} }] }
|
|
273
|
-
* getCurrentItemLabel(config, 0) // 'Thank you'
|
|
274
|
-
* getCurrentItemLabel(config, 1) // undefined (out of range)
|
|
275
|
-
*/
|
|
276
|
-
export function getCurrentItemLabel(config: TaskScheduleConfig, currentStep: number): string | undefined {
|
|
277
|
-
switch (config.type) {
|
|
278
|
-
case 'recurring':
|
|
279
|
-
return undefined // Recurring schedules don't have step labels
|
|
280
|
-
|
|
281
|
-
case 'relative':
|
|
282
|
-
if (currentStep >= config.items.length) return undefined
|
|
283
|
-
return config.items[currentStep].label
|
|
284
|
-
|
|
285
|
-
case 'absolute':
|
|
286
|
-
if (currentStep >= config.items.length) return undefined
|
|
287
|
-
return config.items[currentStep].label
|
|
288
|
-
}
|
|
289
|
-
}
|
|
290
|
-
|
|
291
|
-
/**
|
|
292
|
-
* Check if a schedule is complete (all items executed)
|
|
293
|
-
*
|
|
294
|
-
* @param config - The schedule configuration
|
|
295
|
-
* @param currentStep - Current step index (0-based)
|
|
296
|
-
* @returns true if schedule is complete, false otherwise
|
|
297
|
-
*
|
|
298
|
-
* @example
|
|
299
|
-
* const config = { type: 'relative', items: [{ offset: '+1d', payload: {} }] }
|
|
300
|
-
* isScheduleComplete(config, 0) // false
|
|
301
|
-
* isScheduleComplete(config, 1) // true (past all items)
|
|
302
|
-
*
|
|
303
|
-
* // Recurring with end date
|
|
304
|
-
* const recurring = { type: 'recurring', interval: 'daily', time: '09:00', endAt: '2026-01-15' }
|
|
305
|
-
* isScheduleComplete(recurring, 0) // false (before end date)
|
|
306
|
-
* // Returns true after endAt has passed
|
|
307
|
-
*/
|
|
308
|
-
export function isScheduleComplete(config: TaskScheduleConfig, currentStep: number): boolean {
|
|
309
|
-
switch (config.type) {
|
|
310
|
-
case 'recurring':
|
|
311
|
-
// Recurring schedules are only complete if endAt has passed
|
|
312
|
-
if (config.endAt) {
|
|
313
|
-
return new Date() >= new Date(config.endAt)
|
|
314
|
-
}
|
|
315
|
-
return false // Indefinite recurring schedules never complete
|
|
316
|
-
|
|
317
|
-
case 'relative':
|
|
318
|
-
case 'absolute':
|
|
319
|
-
return currentStep >= config.items.length
|
|
320
|
-
}
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
/**
|
|
324
|
-
* Get the total number of steps in a schedule
|
|
325
|
-
*
|
|
326
|
-
* @param config - The schedule configuration
|
|
327
|
-
* @returns Number of steps, or null for indefinite recurring schedules
|
|
328
|
-
*
|
|
329
|
-
* @example
|
|
330
|
-
* const relative = { type: 'relative', items: [{...}, {...}, {...}] }
|
|
331
|
-
* getTotalSteps(relative) // 3
|
|
332
|
-
*
|
|
333
|
-
* const recurring = { type: 'recurring', interval: 'daily', endAt: null }
|
|
334
|
-
* getTotalSteps(recurring) // null (indefinite)
|
|
335
|
-
*/
|
|
336
|
-
export function getTotalSteps(config: TaskScheduleConfig): number | null {
|
|
337
|
-
switch (config.type) {
|
|
338
|
-
case 'recurring':
|
|
339
|
-
// Recurring schedules don't have a fixed number of steps
|
|
340
|
-
return null
|
|
341
|
-
|
|
342
|
-
case 'relative':
|
|
343
|
-
return config.items.length
|
|
344
|
-
|
|
345
|
-
case 'absolute':
|
|
346
|
-
return config.items.length
|
|
347
|
-
}
|
|
348
|
-
}
|
|
349
|
-
|
|
350
|
-
/**
|
|
351
|
-
* Validate that an offset string is properly formatted
|
|
352
|
-
*
|
|
353
|
-
* @param offset - Offset string to validate
|
|
354
|
-
* @returns true if valid, false otherwise
|
|
355
|
-
*
|
|
356
|
-
* @example
|
|
357
|
-
* isValidOffset('+3d') // true
|
|
358
|
-
* isValidOffset('-2h') // true
|
|
359
|
-
* isValidOffset('3d') // false (missing sign)
|
|
360
|
-
* isValidOffset('+3x') // false (invalid unit)
|
|
361
|
-
*/
|
|
362
|
-
export function isValidOffset(offset: string): boolean {
|
|
363
|
-
return /^[+-]\d+[dhm]$/.test(offset)
|
|
364
|
-
}
|
|
1
|
+
import { toZonedTime, fromZonedTime } from 'date-fns-tz'
|
|
2
|
+
import { Cron } from 'croner'
|
|
3
|
+
import type {
|
|
4
|
+
TaskScheduleConfig,
|
|
5
|
+
RelativeScheduleConfig,
|
|
6
|
+
AbsoluteScheduleConfig,
|
|
7
|
+
RecurringScheduleConfig
|
|
8
|
+
} from './types'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Parsed offset result
|
|
12
|
+
*/
|
|
13
|
+
export interface ParsedOffset {
|
|
14
|
+
/** Can be negative for "before" offsets */
|
|
15
|
+
value: number
|
|
16
|
+
unit: 'd' | 'h' | 'm'
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Parse offset strings like '+3d', '-2h', '+30m', '-14d'
|
|
21
|
+
*
|
|
22
|
+
* @param offset - Offset string (e.g., '+3d', '-2h', '+30m')
|
|
23
|
+
* @returns Parsed offset with value and unit
|
|
24
|
+
* @throws Error if format is invalid
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* parseOffset('+3d') // { value: 3, unit: 'd' }
|
|
28
|
+
* parseOffset('-2h') // { value: -2, unit: 'h' }
|
|
29
|
+
* parseOffset('+30m') // { value: 30, unit: 'm' }
|
|
30
|
+
*/
|
|
31
|
+
export function parseOffset(offset: string): ParsedOffset {
|
|
32
|
+
const match = offset.match(/^([+-])(\d+)([dhm])$/)
|
|
33
|
+
if (!match) {
|
|
34
|
+
throw new Error(`Invalid offset format: "${offset}". Expected format: +3d, -2h, +30m, etc.`)
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const sign = match[1] === '+' ? 1 : -1
|
|
38
|
+
const value = parseInt(match[2], 10) * sign
|
|
39
|
+
const unit = match[3] as 'd' | 'h' | 'm'
|
|
40
|
+
|
|
41
|
+
return { value, unit }
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Apply an offset to an anchor date
|
|
46
|
+
*
|
|
47
|
+
* @param anchor - The anchor date to apply offset to
|
|
48
|
+
* @param offset - Offset string (e.g., '+3d', '-2h')
|
|
49
|
+
* @returns New Date with offset applied
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* const anchor = new Date('2026-01-15T10:00:00Z')
|
|
53
|
+
* applyOffset(anchor, '+3d') // 2026-01-18T10:00:00Z
|
|
54
|
+
* applyOffset(anchor, '-2h') // 2026-01-15T08:00:00Z
|
|
55
|
+
*/
|
|
56
|
+
export function applyOffset(anchor: Date, offset: string): Date {
|
|
57
|
+
const { value, unit } = parseOffset(offset)
|
|
58
|
+
const result = new Date(anchor)
|
|
59
|
+
|
|
60
|
+
switch (unit) {
|
|
61
|
+
case 'd':
|
|
62
|
+
result.setDate(result.getDate() + value)
|
|
63
|
+
break
|
|
64
|
+
case 'h':
|
|
65
|
+
result.setHours(result.getHours() + value)
|
|
66
|
+
break
|
|
67
|
+
case 'm':
|
|
68
|
+
result.setMinutes(result.getMinutes() + value)
|
|
69
|
+
break
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return result
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Calculate next retry time using exponential backoff.
|
|
77
|
+
* Formula: (retryCount + 1)^2 minutes
|
|
78
|
+
* Results: 1 min (retry 0), 4 min (retry 1), 9 min (retry 2), 16 min (retry 3)
|
|
79
|
+
*
|
|
80
|
+
* @param retryCount - Current retry attempt (0-based)
|
|
81
|
+
* @returns Date for when the next retry should occur
|
|
82
|
+
*
|
|
83
|
+
* @example
|
|
84
|
+
* computeRetryNextRunAt(0) // 1 minute from now
|
|
85
|
+
* computeRetryNextRunAt(1) // 4 minutes from now
|
|
86
|
+
* computeRetryNextRunAt(2) // 9 minutes from now
|
|
87
|
+
* computeRetryNextRunAt(3) // 16 minutes from now
|
|
88
|
+
*/
|
|
89
|
+
export function computeRetryNextRunAt(retryCount: number): Date {
|
|
90
|
+
const delayMinutes = Math.pow(retryCount + 1, 2)
|
|
91
|
+
const nextRun = new Date()
|
|
92
|
+
nextRun.setMinutes(nextRun.getMinutes() + delayMinutes)
|
|
93
|
+
return nextRun
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Compute next run for recurring schedule.
|
|
98
|
+
* Supports both cron expressions (via croner) and interval-based (daily/weekly/monthly).
|
|
99
|
+
*
|
|
100
|
+
* Timezone handling:
|
|
101
|
+
* - config.time / config.cron are interpreted in config.timezone
|
|
102
|
+
* - fromTime is UTC, converted to target timezone for comparison
|
|
103
|
+
* - Returns UTC Date for storage
|
|
104
|
+
*/
|
|
105
|
+
function computeRecurringNextRun(config: RecurringScheduleConfig, fromTime: Date): Date | null {
|
|
106
|
+
const timezone = config.timezone || 'UTC'
|
|
107
|
+
|
|
108
|
+
// Check if schedule has ended
|
|
109
|
+
if (config.endAt) {
|
|
110
|
+
const endDate = new Date(config.endAt)
|
|
111
|
+
if (fromTime >= endDate) {
|
|
112
|
+
return null
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Cron-based schedules
|
|
117
|
+
if (config.cron) {
|
|
118
|
+
const job = new Cron(config.cron, { timezone })
|
|
119
|
+
const next = job.nextRun(fromTime)
|
|
120
|
+
|
|
121
|
+
if (!next) return null
|
|
122
|
+
|
|
123
|
+
// Check end date
|
|
124
|
+
if (config.endAt && next > new Date(config.endAt)) {
|
|
125
|
+
return null
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return next
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Interval-based schedules
|
|
132
|
+
if (config.interval && config.time) {
|
|
133
|
+
const [hours, minutes] = config.time.split(':').map(Number)
|
|
134
|
+
|
|
135
|
+
// Convert fromTime (UTC) to the target timezone for comparison
|
|
136
|
+
const fromTimeInTz = toZonedTime(fromTime, timezone)
|
|
137
|
+
|
|
138
|
+
// Create next run time in target timezone
|
|
139
|
+
const nextInTz = new Date(fromTimeInTz)
|
|
140
|
+
|
|
141
|
+
// Set the time in target timezone
|
|
142
|
+
nextInTz.setHours(hours, minutes, 0, 0)
|
|
143
|
+
|
|
144
|
+
// If that time has passed today in target timezone, move to next interval
|
|
145
|
+
if (nextInTz <= fromTimeInTz) {
|
|
146
|
+
switch (config.interval) {
|
|
147
|
+
case 'daily':
|
|
148
|
+
nextInTz.setDate(nextInTz.getDate() + 1)
|
|
149
|
+
break
|
|
150
|
+
case 'weekly':
|
|
151
|
+
nextInTz.setDate(nextInTz.getDate() + 7)
|
|
152
|
+
break
|
|
153
|
+
case 'monthly':
|
|
154
|
+
nextInTz.setMonth(nextInTz.getMonth() + 1)
|
|
155
|
+
break
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Convert back to UTC for storage
|
|
160
|
+
const nextUtc = fromZonedTime(nextInTz, timezone)
|
|
161
|
+
|
|
162
|
+
// Check end date again (compare UTC times)
|
|
163
|
+
if (config.endAt && nextUtc > new Date(config.endAt)) {
|
|
164
|
+
return null
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
return nextUtc
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
throw new Error('Invalid recurring schedule: must have either cron or interval+time')
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Compute next run for relative schedule (anchor + offset)
|
|
175
|
+
*/
|
|
176
|
+
function computeRelativeNextRun(config: RelativeScheduleConfig, currentStep: number): Date | null {
|
|
177
|
+
if (currentStep >= config.items.length) {
|
|
178
|
+
return null // Sequence complete
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
const item = config.items[currentStep]
|
|
182
|
+
const anchor = new Date(config.anchorAt)
|
|
183
|
+
|
|
184
|
+
return applyOffset(anchor, item.offset)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Compute next run for absolute schedule (specific datetimes)
|
|
189
|
+
*/
|
|
190
|
+
function computeAbsoluteNextRun(config: AbsoluteScheduleConfig, currentStep: number): Date | null {
|
|
191
|
+
if (currentStep >= config.items.length) {
|
|
192
|
+
return null // Sequence complete
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
return new Date(config.items[currentStep].runAt)
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* Compute the next run time for a schedule based on its config and current step
|
|
200
|
+
*
|
|
201
|
+
* @param config - The schedule configuration
|
|
202
|
+
* @param currentStep - Current step index (0-based, for sequences)
|
|
203
|
+
* @param fromTime - Optional reference time for recurring (defaults to now)
|
|
204
|
+
* @returns Next run Date, or null if schedule is complete
|
|
205
|
+
*
|
|
206
|
+
* @example
|
|
207
|
+
* // Relative schedule
|
|
208
|
+
* const config = { type: 'relative', anchorAt: '2026-01-15T10:00:00Z', items: [...] }
|
|
209
|
+
* computeNextRunAt(config, 0) // Returns anchor + items[0].offset
|
|
210
|
+
*
|
|
211
|
+
* // Absolute schedule
|
|
212
|
+
* const config = { type: 'absolute', items: [{ runAt: '2026-01-20T09:00:00Z', ... }] }
|
|
213
|
+
* computeNextRunAt(config, 0) // Returns items[0].runAt as Date
|
|
214
|
+
*
|
|
215
|
+
* // Returns null when sequence is complete
|
|
216
|
+
* computeNextRunAt(config, items.length) // null
|
|
217
|
+
*/
|
|
218
|
+
export function computeNextRunAt(config: TaskScheduleConfig, currentStep: number, fromTime?: Date): Date | null {
|
|
219
|
+
switch (config.type) {
|
|
220
|
+
case 'recurring':
|
|
221
|
+
return computeRecurringNextRun(config, fromTime || new Date())
|
|
222
|
+
|
|
223
|
+
case 'relative':
|
|
224
|
+
return computeRelativeNextRun(config, currentStep)
|
|
225
|
+
|
|
226
|
+
case 'absolute':
|
|
227
|
+
return computeAbsoluteNextRun(config, currentStep)
|
|
228
|
+
|
|
229
|
+
default: {
|
|
230
|
+
// TypeScript exhaustiveness check
|
|
231
|
+
const _exhaustive: never = config
|
|
232
|
+
throw new Error(`Unknown schedule type: ${(_exhaustive as { type: string }).type}`)
|
|
233
|
+
}
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Get the payload for current step
|
|
239
|
+
*
|
|
240
|
+
* @param config - The schedule configuration
|
|
241
|
+
* @param currentStep - Current step index (0-based)
|
|
242
|
+
* @returns Payload for the current step, or null if step is out of range
|
|
243
|
+
*
|
|
244
|
+
* @example
|
|
245
|
+
* const config = { type: 'relative', items: [{ offset: '+1d', payload: { tone: 'grateful' } }] }
|
|
246
|
+
* getCurrentPayload(config, 0) // { tone: 'grateful' }
|
|
247
|
+
* getCurrentPayload(config, 1) // null (out of range)
|
|
248
|
+
*/
|
|
249
|
+
export function getCurrentPayload(config: TaskScheduleConfig, currentStep: number): Record<string, unknown> | null {
|
|
250
|
+
switch (config.type) {
|
|
251
|
+
case 'recurring':
|
|
252
|
+
return config.payload
|
|
253
|
+
|
|
254
|
+
case 'relative':
|
|
255
|
+
if (currentStep >= config.items.length) return null
|
|
256
|
+
return config.items[currentStep].payload
|
|
257
|
+
|
|
258
|
+
case 'absolute':
|
|
259
|
+
if (currentStep >= config.items.length) return null
|
|
260
|
+
return config.items[currentStep].payload
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Get the label for current step (if any)
|
|
266
|
+
*
|
|
267
|
+
* @param config - The schedule configuration
|
|
268
|
+
* @param currentStep - Current step index (0-based)
|
|
269
|
+
* @returns Label for the current step, or undefined if none
|
|
270
|
+
*
|
|
271
|
+
* @example
|
|
272
|
+
* const config = { type: 'relative', items: [{ offset: '+1d', label: 'Thank you', payload: {} }] }
|
|
273
|
+
* getCurrentItemLabel(config, 0) // 'Thank you'
|
|
274
|
+
* getCurrentItemLabel(config, 1) // undefined (out of range)
|
|
275
|
+
*/
|
|
276
|
+
export function getCurrentItemLabel(config: TaskScheduleConfig, currentStep: number): string | undefined {
|
|
277
|
+
switch (config.type) {
|
|
278
|
+
case 'recurring':
|
|
279
|
+
return undefined // Recurring schedules don't have step labels
|
|
280
|
+
|
|
281
|
+
case 'relative':
|
|
282
|
+
if (currentStep >= config.items.length) return undefined
|
|
283
|
+
return config.items[currentStep].label
|
|
284
|
+
|
|
285
|
+
case 'absolute':
|
|
286
|
+
if (currentStep >= config.items.length) return undefined
|
|
287
|
+
return config.items[currentStep].label
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Check if a schedule is complete (all items executed)
|
|
293
|
+
*
|
|
294
|
+
* @param config - The schedule configuration
|
|
295
|
+
* @param currentStep - Current step index (0-based)
|
|
296
|
+
* @returns true if schedule is complete, false otherwise
|
|
297
|
+
*
|
|
298
|
+
* @example
|
|
299
|
+
* const config = { type: 'relative', items: [{ offset: '+1d', payload: {} }] }
|
|
300
|
+
* isScheduleComplete(config, 0) // false
|
|
301
|
+
* isScheduleComplete(config, 1) // true (past all items)
|
|
302
|
+
*
|
|
303
|
+
* // Recurring with end date
|
|
304
|
+
* const recurring = { type: 'recurring', interval: 'daily', time: '09:00', endAt: '2026-01-15' }
|
|
305
|
+
* isScheduleComplete(recurring, 0) // false (before end date)
|
|
306
|
+
* // Returns true after endAt has passed
|
|
307
|
+
*/
|
|
308
|
+
export function isScheduleComplete(config: TaskScheduleConfig, currentStep: number): boolean {
|
|
309
|
+
switch (config.type) {
|
|
310
|
+
case 'recurring':
|
|
311
|
+
// Recurring schedules are only complete if endAt has passed
|
|
312
|
+
if (config.endAt) {
|
|
313
|
+
return new Date() >= new Date(config.endAt)
|
|
314
|
+
}
|
|
315
|
+
return false // Indefinite recurring schedules never complete
|
|
316
|
+
|
|
317
|
+
case 'relative':
|
|
318
|
+
case 'absolute':
|
|
319
|
+
return currentStep >= config.items.length
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
/**
|
|
324
|
+
* Get the total number of steps in a schedule
|
|
325
|
+
*
|
|
326
|
+
* @param config - The schedule configuration
|
|
327
|
+
* @returns Number of steps, or null for indefinite recurring schedules
|
|
328
|
+
*
|
|
329
|
+
* @example
|
|
330
|
+
* const relative = { type: 'relative', items: [{...}, {...}, {...}] }
|
|
331
|
+
* getTotalSteps(relative) // 3
|
|
332
|
+
*
|
|
333
|
+
* const recurring = { type: 'recurring', interval: 'daily', endAt: null }
|
|
334
|
+
* getTotalSteps(recurring) // null (indefinite)
|
|
335
|
+
*/
|
|
336
|
+
export function getTotalSteps(config: TaskScheduleConfig): number | null {
|
|
337
|
+
switch (config.type) {
|
|
338
|
+
case 'recurring':
|
|
339
|
+
// Recurring schedules don't have a fixed number of steps
|
|
340
|
+
return null
|
|
341
|
+
|
|
342
|
+
case 'relative':
|
|
343
|
+
return config.items.length
|
|
344
|
+
|
|
345
|
+
case 'absolute':
|
|
346
|
+
return config.items.length
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
/**
|
|
351
|
+
* Validate that an offset string is properly formatted
|
|
352
|
+
*
|
|
353
|
+
* @param offset - Offset string to validate
|
|
354
|
+
* @returns true if valid, false otherwise
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* isValidOffset('+3d') // true
|
|
358
|
+
* isValidOffset('-2h') // true
|
|
359
|
+
* isValidOffset('3d') // false (missing sign)
|
|
360
|
+
* isValidOffset('+3x') // false (invalid unit)
|
|
361
|
+
*/
|
|
362
|
+
export function isValidOffset(offset: string): boolean {
|
|
363
|
+
return /^[+-]\d+[dhm]$/.test(offset)
|
|
364
|
+
}
|