@dotdo/do 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +400 -0
- package/dist/ai/embeddings.d.ts +129 -0
- package/dist/ai/embeddings.d.ts.map +1 -0
- package/dist/ai/embeddings.js +217 -0
- package/dist/ai/embeddings.js.map +1 -0
- package/dist/ai/gateway.d.ts +139 -0
- package/dist/ai/gateway.d.ts.map +1 -0
- package/dist/ai/gateway.js +179 -0
- package/dist/ai/gateway.js.map +1 -0
- package/dist/ai/image.d.ts +140 -0
- package/dist/ai/image.d.ts.map +1 -0
- package/dist/ai/image.js +199 -0
- package/dist/ai/image.js.map +1 -0
- package/dist/ai/index.d.ts +98 -0
- package/dist/ai/index.d.ts.map +1 -0
- package/dist/ai/index.js +223 -0
- package/dist/ai/index.js.map +1 -0
- package/dist/ai/models.d.ts +81 -0
- package/dist/ai/models.d.ts.map +1 -0
- package/dist/ai/models.js +537 -0
- package/dist/ai/models.js.map +1 -0
- package/dist/ai/text.d.ts +176 -0
- package/dist/ai/text.d.ts.map +1 -0
- package/dist/ai/text.js +253 -0
- package/dist/ai/text.js.map +1 -0
- package/dist/ai/voice/agents.d.ts +224 -0
- package/dist/ai/voice/agents.d.ts.map +1 -0
- package/dist/ai/voice/agents.js +375 -0
- package/dist/ai/voice/agents.js.map +1 -0
- package/dist/ai/voice/campaigns.d.ts +307 -0
- package/dist/ai/voice/campaigns.d.ts.map +1 -0
- package/dist/ai/voice/campaigns.js +739 -0
- package/dist/ai/voice/campaigns.js.map +1 -0
- package/dist/ai/voice/index.d.ts +21 -0
- package/dist/ai/voice/index.d.ts.map +1 -0
- package/dist/ai/voice/index.js +42 -0
- package/dist/ai/voice/index.js.map +1 -0
- package/dist/ai/voice/providers.d.ts +283 -0
- package/dist/ai/voice/providers.d.ts.map +1 -0
- package/dist/ai/voice/providers.js +286 -0
- package/dist/ai/voice/providers.js.map +1 -0
- package/dist/ai/voice/sessions.d.ts +294 -0
- package/dist/ai/voice/sessions.d.ts.map +1 -0
- package/dist/ai/voice/sessions.js +531 -0
- package/dist/ai/voice/sessions.js.map +1 -0
- package/dist/ai/voice/tools.d.ts +242 -0
- package/dist/ai/voice/tools.d.ts.map +1 -0
- package/dist/ai/voice/tools.js +370 -0
- package/dist/ai/voice/tools.js.map +1 -0
- package/dist/ai/voice/tts.d.ts +173 -0
- package/dist/ai/voice/tts.d.ts.map +1 -0
- package/dist/ai/voice/tts.js +252 -0
- package/dist/ai/voice/tts.js.map +1 -0
- package/dist/ai/voice/webrtc.d.ts +228 -0
- package/dist/ai/voice/webrtc.d.ts.map +1 -0
- package/dist/ai/voice/webrtc.js +372 -0
- package/dist/ai/voice/webrtc.js.map +1 -0
- package/dist/api/index.d.ts +103 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +191 -0
- package/dist/api/index.js.map +1 -0
- package/dist/api/mcp/handlers.d.ts +25 -0
- package/dist/api/mcp/handlers.d.ts.map +1 -0
- package/dist/api/mcp/handlers.js +422 -0
- package/dist/api/mcp/handlers.js.map +1 -0
- package/dist/api/mcp/index.d.ts +113 -0
- package/dist/api/mcp/index.d.ts.map +1 -0
- package/dist/api/mcp/index.js +141 -0
- package/dist/api/mcp/index.js.map +1 -0
- package/dist/api/middleware/auth.d.ts +65 -0
- package/dist/api/middleware/auth.d.ts.map +1 -0
- package/dist/api/middleware/auth.js +271 -0
- package/dist/api/middleware/auth.js.map +1 -0
- package/dist/api/middleware/cors.d.ts +62 -0
- package/dist/api/middleware/cors.d.ts.map +1 -0
- package/dist/api/middleware/cors.js +225 -0
- package/dist/api/middleware/cors.js.map +1 -0
- package/dist/api/middleware/index.d.ts +60 -0
- package/dist/api/middleware/index.d.ts.map +1 -0
- package/dist/api/middleware/index.js +175 -0
- package/dist/api/middleware/index.js.map +1 -0
- package/dist/api/middleware/rateLimit.d.ts +84 -0
- package/dist/api/middleware/rateLimit.d.ts.map +1 -0
- package/dist/api/middleware/rateLimit.js +321 -0
- package/dist/api/middleware/rateLimit.js.map +1 -0
- package/dist/api/routes/ai.d.ts +17 -0
- package/dist/api/routes/ai.d.ts.map +1 -0
- package/dist/api/routes/ai.js +430 -0
- package/dist/api/routes/ai.js.map +1 -0
- package/dist/api/routes/do.d.ts +17 -0
- package/dist/api/routes/do.d.ts.map +1 -0
- package/dist/api/routes/do.js +458 -0
- package/dist/api/routes/do.js.map +1 -0
- package/dist/api/routes/functions.d.ts +111 -0
- package/dist/api/routes/functions.d.ts.map +1 -0
- package/dist/api/routes/functions.js +548 -0
- package/dist/api/routes/functions.js.map +1 -0
- package/dist/api/routes/health.d.ts +16 -0
- package/dist/api/routes/health.d.ts.map +1 -0
- package/dist/api/routes/health.js +163 -0
- package/dist/api/routes/health.js.map +1 -0
- package/dist/api/routes/index.d.ts +41 -0
- package/dist/api/routes/index.d.ts.map +1 -0
- package/dist/api/routes/index.js +275 -0
- package/dist/api/routes/index.js.map +1 -0
- package/dist/api/routes/nouns.d.ts +26 -0
- package/dist/api/routes/nouns.d.ts.map +1 -0
- package/dist/api/routes/nouns.js +456 -0
- package/dist/api/routes/nouns.js.map +1 -0
- package/dist/api/routes/orgs.d.ts +17 -0
- package/dist/api/routes/orgs.d.ts.map +1 -0
- package/dist/api/routes/orgs.js +560 -0
- package/dist/api/routes/orgs.js.map +1 -0
- package/dist/api/routes/relationships.d.ts +30 -0
- package/dist/api/routes/relationships.d.ts.map +1 -0
- package/dist/api/routes/relationships.js +360 -0
- package/dist/api/routes/relationships.js.map +1 -0
- package/dist/api/routes/roles.d.ts +17 -0
- package/dist/api/routes/roles.d.ts.map +1 -0
- package/dist/api/routes/roles.js +721 -0
- package/dist/api/routes/roles.js.map +1 -0
- package/dist/api/routes/things.d.ts +27 -0
- package/dist/api/routes/things.d.ts.map +1 -0
- package/dist/api/routes/things.js +568 -0
- package/dist/api/routes/things.js.map +1 -0
- package/dist/api/routes/users.d.ts +17 -0
- package/dist/api/routes/users.d.ts.map +1 -0
- package/dist/api/routes/users.js +401 -0
- package/dist/api/routes/users.js.map +1 -0
- package/dist/api/routes/verbs.d.ts +31 -0
- package/dist/api/routes/verbs.d.ts.map +1 -0
- package/dist/api/routes/verbs.js +505 -0
- package/dist/api/routes/verbs.js.map +1 -0
- package/dist/api/routes/workflows.d.ts +44 -0
- package/dist/api/routes/workflows.d.ts.map +1 -0
- package/dist/api/routes/workflows.js +521 -0
- package/dist/api/routes/workflows.js.map +1 -0
- package/dist/api/types.d.ts +370 -0
- package/dist/api/types.d.ts.map +1 -0
- package/dist/api/types.js +11 -0
- package/dist/api/types.js.map +1 -0
- package/dist/db/cdc/events.d.ts +201 -0
- package/dist/db/cdc/events.d.ts.map +1 -0
- package/dist/db/cdc/events.js +271 -0
- package/dist/db/cdc/events.js.map +1 -0
- package/dist/db/cdc/index.d.ts +13 -0
- package/dist/db/cdc/index.d.ts.map +1 -0
- package/dist/db/cdc/index.js +16 -0
- package/dist/db/cdc/index.js.map +1 -0
- package/dist/db/cdc/replay.d.ts +388 -0
- package/dist/db/cdc/replay.d.ts.map +1 -0
- package/dist/db/cdc/replay.js +469 -0
- package/dist/db/cdc/replay.js.map +1 -0
- package/dist/db/cdc/storage.d.ts +567 -0
- package/dist/db/cdc/storage.d.ts.map +1 -0
- package/dist/db/cdc/storage.js +856 -0
- package/dist/db/cdc/storage.js.map +1 -0
- package/dist/db/cdc/streaming.d.ts +459 -0
- package/dist/db/cdc/streaming.d.ts.map +1 -0
- package/dist/db/cdc/streaming.js +636 -0
- package/dist/db/cdc/streaming.js.map +1 -0
- package/dist/db/collections/actions.d.ts +440 -0
- package/dist/db/collections/actions.d.ts.map +1 -0
- package/dist/db/collections/actions.js +631 -0
- package/dist/db/collections/actions.js.map +1 -0
- package/dist/db/collections/base.d.ts +342 -0
- package/dist/db/collections/base.d.ts.map +1 -0
- package/dist/db/collections/base.js +510 -0
- package/dist/db/collections/base.js.map +1 -0
- package/dist/db/collections/index.d.ts +50 -0
- package/dist/db/collections/index.d.ts.map +1 -0
- package/dist/db/collections/index.js +48 -0
- package/dist/db/collections/index.js.map +1 -0
- package/dist/db/collections/nouns.d.ts +260 -0
- package/dist/db/collections/nouns.d.ts.map +1 -0
- package/dist/db/collections/nouns.js +273 -0
- package/dist/db/collections/nouns.js.map +1 -0
- package/dist/db/collections/relationships.d.ts +484 -0
- package/dist/db/collections/relationships.d.ts.map +1 -0
- package/dist/db/collections/relationships.js +815 -0
- package/dist/db/collections/relationships.js.map +1 -0
- package/dist/db/collections/things.d.ts +439 -0
- package/dist/db/collections/things.d.ts.map +1 -0
- package/dist/db/collections/things.js +603 -0
- package/dist/db/collections/things.js.map +1 -0
- package/dist/db/collections/verbs.d.ts +308 -0
- package/dist/db/collections/verbs.d.ts.map +1 -0
- package/dist/db/collections/verbs.js +480 -0
- package/dist/db/collections/verbs.js.map +1 -0
- package/dist/db/index.d.ts +14 -0
- package/dist/db/index.d.ts.map +1 -0
- package/dist/db/index.js +23 -0
- package/dist/db/index.js.map +1 -0
- package/dist/db/storage/cold.d.ts +313 -0
- package/dist/db/storage/cold.d.ts.map +1 -0
- package/dist/db/storage/cold.js +319 -0
- package/dist/db/storage/cold.js.map +1 -0
- package/dist/db/storage/hot.d.ts +340 -0
- package/dist/db/storage/hot.d.ts.map +1 -0
- package/dist/db/storage/hot.js +333 -0
- package/dist/db/storage/hot.js.map +1 -0
- package/dist/db/storage/index.d.ts +242 -0
- package/dist/db/storage/index.d.ts.map +1 -0
- package/dist/db/storage/index.js +109 -0
- package/dist/db/storage/index.js.map +1 -0
- package/dist/db/storage/snapshots.d.ts +342 -0
- package/dist/db/storage/snapshots.d.ts.map +1 -0
- package/dist/db/storage/snapshots.js +298 -0
- package/dist/db/storage/snapshots.js.map +1 -0
- package/dist/db/storage/vortex.d.ts +324 -0
- package/dist/db/storage/vortex.d.ts.map +1 -0
- package/dist/db/storage/vortex.js +365 -0
- package/dist/db/storage/vortex.js.map +1 -0
- package/dist/db/storage/warm.d.ts +306 -0
- package/dist/db/storage/warm.d.ts.map +1 -0
- package/dist/db/storage/warm.js +339 -0
- package/dist/db/storage/warm.js.map +1 -0
- package/dist/do/DigitalObject.d.ts +595 -0
- package/dist/do/DigitalObject.d.ts.map +1 -0
- package/dist/do/DigitalObject.js +971 -0
- package/dist/do/DigitalObject.js.map +1 -0
- package/dist/do/business/financial/accounting.d.ts +436 -0
- package/dist/do/business/financial/accounting.d.ts.map +1 -0
- package/dist/do/business/financial/accounting.js +476 -0
- package/dist/do/business/financial/accounting.js.map +1 -0
- package/dist/do/business/financial/index.d.ts +15 -0
- package/dist/do/business/financial/index.d.ts.map +1 -0
- package/dist/do/business/financial/index.js +20 -0
- package/dist/do/business/financial/index.js.map +1 -0
- package/dist/do/business/financial/metrics.d.ts +370 -0
- package/dist/do/business/financial/metrics.d.ts.map +1 -0
- package/dist/do/business/financial/metrics.js +376 -0
- package/dist/do/business/financial/metrics.js.map +1 -0
- package/dist/do/business/financial/payments.d.ts +397 -0
- package/dist/do/business/financial/payments.d.ts.map +1 -0
- package/dist/do/business/financial/payments.js +395 -0
- package/dist/do/business/financial/payments.js.map +1 -0
- package/dist/do/business/financial/reports.d.ts +284 -0
- package/dist/do/business/financial/reports.d.ts.map +1 -0
- package/dist/do/business/financial/reports.js +347 -0
- package/dist/do/business/financial/reports.js.map +1 -0
- package/dist/do/business/financial/stripe.d.ts +254 -0
- package/dist/do/business/financial/stripe.d.ts.map +1 -0
- package/dist/do/business/financial/stripe.js +261 -0
- package/dist/do/business/financial/stripe.js.map +1 -0
- package/dist/do/business/financial/subscriptions.d.ts +402 -0
- package/dist/do/business/financial/subscriptions.d.ts.map +1 -0
- package/dist/do/business/financial/subscriptions.js +349 -0
- package/dist/do/business/financial/subscriptions.js.map +1 -0
- package/dist/do/business/index.d.ts +9 -0
- package/dist/do/business/index.d.ts.map +1 -0
- package/dist/do/business/index.js +10 -0
- package/dist/do/business/index.js.map +1 -0
- package/dist/do/colo/followers.d.ts +194 -0
- package/dist/do/colo/followers.d.ts.map +1 -0
- package/dist/do/colo/followers.js +224 -0
- package/dist/do/colo/followers.js.map +1 -0
- package/dist/do/colo/fork.d.ts +103 -0
- package/dist/do/colo/fork.d.ts.map +1 -0
- package/dist/do/colo/fork.js +143 -0
- package/dist/do/colo/fork.js.map +1 -0
- package/dist/do/colo/index.d.ts +181 -0
- package/dist/do/colo/index.d.ts.map +1 -0
- package/dist/do/colo/index.js +145 -0
- package/dist/do/colo/index.js.map +1 -0
- package/dist/do/colo/info.d.ts +106 -0
- package/dist/do/colo/info.d.ts.map +1 -0
- package/dist/do/colo/info.js +196 -0
- package/dist/do/colo/info.js.map +1 -0
- package/dist/do/colo/migrate.d.ts +161 -0
- package/dist/do/colo/migrate.d.ts.map +1 -0
- package/dist/do/colo/migrate.js +190 -0
- package/dist/do/colo/migrate.js.map +1 -0
- package/dist/do/colo/routing.d.ts +182 -0
- package/dist/do/colo/routing.d.ts.map +1 -0
- package/dist/do/colo/routing.js +254 -0
- package/dist/do/colo/routing.js.map +1 -0
- package/dist/do/domains/dns.d.ts +269 -0
- package/dist/do/domains/dns.d.ts.map +1 -0
- package/dist/do/domains/dns.js +215 -0
- package/dist/do/domains/dns.js.map +1 -0
- package/dist/do/domains/index.d.ts +40 -0
- package/dist/do/domains/index.d.ts.map +1 -0
- package/dist/do/domains/index.js +61 -0
- package/dist/do/domains/index.js.map +1 -0
- package/dist/do/domains/routing.d.ts +263 -0
- package/dist/do/domains/routing.d.ts.map +1 -0
- package/dist/do/domains/routing.js +362 -0
- package/dist/do/domains/routing.js.map +1 -0
- package/dist/do/domains/ssl.d.ts +217 -0
- package/dist/do/domains/ssl.d.ts.map +1 -0
- package/dist/do/domains/ssl.js +231 -0
- package/dist/do/domains/ssl.js.map +1 -0
- package/dist/do/domains/subdomains.d.ts +207 -0
- package/dist/do/domains/subdomains.d.ts.map +1 -0
- package/dist/do/domains/subdomains.js +223 -0
- package/dist/do/domains/subdomains.js.map +1 -0
- package/dist/do/domains/tlds.d.ts +175 -0
- package/dist/do/domains/tlds.d.ts.map +1 -0
- package/dist/do/domains/tlds.js +188 -0
- package/dist/do/domains/tlds.js.map +1 -0
- package/dist/do/domains/validation.d.ts +164 -0
- package/dist/do/domains/validation.d.ts.map +1 -0
- package/dist/do/domains/validation.js +290 -0
- package/dist/do/domains/validation.js.map +1 -0
- package/dist/do/hibernation.d.ts +385 -0
- package/dist/do/hibernation.d.ts.map +1 -0
- package/dist/do/hibernation.js +518 -0
- package/dist/do/hibernation.js.map +1 -0
- package/dist/do/index.d.ts +19 -0
- package/dist/do/index.d.ts.map +1 -0
- package/dist/do/index.js +23 -0
- package/dist/do/index.js.map +1 -0
- package/dist/do/state.d.ts +336 -0
- package/dist/do/state.d.ts.map +1 -0
- package/dist/do/state.js +290 -0
- package/dist/do/state.js.map +1 -0
- package/dist/index.d.ts +44 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +89 -0
- package/dist/index.js.map +1 -0
- package/dist/rpc/client.d.ts +426 -0
- package/dist/rpc/client.d.ts.map +1 -0
- package/dist/rpc/client.js +826 -0
- package/dist/rpc/client.js.map +1 -0
- package/dist/rpc/index.d.ts +19 -0
- package/dist/rpc/index.d.ts.map +1 -0
- package/dist/rpc/index.js +23 -0
- package/dist/rpc/index.js.map +1 -0
- package/dist/rpc/methods.d.ts +364 -0
- package/dist/rpc/methods.d.ts.map +1 -0
- package/dist/rpc/methods.js +557 -0
- package/dist/rpc/methods.js.map +1 -0
- package/dist/rpc/protocol.d.ts +310 -0
- package/dist/rpc/protocol.d.ts.map +1 -0
- package/dist/rpc/protocol.js +672 -0
- package/dist/rpc/protocol.js.map +1 -0
- package/dist/rpc/routes.d.ts +332 -0
- package/dist/rpc/routes.d.ts.map +1 -0
- package/dist/rpc/routes.js +633 -0
- package/dist/rpc/routes.js.map +1 -0
- package/dist/rpc/server.d.ts +380 -0
- package/dist/rpc/server.d.ts.map +1 -0
- package/dist/rpc/server.js +850 -0
- package/dist/rpc/server.js.map +1 -0
- package/dist/sdk/auth.d.ts +201 -0
- package/dist/sdk/auth.d.ts.map +1 -0
- package/dist/sdk/auth.js +343 -0
- package/dist/sdk/auth.js.map +1 -0
- package/dist/sdk/client.d.ts +123 -0
- package/dist/sdk/client.d.ts.map +1 -0
- package/dist/sdk/client.js +403 -0
- package/dist/sdk/client.js.map +1 -0
- package/dist/sdk/index.d.ts +123 -0
- package/dist/sdk/index.d.ts.map +1 -0
- package/dist/sdk/index.js +230 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sdk/rpc.d.ts +275 -0
- package/dist/sdk/rpc.d.ts.map +1 -0
- package/dist/sdk/rpc.js +249 -0
- package/dist/sdk/rpc.js.map +1 -0
- package/dist/sdk/transport.d.ts +283 -0
- package/dist/sdk/transport.d.ts.map +1 -0
- package/dist/sdk/transport.js +661 -0
- package/dist/sdk/transport.js.map +1 -0
- package/dist/sdk/types.d.ts +265 -0
- package/dist/sdk/types.d.ts.map +1 -0
- package/dist/sdk/types.js +27 -0
- package/dist/sdk/types.js.map +1 -0
- package/dist/types/ai.d.ts +533 -0
- package/dist/types/ai.d.ts.map +1 -0
- package/dist/types/ai.js +18 -0
- package/dist/types/ai.js.map +1 -0
- package/dist/types/app.d.ts +371 -0
- package/dist/types/app.d.ts.map +1 -0
- package/dist/types/app.js +151 -0
- package/dist/types/app.js.map +1 -0
- package/dist/types/business.d.ts +482 -0
- package/dist/types/business.d.ts.map +1 -0
- package/dist/types/business.js +60 -0
- package/dist/types/business.js.map +1 -0
- package/dist/types/cascade.d.ts +323 -0
- package/dist/types/cascade.d.ts.map +1 -0
- package/dist/types/cascade.js +82 -0
- package/dist/types/cascade.js.map +1 -0
- package/dist/types/collections.d.ts +704 -0
- package/dist/types/collections.d.ts.map +1 -0
- package/dist/types/collections.js +23 -0
- package/dist/types/collections.js.map +1 -0
- package/dist/types/colo.d.ts +171 -0
- package/dist/types/colo.d.ts.map +1 -0
- package/dist/types/colo.js +63 -0
- package/dist/types/colo.js.map +1 -0
- package/dist/types/communication.d.ts +595 -0
- package/dist/types/communication.d.ts.map +1 -0
- package/dist/types/communication.js +16 -0
- package/dist/types/communication.js.map +1 -0
- package/dist/types/content.d.ts +286 -0
- package/dist/types/content.d.ts.map +1 -0
- package/dist/types/content.js +8 -0
- package/dist/types/content.js.map +1 -0
- package/dist/types/context.d.ts +407 -0
- package/dist/types/context.d.ts.map +1 -0
- package/dist/types/context.js +36 -0
- package/dist/types/context.js.map +1 -0
- package/dist/types/databases.d.ts +377 -0
- package/dist/types/databases.d.ts.map +1 -0
- package/dist/types/databases.js +14 -0
- package/dist/types/databases.js.map +1 -0
- package/dist/types/domains.d.ts +132 -0
- package/dist/types/domains.d.ts.map +1 -0
- package/dist/types/domains.js +107 -0
- package/dist/types/domains.js.map +1 -0
- package/dist/types/execution.d.ts +381 -0
- package/dist/types/execution.d.ts.map +1 -0
- package/dist/types/execution.js +40 -0
- package/dist/types/execution.js.map +1 -0
- package/dist/types/financial.d.ts +608 -0
- package/dist/types/financial.d.ts.map +1 -0
- package/dist/types/financial.js +12 -0
- package/dist/types/financial.js.map +1 -0
- package/dist/types/functions.d.ts +215 -0
- package/dist/types/functions.d.ts.map +1 -0
- package/dist/types/functions.js +15 -0
- package/dist/types/functions.js.map +1 -0
- package/dist/types/git.d.ts +299 -0
- package/dist/types/git.d.ts.map +1 -0
- package/dist/types/git.js +17 -0
- package/dist/types/git.js.map +1 -0
- package/dist/types/identity.d.ts +141 -0
- package/dist/types/identity.d.ts.map +1 -0
- package/dist/types/identity.js +54 -0
- package/dist/types/identity.js.map +1 -0
- package/dist/types/index.d.ts +40 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +65 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/integrations.d.ts +356 -0
- package/dist/types/integrations.d.ts.map +1 -0
- package/dist/types/integrations.js +19 -0
- package/dist/types/integrations.js.map +1 -0
- package/dist/types/mdxui.d.ts +1955 -0
- package/dist/types/mdxui.d.ts.map +1 -0
- package/dist/types/mdxui.js +751 -0
- package/dist/types/mdxui.js.map +1 -0
- package/dist/types/observability.d.ts +315 -0
- package/dist/types/observability.d.ts.map +1 -0
- package/dist/types/observability.js +13 -0
- package/dist/types/observability.js.map +1 -0
- package/dist/types/rpc.d.ts +339 -0
- package/dist/types/rpc.d.ts.map +1 -0
- package/dist/types/rpc.js +24 -0
- package/dist/types/rpc.js.map +1 -0
- package/dist/types/saas.d.ts +678 -0
- package/dist/types/saas.d.ts.map +1 -0
- package/dist/types/saas.js +59 -0
- package/dist/types/saas.js.map +1 -0
- package/dist/types/service.d.ts +676 -0
- package/dist/types/service.d.ts.map +1 -0
- package/dist/types/service.js +69 -0
- package/dist/types/service.js.map +1 -0
- package/dist/types/site.d.ts +317 -0
- package/dist/types/site.d.ts.map +1 -0
- package/dist/types/site.js +203 -0
- package/dist/types/site.js.map +1 -0
- package/dist/types/startup.d.ts +576 -0
- package/dist/types/startup.d.ts.map +1 -0
- package/dist/types/startup.js +59 -0
- package/dist/types/startup.js.map +1 -0
- package/dist/types/storage.d.ts +276 -0
- package/dist/types/storage.d.ts.map +1 -0
- package/dist/types/storage.js +35 -0
- package/dist/types/storage.js.map +1 -0
- package/dist/types/telephony.d.ts +458 -0
- package/dist/types/telephony.d.ts.map +1 -0
- package/dist/types/telephony.js +19 -0
- package/dist/types/telephony.js.map +1 -0
- package/dist/types/tenant.d.ts +708 -0
- package/dist/types/tenant.d.ts.map +1 -0
- package/dist/types/tenant.js +103 -0
- package/dist/types/tenant.js.map +1 -0
- package/dist/types/voice-ai.d.ts +459 -0
- package/dist/types/voice-ai.d.ts.map +1 -0
- package/dist/types/voice-ai.js +32 -0
- package/dist/types/voice-ai.js.map +1 -0
- package/package.json +143 -0
|
@@ -0,0 +1,850 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CapnWeb RPC Server
|
|
3
|
+
*
|
|
4
|
+
* Handles both WebSocket and HTTP transports for RPC communication.
|
|
5
|
+
* Implements Cloudflare Durable Object WebSocket hibernation for 95% cost savings.
|
|
6
|
+
*
|
|
7
|
+
* @module rpc/server
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```typescript
|
|
11
|
+
* import { RPCServer } from 'do/rpc/server'
|
|
12
|
+
* import { MethodRegistry } from 'do/rpc/methods'
|
|
13
|
+
*
|
|
14
|
+
* export class MyDurableObject {
|
|
15
|
+
* private rpc: RPCServer
|
|
16
|
+
*
|
|
17
|
+
* constructor(state: DurableObjectState, env: Env) {
|
|
18
|
+
* const registry = new MethodRegistry()
|
|
19
|
+
* // Register your methods...
|
|
20
|
+
*
|
|
21
|
+
* this.rpc = new RPCServer(state, env, registry)
|
|
22
|
+
* }
|
|
23
|
+
*
|
|
24
|
+
* async fetch(request: Request): Promise<Response> {
|
|
25
|
+
* return this.rpc.handleRequest(request)
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* // Hibernation handlers
|
|
29
|
+
* async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer) {
|
|
30
|
+
* return this.rpc.handleWebSocketMessage(ws, message)
|
|
31
|
+
* }
|
|
32
|
+
*
|
|
33
|
+
* async webSocketClose(ws: WebSocket, code: number, reason: string) {
|
|
34
|
+
* return this.rpc.handleWebSocketClose(ws, code, reason)
|
|
35
|
+
* }
|
|
36
|
+
*
|
|
37
|
+
* async webSocketError(ws: WebSocket, error: unknown) {
|
|
38
|
+
* return this.rpc.handleWebSocketError(ws, error)
|
|
39
|
+
* }
|
|
40
|
+
* }
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
import { RpcErrorCodes as ErrorCodes } from '../types/rpc';
|
|
44
|
+
export class RPCServer {
|
|
45
|
+
state;
|
|
46
|
+
env;
|
|
47
|
+
options;
|
|
48
|
+
connections;
|
|
49
|
+
wsToId;
|
|
50
|
+
methods;
|
|
51
|
+
rateLimitState;
|
|
52
|
+
/**
|
|
53
|
+
* Create a new RPC server
|
|
54
|
+
*
|
|
55
|
+
* @param options - Server configuration including state, env, and registry
|
|
56
|
+
*/
|
|
57
|
+
constructor(options) {
|
|
58
|
+
this.options = options || {};
|
|
59
|
+
this.state = options?.state;
|
|
60
|
+
this.env = options?.env || {};
|
|
61
|
+
this.connections = new Map();
|
|
62
|
+
this.wsToId = new Map();
|
|
63
|
+
this.methods = new Map();
|
|
64
|
+
this.rateLimitState = new Map();
|
|
65
|
+
}
|
|
66
|
+
// ===========================================================================
|
|
67
|
+
// Request Handling
|
|
68
|
+
// ===========================================================================
|
|
69
|
+
/**
|
|
70
|
+
* Handle an incoming HTTP request
|
|
71
|
+
*
|
|
72
|
+
* Routes to appropriate handler based on method and path:
|
|
73
|
+
* - GET /rpc - Schema discovery
|
|
74
|
+
* - GET /rpc/* - Method documentation
|
|
75
|
+
* - POST / or POST /rpc - Execute RPC
|
|
76
|
+
* - WebSocket upgrade on /rpc
|
|
77
|
+
*
|
|
78
|
+
* @param request - Incoming HTTP request
|
|
79
|
+
* @returns HTTP response
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```typescript
|
|
83
|
+
* async fetch(request: Request): Promise<Response> {
|
|
84
|
+
* return this.rpc.handleRequest(request)
|
|
85
|
+
* }
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
async handleRequest(request) {
|
|
89
|
+
const url = new URL(request.url);
|
|
90
|
+
const path = url.pathname;
|
|
91
|
+
// Check for WebSocket upgrade
|
|
92
|
+
const upgradeHeader = request.headers.get('Upgrade');
|
|
93
|
+
if (upgradeHeader?.toLowerCase() === 'websocket') {
|
|
94
|
+
return this.handleWebSocketUpgrade(request);
|
|
95
|
+
}
|
|
96
|
+
// Handle CORS preflight
|
|
97
|
+
if (request.method === 'OPTIONS') {
|
|
98
|
+
return this.handleCors();
|
|
99
|
+
}
|
|
100
|
+
// GET returns method info
|
|
101
|
+
if (request.method === 'GET') {
|
|
102
|
+
const methodList = this.getMethods();
|
|
103
|
+
return this.addCorsHeaders(new Response(JSON.stringify({ methods: methodList }), {
|
|
104
|
+
status: 200,
|
|
105
|
+
headers: { 'Content-Type': 'application/json' },
|
|
106
|
+
}));
|
|
107
|
+
}
|
|
108
|
+
// POST / or POST /rpc - Execute RPC
|
|
109
|
+
if (request.method === 'POST' && (path === '/' || path === '/rpc')) {
|
|
110
|
+
return this.handleHttpRpc(request);
|
|
111
|
+
}
|
|
112
|
+
return new Response('Not Found', { status: 404 });
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Handle WebSocket upgrade request
|
|
116
|
+
*
|
|
117
|
+
* Creates a WebSocket pair and accepts the connection.
|
|
118
|
+
* The connection will hibernate after the idle timeout.
|
|
119
|
+
*
|
|
120
|
+
* @param request - WebSocket upgrade request
|
|
121
|
+
* @returns Response with WebSocket
|
|
122
|
+
*/
|
|
123
|
+
async handleWebSocketUpgrade(request) {
|
|
124
|
+
const pair = new WebSocketPair();
|
|
125
|
+
const [client, server] = [pair[0], pair[1]];
|
|
126
|
+
const connectionId = crypto.randomUUID();
|
|
127
|
+
const now = Date.now();
|
|
128
|
+
const connState = {
|
|
129
|
+
id: connectionId,
|
|
130
|
+
ws: server,
|
|
131
|
+
status: 'open',
|
|
132
|
+
connectedAt: now,
|
|
133
|
+
lastMessageAt: now,
|
|
134
|
+
subscriptions: [],
|
|
135
|
+
queuedEvents: [],
|
|
136
|
+
};
|
|
137
|
+
this.connections.set(connectionId, connState);
|
|
138
|
+
this.wsToId.set(server, connectionId);
|
|
139
|
+
// Set up idle timer if hibernation is enabled
|
|
140
|
+
this.setupIdleTimer(connectionId);
|
|
141
|
+
server.accept?.();
|
|
142
|
+
return new Response(null, {
|
|
143
|
+
status: 101,
|
|
144
|
+
webSocket: client,
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Handle HTTP POST RPC request
|
|
149
|
+
*
|
|
150
|
+
* @param request - HTTP POST request with JSON body
|
|
151
|
+
* @returns JSON response with RPC result
|
|
152
|
+
*/
|
|
153
|
+
async handleHttpRpc(request) {
|
|
154
|
+
// Set up timeout wrapper if configured
|
|
155
|
+
const doHttpRpc = async () => {
|
|
156
|
+
// Check Content-Type
|
|
157
|
+
const contentType = request.headers.get('Content-Type') || '';
|
|
158
|
+
if (!contentType.includes('application/json')) {
|
|
159
|
+
return this.addCorsHeaders(new Response(JSON.stringify({
|
|
160
|
+
id: null,
|
|
161
|
+
error: { code: ErrorCodes.ParseError, message: 'Unsupported Media Type' },
|
|
162
|
+
}), { status: 415, headers: { 'Content-Type': 'application/json' } }));
|
|
163
|
+
}
|
|
164
|
+
// Check rate limit
|
|
165
|
+
if (this.options.rateLimit) {
|
|
166
|
+
const clientId = request.headers.get('CF-Connecting-IP') || 'default';
|
|
167
|
+
if (this.isRateLimited(clientId)) {
|
|
168
|
+
return this.addCorsHeaders(new Response(JSON.stringify({
|
|
169
|
+
id: null,
|
|
170
|
+
error: { code: ErrorCodes.RateLimited, message: 'Rate limit exceeded' },
|
|
171
|
+
}), { status: 429, headers: { 'Content-Type': 'application/json' } }));
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
let body;
|
|
175
|
+
try {
|
|
176
|
+
body = await request.text();
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return this.addCorsHeaders(new Response(JSON.stringify({
|
|
180
|
+
id: null,
|
|
181
|
+
error: { code: ErrorCodes.ParseError, message: 'Parse error: unable to read body' },
|
|
182
|
+
}), { status: 400, headers: { 'Content-Type': 'application/json' } }));
|
|
183
|
+
}
|
|
184
|
+
// Check payload size after reading body
|
|
185
|
+
if (this.options.maxPayloadSize && body.length > this.options.maxPayloadSize) {
|
|
186
|
+
return this.addCorsHeaders(new Response(JSON.stringify({
|
|
187
|
+
id: null,
|
|
188
|
+
error: { code: ErrorCodes.InvalidRequest, message: 'Payload Too Large' },
|
|
189
|
+
}), { status: 413, headers: { 'Content-Type': 'application/json' } }));
|
|
190
|
+
}
|
|
191
|
+
let parsed;
|
|
192
|
+
try {
|
|
193
|
+
parsed = JSON.parse(body);
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return this.addCorsHeaders(new Response(JSON.stringify({
|
|
197
|
+
id: null,
|
|
198
|
+
error: { code: ErrorCodes.ParseError, message: 'Parse error: invalid JSON' },
|
|
199
|
+
}), { status: 400, headers: { 'Content-Type': 'application/json' } }));
|
|
200
|
+
}
|
|
201
|
+
// Check if batch request
|
|
202
|
+
if (this.isBatchRequest(parsed)) {
|
|
203
|
+
const batchReq = parsed;
|
|
204
|
+
const responses = [];
|
|
205
|
+
for (const req of batchReq.requests) {
|
|
206
|
+
const response = await this.executeRequest(req);
|
|
207
|
+
responses.push(response);
|
|
208
|
+
if (batchReq.abortOnError && response.error) {
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const batchResponse = {
|
|
213
|
+
id: batchReq.id,
|
|
214
|
+
responses,
|
|
215
|
+
success: !responses.some((r) => r.error),
|
|
216
|
+
};
|
|
217
|
+
return this.addCorsHeaders(new Response(JSON.stringify(batchResponse), {
|
|
218
|
+
status: 200,
|
|
219
|
+
headers: { 'Content-Type': 'application/json' },
|
|
220
|
+
}));
|
|
221
|
+
}
|
|
222
|
+
// Single request
|
|
223
|
+
const rpcRequest = parsed;
|
|
224
|
+
// Validate request structure
|
|
225
|
+
if (!rpcRequest.id) {
|
|
226
|
+
return this.addCorsHeaders(new Response(JSON.stringify({
|
|
227
|
+
id: null,
|
|
228
|
+
error: { code: ErrorCodes.InvalidRequest, message: 'Invalid Request: missing id' },
|
|
229
|
+
}), { status: 400, headers: { 'Content-Type': 'application/json' } }));
|
|
230
|
+
}
|
|
231
|
+
if (!rpcRequest.method) {
|
|
232
|
+
return this.addCorsHeaders(new Response(JSON.stringify({
|
|
233
|
+
id: rpcRequest.id,
|
|
234
|
+
error: { code: ErrorCodes.InvalidRequest, message: 'Invalid Request: missing method' },
|
|
235
|
+
}), { status: 400, headers: { 'Content-Type': 'application/json' } }));
|
|
236
|
+
}
|
|
237
|
+
const response = await this.executeRequest(rpcRequest);
|
|
238
|
+
return this.addCorsHeaders(new Response(JSON.stringify(response), {
|
|
239
|
+
status: 200,
|
|
240
|
+
headers: { 'Content-Type': 'application/json' },
|
|
241
|
+
}));
|
|
242
|
+
};
|
|
243
|
+
// If methodTimeout is set, race the entire operation against a timeout
|
|
244
|
+
if (this.options.methodTimeout) {
|
|
245
|
+
const timeoutPromise = new Promise((resolve) => {
|
|
246
|
+
setTimeout(() => {
|
|
247
|
+
resolve(this.addCorsHeaders(new Response(JSON.stringify({
|
|
248
|
+
id: null,
|
|
249
|
+
error: { code: ErrorCodes.Timeout, message: 'Method timeout' },
|
|
250
|
+
}), { status: 200, headers: { 'Content-Type': 'application/json' } })));
|
|
251
|
+
}, this.options.methodTimeout);
|
|
252
|
+
});
|
|
253
|
+
return Promise.race([doHttpRpc(), timeoutPromise]);
|
|
254
|
+
}
|
|
255
|
+
return doHttpRpc();
|
|
256
|
+
}
|
|
257
|
+
// ===========================================================================
|
|
258
|
+
// WebSocket Hibernation Handlers
|
|
259
|
+
// ===========================================================================
|
|
260
|
+
/**
|
|
261
|
+
* Handle WebSocket message (hibernation callback)
|
|
262
|
+
*
|
|
263
|
+
* Called by Cloudflare when a message is received on a hibernated WebSocket.
|
|
264
|
+
*
|
|
265
|
+
* @param ws - WebSocket that received the message
|
|
266
|
+
* @param message - Message content (string or ArrayBuffer)
|
|
267
|
+
*
|
|
268
|
+
* @example
|
|
269
|
+
* ```typescript
|
|
270
|
+
* async webSocketMessage(ws: WebSocket, message: string | ArrayBuffer) {
|
|
271
|
+
* return this.rpc.handleWebSocketMessage(ws, message)
|
|
272
|
+
* }
|
|
273
|
+
* ```
|
|
274
|
+
*/
|
|
275
|
+
async handleWebSocketMessage(ws, message) {
|
|
276
|
+
const connectionId = this.wsToId.get(ws);
|
|
277
|
+
const connState = connectionId ? this.connections.get(connectionId) : undefined;
|
|
278
|
+
// Reset idle timer on activity
|
|
279
|
+
if (connectionId) {
|
|
280
|
+
this.resetIdleTimer(connectionId);
|
|
281
|
+
}
|
|
282
|
+
// Parse message
|
|
283
|
+
let parsed;
|
|
284
|
+
try {
|
|
285
|
+
const msgStr = typeof message === 'string' ? message : new TextDecoder().decode(message);
|
|
286
|
+
parsed = JSON.parse(msgStr);
|
|
287
|
+
}
|
|
288
|
+
catch {
|
|
289
|
+
const errorResponse = {
|
|
290
|
+
id: '',
|
|
291
|
+
error: { code: ErrorCodes.ParseError, message: 'Parse error: invalid JSON' },
|
|
292
|
+
};
|
|
293
|
+
ws.send(JSON.stringify(errorResponse));
|
|
294
|
+
return;
|
|
295
|
+
}
|
|
296
|
+
// Execute and respond
|
|
297
|
+
const response = await this.executeRequest(parsed, connState?.data);
|
|
298
|
+
ws.send(JSON.stringify(response));
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Handle WebSocket close (hibernation callback)
|
|
302
|
+
*
|
|
303
|
+
* @param ws - WebSocket that was closed
|
|
304
|
+
* @param code - Close code
|
|
305
|
+
* @param reason - Close reason
|
|
306
|
+
*/
|
|
307
|
+
async handleWebSocketClose(ws, code, reason) {
|
|
308
|
+
const connectionId = this.wsToId.get(ws);
|
|
309
|
+
if (connectionId) {
|
|
310
|
+
const connState = this.connections.get(connectionId);
|
|
311
|
+
if (connState) {
|
|
312
|
+
connState.status = 'closed';
|
|
313
|
+
if (connState.idleTimer)
|
|
314
|
+
clearTimeout(connState.idleTimer);
|
|
315
|
+
if (connState.hibernationTimer)
|
|
316
|
+
clearTimeout(connState.hibernationTimer);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
/**
|
|
321
|
+
* Handle WebSocket error (hibernation callback)
|
|
322
|
+
*
|
|
323
|
+
* @param ws - WebSocket that errored
|
|
324
|
+
* @param error - Error that occurred
|
|
325
|
+
*/
|
|
326
|
+
async handleWebSocketError(ws, error) {
|
|
327
|
+
const connectionId = this.wsToId.get(ws);
|
|
328
|
+
if (connectionId) {
|
|
329
|
+
const connState = this.connections.get(connectionId);
|
|
330
|
+
if (connState) {
|
|
331
|
+
connState.status = 'closed';
|
|
332
|
+
if (connState.idleTimer)
|
|
333
|
+
clearTimeout(connState.idleTimer);
|
|
334
|
+
if (connState.hibernationTimer)
|
|
335
|
+
clearTimeout(connState.hibernationTimer);
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
// ===========================================================================
|
|
340
|
+
// Connection Management
|
|
341
|
+
// ===========================================================================
|
|
342
|
+
/**
|
|
343
|
+
* Get all active WebSocket connections
|
|
344
|
+
*
|
|
345
|
+
* @returns Array of connection states
|
|
346
|
+
*/
|
|
347
|
+
getConnections() {
|
|
348
|
+
return Array.from(this.connections.values()).map((c) => ({
|
|
349
|
+
id: c.id,
|
|
350
|
+
status: c.status,
|
|
351
|
+
connectedAt: c.connectedAt,
|
|
352
|
+
hibernatedAt: c.hibernatedAt,
|
|
353
|
+
lastMessageAt: c.lastMessageAt,
|
|
354
|
+
subscriptions: c.subscriptions,
|
|
355
|
+
data: c.data,
|
|
356
|
+
}));
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Get a specific connection by ID
|
|
360
|
+
*
|
|
361
|
+
* @param id - Connection ID
|
|
362
|
+
* @returns Connection state or undefined
|
|
363
|
+
*/
|
|
364
|
+
getConnection(id) {
|
|
365
|
+
const conn = this.connections.get(id);
|
|
366
|
+
if (!conn)
|
|
367
|
+
return undefined;
|
|
368
|
+
return {
|
|
369
|
+
id: conn.id,
|
|
370
|
+
status: conn.status,
|
|
371
|
+
connectedAt: conn.connectedAt,
|
|
372
|
+
hibernatedAt: conn.hibernatedAt,
|
|
373
|
+
lastMessageAt: conn.lastMessageAt,
|
|
374
|
+
subscriptions: conn.subscriptions,
|
|
375
|
+
data: conn.data,
|
|
376
|
+
};
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Broadcast a message to all connected clients
|
|
380
|
+
*
|
|
381
|
+
* @param message - Message to broadcast
|
|
382
|
+
* @param filter - Optional filter function
|
|
383
|
+
*/
|
|
384
|
+
async broadcast(message, filter) {
|
|
385
|
+
for (const conn of this.connections.values()) {
|
|
386
|
+
if (conn.status !== 'open')
|
|
387
|
+
continue;
|
|
388
|
+
const wsState = {
|
|
389
|
+
id: conn.id,
|
|
390
|
+
status: conn.status,
|
|
391
|
+
connectedAt: conn.connectedAt,
|
|
392
|
+
lastMessageAt: conn.lastMessageAt,
|
|
393
|
+
subscriptions: conn.subscriptions,
|
|
394
|
+
data: conn.data,
|
|
395
|
+
};
|
|
396
|
+
if (filter && !filter(wsState))
|
|
397
|
+
continue;
|
|
398
|
+
conn.ws.send(JSON.stringify(message));
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
/**
|
|
402
|
+
* Send a message to a specific connection
|
|
403
|
+
*
|
|
404
|
+
* @param connectionId - Target connection ID
|
|
405
|
+
* @param message - Message to send
|
|
406
|
+
*/
|
|
407
|
+
async send(connectionId, message) {
|
|
408
|
+
const conn = this.connections.get(connectionId);
|
|
409
|
+
if (conn && conn.status === 'open') {
|
|
410
|
+
conn.ws.send(JSON.stringify(message));
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Close a connection
|
|
415
|
+
*
|
|
416
|
+
* @param connectionId - Connection to close
|
|
417
|
+
* @param code - Close code
|
|
418
|
+
* @param reason - Close reason
|
|
419
|
+
*/
|
|
420
|
+
async closeConnection(connectionId, code, reason) {
|
|
421
|
+
const conn = this.connections.get(connectionId);
|
|
422
|
+
if (conn) {
|
|
423
|
+
conn.ws.close(code, reason);
|
|
424
|
+
conn.status = 'closed';
|
|
425
|
+
if (conn.idleTimer)
|
|
426
|
+
clearTimeout(conn.idleTimer);
|
|
427
|
+
if (conn.hibernationTimer)
|
|
428
|
+
clearTimeout(conn.hibernationTimer);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
// ===========================================================================
|
|
432
|
+
// Method Registration
|
|
433
|
+
// ===========================================================================
|
|
434
|
+
/**
|
|
435
|
+
* Register a method handler
|
|
436
|
+
*
|
|
437
|
+
* @param name - Method name (e.g., 'do.things.list')
|
|
438
|
+
* @param handler - Handler function
|
|
439
|
+
*/
|
|
440
|
+
registerMethod(name, handler) {
|
|
441
|
+
this.methods.set(name, handler);
|
|
442
|
+
}
|
|
443
|
+
/**
|
|
444
|
+
* Unregister a method handler
|
|
445
|
+
*
|
|
446
|
+
* @param name - Method name to unregister
|
|
447
|
+
*/
|
|
448
|
+
unregisterMethod(name) {
|
|
449
|
+
this.methods.delete(name);
|
|
450
|
+
}
|
|
451
|
+
/**
|
|
452
|
+
* Get all registered method names
|
|
453
|
+
*
|
|
454
|
+
* @returns Array of method names
|
|
455
|
+
*/
|
|
456
|
+
getMethods() {
|
|
457
|
+
return Array.from(this.methods.keys());
|
|
458
|
+
}
|
|
459
|
+
// ===========================================================================
|
|
460
|
+
// Subscription and Events
|
|
461
|
+
// ===========================================================================
|
|
462
|
+
/**
|
|
463
|
+
* Subscribe a connection to a channel
|
|
464
|
+
*
|
|
465
|
+
* @param connectionId - Connection ID
|
|
466
|
+
* @param channel - Channel name
|
|
467
|
+
*/
|
|
468
|
+
async subscribe(connectionId, channel) {
|
|
469
|
+
const conn = this.connections.get(connectionId);
|
|
470
|
+
if (conn && !conn.subscriptions.includes(channel)) {
|
|
471
|
+
conn.subscriptions.push(channel);
|
|
472
|
+
}
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Emit an event to all subscribers of a channel
|
|
476
|
+
*
|
|
477
|
+
* @param channel - Channel name
|
|
478
|
+
* @param data - Event data
|
|
479
|
+
*/
|
|
480
|
+
async emit(channel, data) {
|
|
481
|
+
for (const conn of this.connections.values()) {
|
|
482
|
+
if (!conn.subscriptions.includes(channel))
|
|
483
|
+
continue;
|
|
484
|
+
if (conn.status === 'hibernating') {
|
|
485
|
+
// Queue event for later delivery
|
|
486
|
+
conn.queuedEvents.push({ channel, data });
|
|
487
|
+
}
|
|
488
|
+
else if (conn.status === 'open') {
|
|
489
|
+
const event = {
|
|
490
|
+
id: '',
|
|
491
|
+
result: { channel, data },
|
|
492
|
+
};
|
|
493
|
+
conn.ws.send(JSON.stringify(event));
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
// ===========================================================================
|
|
498
|
+
// Connection Registration
|
|
499
|
+
// ===========================================================================
|
|
500
|
+
/**
|
|
501
|
+
* Register a connection
|
|
502
|
+
*
|
|
503
|
+
* @param connectionId - Unique connection ID
|
|
504
|
+
* @param ws - WebSocket instance
|
|
505
|
+
*/
|
|
506
|
+
registerConnection(connectionId, ws) {
|
|
507
|
+
const now = Date.now();
|
|
508
|
+
const connState = {
|
|
509
|
+
id: connectionId,
|
|
510
|
+
ws,
|
|
511
|
+
status: 'open',
|
|
512
|
+
connectedAt: now,
|
|
513
|
+
lastMessageAt: now,
|
|
514
|
+
subscriptions: [],
|
|
515
|
+
queuedEvents: [],
|
|
516
|
+
};
|
|
517
|
+
this.connections.set(connectionId, connState);
|
|
518
|
+
this.wsToId.set(ws, connectionId);
|
|
519
|
+
this.setupIdleTimer(connectionId);
|
|
520
|
+
}
|
|
521
|
+
/**
|
|
522
|
+
* Set custom data for a connection
|
|
523
|
+
*
|
|
524
|
+
* @param connectionId - Connection ID
|
|
525
|
+
* @param data - Custom data to store
|
|
526
|
+
*/
|
|
527
|
+
setConnectionData(connectionId, data) {
|
|
528
|
+
const conn = this.connections.get(connectionId);
|
|
529
|
+
if (conn) {
|
|
530
|
+
conn.data = data;
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
/**
|
|
534
|
+
* Wake a hibernated connection
|
|
535
|
+
*
|
|
536
|
+
* @param ws - WebSocket instance
|
|
537
|
+
* @returns Connection ID
|
|
538
|
+
*/
|
|
539
|
+
async wakeConnection(ws) {
|
|
540
|
+
// Try to restore from attachment
|
|
541
|
+
let connectionId = this.wsToId.get(ws);
|
|
542
|
+
let restored;
|
|
543
|
+
try {
|
|
544
|
+
restored = ws.deserializeAttachment?.();
|
|
545
|
+
}
|
|
546
|
+
catch {
|
|
547
|
+
// Ignore
|
|
548
|
+
}
|
|
549
|
+
if (!connectionId) {
|
|
550
|
+
connectionId = crypto.randomUUID();
|
|
551
|
+
}
|
|
552
|
+
const existing = this.connections.get(connectionId);
|
|
553
|
+
if (existing) {
|
|
554
|
+
existing.status = 'open';
|
|
555
|
+
existing.hibernatedAt = undefined;
|
|
556
|
+
if (restored) {
|
|
557
|
+
existing.data = { ...existing.data, ...restored };
|
|
558
|
+
}
|
|
559
|
+
// Clear hibernation timer
|
|
560
|
+
if (existing.hibernationTimer) {
|
|
561
|
+
clearTimeout(existing.hibernationTimer);
|
|
562
|
+
existing.hibernationTimer = undefined;
|
|
563
|
+
}
|
|
564
|
+
// Deliver queued events
|
|
565
|
+
for (const event of existing.queuedEvents) {
|
|
566
|
+
const response = {
|
|
567
|
+
id: '',
|
|
568
|
+
result: { channel: event.channel, data: event.data },
|
|
569
|
+
};
|
|
570
|
+
ws.send(JSON.stringify(response));
|
|
571
|
+
}
|
|
572
|
+
existing.queuedEvents = [];
|
|
573
|
+
this.setupIdleTimer(connectionId);
|
|
574
|
+
}
|
|
575
|
+
else {
|
|
576
|
+
// New connection
|
|
577
|
+
const now = Date.now();
|
|
578
|
+
const connState = {
|
|
579
|
+
id: connectionId,
|
|
580
|
+
ws,
|
|
581
|
+
status: 'open',
|
|
582
|
+
connectedAt: now,
|
|
583
|
+
lastMessageAt: now,
|
|
584
|
+
subscriptions: [],
|
|
585
|
+
data: restored,
|
|
586
|
+
queuedEvents: [],
|
|
587
|
+
};
|
|
588
|
+
this.connections.set(connectionId, connState);
|
|
589
|
+
this.wsToId.set(ws, connectionId);
|
|
590
|
+
this.setupIdleTimer(connectionId);
|
|
591
|
+
}
|
|
592
|
+
return connectionId;
|
|
593
|
+
}
|
|
594
|
+
// ===========================================================================
|
|
595
|
+
// Fetch Handler
|
|
596
|
+
// ===========================================================================
|
|
597
|
+
/**
|
|
598
|
+
* Handle an incoming HTTP request (convenience method)
|
|
599
|
+
*
|
|
600
|
+
* Alias for handleRequest for Worker fetch handler compatibility.
|
|
601
|
+
*
|
|
602
|
+
* @param request - Incoming HTTP request
|
|
603
|
+
* @returns HTTP response
|
|
604
|
+
*/
|
|
605
|
+
async fetch(request) {
|
|
606
|
+
return this.handleRequest(request);
|
|
607
|
+
}
|
|
608
|
+
// ===========================================================================
|
|
609
|
+
// Internal Helpers
|
|
610
|
+
// ===========================================================================
|
|
611
|
+
/**
|
|
612
|
+
* Build method context from request
|
|
613
|
+
*
|
|
614
|
+
* @param request - Optional HTTP request
|
|
615
|
+
* @param ws - Optional WebSocket
|
|
616
|
+
* @returns Method context
|
|
617
|
+
*/
|
|
618
|
+
buildContext(request, ws, meta) {
|
|
619
|
+
return {
|
|
620
|
+
state: this.state,
|
|
621
|
+
env: this.env,
|
|
622
|
+
meta: meta,
|
|
623
|
+
websocket: ws,
|
|
624
|
+
request,
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Handle CORS preflight request
|
|
629
|
+
*
|
|
630
|
+
* @returns CORS preflight response
|
|
631
|
+
*/
|
|
632
|
+
handleCors() {
|
|
633
|
+
return new Response(null, {
|
|
634
|
+
status: 204,
|
|
635
|
+
headers: {
|
|
636
|
+
'Access-Control-Allow-Origin': '*',
|
|
637
|
+
'Access-Control-Allow-Methods': 'GET, POST, OPTIONS',
|
|
638
|
+
'Access-Control-Allow-Headers': 'Content-Type',
|
|
639
|
+
'Access-Control-Max-Age': '86400',
|
|
640
|
+
},
|
|
641
|
+
});
|
|
642
|
+
}
|
|
643
|
+
/**
|
|
644
|
+
* Add CORS headers to response
|
|
645
|
+
*
|
|
646
|
+
* @param response - Response to modify
|
|
647
|
+
* @returns Response with CORS headers
|
|
648
|
+
*/
|
|
649
|
+
addCorsHeaders(response) {
|
|
650
|
+
const newHeaders = new Headers(response.headers);
|
|
651
|
+
newHeaders.set('Access-Control-Allow-Origin', '*');
|
|
652
|
+
return new Response(response.body, {
|
|
653
|
+
status: response.status,
|
|
654
|
+
statusText: response.statusText,
|
|
655
|
+
headers: newHeaders,
|
|
656
|
+
});
|
|
657
|
+
}
|
|
658
|
+
/**
|
|
659
|
+
* Check if a request is a batch request
|
|
660
|
+
*/
|
|
661
|
+
isBatchRequest(parsed) {
|
|
662
|
+
return (typeof parsed === 'object' &&
|
|
663
|
+
parsed !== null &&
|
|
664
|
+
'requests' in parsed &&
|
|
665
|
+
Array.isArray(parsed.requests));
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Execute a single RPC request
|
|
669
|
+
*/
|
|
670
|
+
async executeRequest(request, connectionData) {
|
|
671
|
+
const startTime = Date.now();
|
|
672
|
+
const meta = { ...request.meta };
|
|
673
|
+
// Look up handler
|
|
674
|
+
let handler = this.methods.get(request.method);
|
|
675
|
+
// Check for wildcard handlers
|
|
676
|
+
if (!handler) {
|
|
677
|
+
const parts = request.method.split('.');
|
|
678
|
+
for (let i = parts.length - 1; i > 0; i--) {
|
|
679
|
+
const wildcardKey = parts.slice(0, i).join('.') + '.*';
|
|
680
|
+
handler = this.methods.get(wildcardKey);
|
|
681
|
+
if (handler)
|
|
682
|
+
break;
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
if (!handler) {
|
|
686
|
+
return {
|
|
687
|
+
id: request.id,
|
|
688
|
+
error: { code: ErrorCodes.MethodNotFound, message: `Method not found: ${request.method}` },
|
|
689
|
+
meta: { ...meta, duration: Date.now() - startTime },
|
|
690
|
+
};
|
|
691
|
+
}
|
|
692
|
+
try {
|
|
693
|
+
// Execute handler
|
|
694
|
+
const result = await handler(request.params, this.buildContext(undefined, undefined, meta));
|
|
695
|
+
return {
|
|
696
|
+
id: request.id,
|
|
697
|
+
result,
|
|
698
|
+
meta: { ...meta, duration: Date.now() - startTime },
|
|
699
|
+
};
|
|
700
|
+
}
|
|
701
|
+
catch (error) {
|
|
702
|
+
// Handle RPC errors thrown by handler
|
|
703
|
+
if (typeof error === 'object' && error !== null && 'code' in error) {
|
|
704
|
+
const rpcError = error;
|
|
705
|
+
// Hide internal error details in production
|
|
706
|
+
if (this.env.NODE_ENV === 'production' && rpcError.code === ErrorCodes.InternalError) {
|
|
707
|
+
return {
|
|
708
|
+
id: request.id,
|
|
709
|
+
error: { code: ErrorCodes.InternalError, message: 'Internal error' },
|
|
710
|
+
meta: { ...meta, duration: Date.now() - startTime },
|
|
711
|
+
};
|
|
712
|
+
}
|
|
713
|
+
return {
|
|
714
|
+
id: request.id,
|
|
715
|
+
error: {
|
|
716
|
+
code: rpcError.code,
|
|
717
|
+
message: rpcError.message || 'Error',
|
|
718
|
+
data: rpcError.data,
|
|
719
|
+
},
|
|
720
|
+
meta: { ...meta, duration: Date.now() - startTime },
|
|
721
|
+
};
|
|
722
|
+
}
|
|
723
|
+
// Handle regular errors
|
|
724
|
+
const err = error;
|
|
725
|
+
// Hide internal error details in production
|
|
726
|
+
if (this.env.NODE_ENV === 'production') {
|
|
727
|
+
return {
|
|
728
|
+
id: request.id,
|
|
729
|
+
error: { code: ErrorCodes.InternalError, message: 'Internal error' },
|
|
730
|
+
meta: { ...meta, duration: Date.now() - startTime },
|
|
731
|
+
};
|
|
732
|
+
}
|
|
733
|
+
return {
|
|
734
|
+
id: request.id,
|
|
735
|
+
error: {
|
|
736
|
+
code: err.code || ErrorCodes.InternalError,
|
|
737
|
+
message: err.message || 'Internal error',
|
|
738
|
+
data: err.data,
|
|
739
|
+
},
|
|
740
|
+
meta: { ...meta, duration: Date.now() - startTime },
|
|
741
|
+
};
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
/**
|
|
745
|
+
* Set up idle timer for hibernation
|
|
746
|
+
*/
|
|
747
|
+
setupIdleTimer(connectionId) {
|
|
748
|
+
if (!this.options.hibernation?.idleTimeout)
|
|
749
|
+
return;
|
|
750
|
+
const conn = this.connections.get(connectionId);
|
|
751
|
+
if (!conn)
|
|
752
|
+
return;
|
|
753
|
+
// Clear existing timer
|
|
754
|
+
if (conn.idleTimer) {
|
|
755
|
+
clearTimeout(conn.idleTimer);
|
|
756
|
+
}
|
|
757
|
+
conn.idleTimer = setTimeout(() => {
|
|
758
|
+
this.hibernateConnection(connectionId);
|
|
759
|
+
}, this.options.hibernation.idleTimeout);
|
|
760
|
+
}
|
|
761
|
+
/**
|
|
762
|
+
* Reset idle timer on activity
|
|
763
|
+
*/
|
|
764
|
+
resetIdleTimer(connectionId) {
|
|
765
|
+
const conn = this.connections.get(connectionId);
|
|
766
|
+
if (!conn)
|
|
767
|
+
return;
|
|
768
|
+
conn.lastMessageAt = Date.now();
|
|
769
|
+
this.setupIdleTimer(connectionId);
|
|
770
|
+
}
|
|
771
|
+
/**
|
|
772
|
+
* Hibernate a connection
|
|
773
|
+
*/
|
|
774
|
+
hibernateConnection(connectionId) {
|
|
775
|
+
const conn = this.connections.get(connectionId);
|
|
776
|
+
if (!conn || conn.status !== 'open')
|
|
777
|
+
return;
|
|
778
|
+
conn.status = 'hibernating';
|
|
779
|
+
conn.hibernatedAt = Date.now();
|
|
780
|
+
// Serialize attachment
|
|
781
|
+
try {
|
|
782
|
+
;
|
|
783
|
+
conn.ws.serializeAttachment?.({
|
|
784
|
+
connectionId: conn.id,
|
|
785
|
+
subscriptions: conn.subscriptions,
|
|
786
|
+
data: conn.data,
|
|
787
|
+
});
|
|
788
|
+
}
|
|
789
|
+
catch {
|
|
790
|
+
// Ignore
|
|
791
|
+
}
|
|
792
|
+
// Set up max hibernation timer if configured
|
|
793
|
+
if (this.options.hibernation?.maxHibernationDuration) {
|
|
794
|
+
conn.hibernationTimer = setTimeout(() => {
|
|
795
|
+
conn.status = 'closed';
|
|
796
|
+
try {
|
|
797
|
+
conn.ws.close(1000, 'Max hibernation duration exceeded');
|
|
798
|
+
}
|
|
799
|
+
catch {
|
|
800
|
+
// Ignore
|
|
801
|
+
}
|
|
802
|
+
}, this.options.hibernation.maxHibernationDuration);
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
/**
|
|
806
|
+
* Check if client is rate limited
|
|
807
|
+
*/
|
|
808
|
+
isRateLimited(clientId) {
|
|
809
|
+
if (!this.options.rateLimit)
|
|
810
|
+
return false;
|
|
811
|
+
const now = Date.now();
|
|
812
|
+
const state = this.rateLimitState.get(clientId);
|
|
813
|
+
if (!state || now - state.windowStart > this.options.rateLimit.windowMs) {
|
|
814
|
+
this.rateLimitState.set(clientId, { count: 1, windowStart: now });
|
|
815
|
+
return false;
|
|
816
|
+
}
|
|
817
|
+
state.count++;
|
|
818
|
+
return state.count > this.options.rateLimit.maxRequests;
|
|
819
|
+
}
|
|
820
|
+
}
|
|
821
|
+
// =============================================================================
|
|
822
|
+
// Factory Functions
|
|
823
|
+
// =============================================================================
|
|
824
|
+
/**
|
|
825
|
+
* Create an RPC server with default configuration
|
|
826
|
+
*
|
|
827
|
+
* @param options - Server options (optional)
|
|
828
|
+
* @returns Configured RPC server
|
|
829
|
+
*/
|
|
830
|
+
export function createRPCServer(options) {
|
|
831
|
+
return new RPCServer(options);
|
|
832
|
+
}
|
|
833
|
+
/**
|
|
834
|
+
* Create method context from Durable Object state
|
|
835
|
+
*
|
|
836
|
+
* Utility for building context outside of server class.
|
|
837
|
+
*
|
|
838
|
+
* @param state - Durable Object state
|
|
839
|
+
* @param env - Environment bindings
|
|
840
|
+
* @param meta - Optional metadata
|
|
841
|
+
* @returns Method context
|
|
842
|
+
*/
|
|
843
|
+
export function createMethodContext(state, env, meta) {
|
|
844
|
+
return {
|
|
845
|
+
state,
|
|
846
|
+
env,
|
|
847
|
+
meta,
|
|
848
|
+
};
|
|
849
|
+
}
|
|
850
|
+
//# sourceMappingURL=server.js.map
|