@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,971 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DigitalObject - Base class for all Digital Objects
|
|
3
|
+
*
|
|
4
|
+
* This is the foundational class that all DOs inherit from. It provides:
|
|
5
|
+
* - Core identity management ($id, $type, $context, $version)
|
|
6
|
+
* - State management via DO SQLite
|
|
7
|
+
* - Hibernation support (Agents SDK pattern)
|
|
8
|
+
* - HTTP request handling via fetch()
|
|
9
|
+
* - Child DO creation with $context linking
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* import { DigitalObject } from './DigitalObject'
|
|
14
|
+
*
|
|
15
|
+
* export class MyStartup extends DigitalObject {
|
|
16
|
+
* async onInitialize() {
|
|
17
|
+
* await this.state.set('status', 'active')
|
|
18
|
+
* }
|
|
19
|
+
*
|
|
20
|
+
* async handlePath(request: Request, path: string): Promise<Response> {
|
|
21
|
+
* if (path === '/api/status') {
|
|
22
|
+
* const status = await this.state.get('status')
|
|
23
|
+
* return Response.json({ status })
|
|
24
|
+
* }
|
|
25
|
+
* return new Response('Not Found', { status: 404 })
|
|
26
|
+
* }
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*
|
|
30
|
+
* @module do/DigitalObject
|
|
31
|
+
*/
|
|
32
|
+
import { createDOState } from './state';
|
|
33
|
+
import { HibernationManager } from './hibernation';
|
|
34
|
+
import { ContextStreamer } from '../db/cdc/streaming';
|
|
35
|
+
import { MethodRegistry, dispatch, registerSystemMethods, registerIdentityMethods, } from '../rpc/methods';
|
|
36
|
+
/**
|
|
37
|
+
* Base class for all Digital Objects
|
|
38
|
+
*
|
|
39
|
+
* A Digital Object is a stateful, addressable entity that:
|
|
40
|
+
* - Has a unique HTTPS URL identity ($id)
|
|
41
|
+
* - Belongs to a type ($type)
|
|
42
|
+
* - May have a parent context ($context) for CDC streaming
|
|
43
|
+
* - Maintains versioned state ($version) for optimistic concurrency
|
|
44
|
+
*
|
|
45
|
+
* @class DigitalObject
|
|
46
|
+
* @implements {DurableObject}
|
|
47
|
+
*
|
|
48
|
+
* @example Creating a custom DO
|
|
49
|
+
* ```typescript
|
|
50
|
+
* export class TenantDO extends DigitalObject {
|
|
51
|
+
* async onInitialize() {
|
|
52
|
+
* // Set up initial tenant state
|
|
53
|
+
* await this.state.set('plan', 'free')
|
|
54
|
+
* await this.state.set('users', [])
|
|
55
|
+
* }
|
|
56
|
+
* }
|
|
57
|
+
* ```
|
|
58
|
+
*
|
|
59
|
+
* @example Handling requests
|
|
60
|
+
* ```typescript
|
|
61
|
+
* export class ApiDO extends DigitalObject {
|
|
62
|
+
* async handlePath(request: Request, path: string): Promise<Response> {
|
|
63
|
+
* const method = request.method
|
|
64
|
+
* const body = method === 'POST' ? await request.json() : null
|
|
65
|
+
*
|
|
66
|
+
* // Route to handlers
|
|
67
|
+
* if (path.startsWith('/api/users')) {
|
|
68
|
+
* return this.handleUsers(request, path, body)
|
|
69
|
+
* }
|
|
70
|
+
*
|
|
71
|
+
* return new Response('Not Found', { status: 404 })
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
export class DigitalObject {
|
|
77
|
+
/**
|
|
78
|
+
* The unique HTTPS URL identifier for this DO
|
|
79
|
+
* Format: https://domain or https://domain/path
|
|
80
|
+
*
|
|
81
|
+
* @example 'https://headless.ly'
|
|
82
|
+
* @example 'https://crm.headless.ly/acme'
|
|
83
|
+
*/
|
|
84
|
+
$id;
|
|
85
|
+
/**
|
|
86
|
+
* The type URL defining this DO's schema
|
|
87
|
+
* Can be a well-known type (resolves to https://do.md/{type})
|
|
88
|
+
* or a full URL
|
|
89
|
+
*
|
|
90
|
+
* @example 'Startup' (resolves to https://do.md/Startup)
|
|
91
|
+
* @example 'https://schema.org.ai/Agent'
|
|
92
|
+
*/
|
|
93
|
+
$type;
|
|
94
|
+
/**
|
|
95
|
+
* Optional parent DO URL for CDC event streaming
|
|
96
|
+
* Events bubble up through the $context chain
|
|
97
|
+
*
|
|
98
|
+
* @example 'https://startups.studio' (parent of https://headless.ly)
|
|
99
|
+
*/
|
|
100
|
+
$context;
|
|
101
|
+
/**
|
|
102
|
+
* Version number for optimistic concurrency control
|
|
103
|
+
* Incremented on each state mutation
|
|
104
|
+
*/
|
|
105
|
+
$version;
|
|
106
|
+
/**
|
|
107
|
+
* State management instance for this DO
|
|
108
|
+
* Provides get/set/delete operations backed by SQLite
|
|
109
|
+
*/
|
|
110
|
+
state;
|
|
111
|
+
/**
|
|
112
|
+
* Hibernation manager for this DO
|
|
113
|
+
* Handles sleep/wake lifecycle and WebSocket preservation
|
|
114
|
+
*/
|
|
115
|
+
hibernation;
|
|
116
|
+
/**
|
|
117
|
+
* Environment bindings (DO namespace, R2, KV, etc.)
|
|
118
|
+
*/
|
|
119
|
+
env;
|
|
120
|
+
/**
|
|
121
|
+
* Raw Durable Object state from Cloudflare runtime
|
|
122
|
+
*/
|
|
123
|
+
ctx;
|
|
124
|
+
/**
|
|
125
|
+
* Whether the DO has been initialized
|
|
126
|
+
* @internal
|
|
127
|
+
*/
|
|
128
|
+
initialized = false;
|
|
129
|
+
/**
|
|
130
|
+
* RPC method registry for this DO
|
|
131
|
+
* Subclasses can register additional methods here
|
|
132
|
+
*/
|
|
133
|
+
rpcRegistry;
|
|
134
|
+
/**
|
|
135
|
+
* Creates a new DigitalObject instance
|
|
136
|
+
*
|
|
137
|
+
* @param ctx - Durable Object state from Cloudflare runtime
|
|
138
|
+
* @param env - Environment bindings
|
|
139
|
+
*
|
|
140
|
+
* @example
|
|
141
|
+
* ```typescript
|
|
142
|
+
* // This is called automatically by Cloudflare Workers runtime
|
|
143
|
+
* // You don't typically call this directly
|
|
144
|
+
* const do = new MyDigitalObject(state, env)
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
constructor(ctx, env) {
|
|
148
|
+
this.ctx = ctx;
|
|
149
|
+
this.env = env;
|
|
150
|
+
// Initialize state and hibernation managers
|
|
151
|
+
// These will be fully set up in initialize()
|
|
152
|
+
this.state = createDOState(ctx);
|
|
153
|
+
this.hibernation = new HibernationManager(ctx, this.getHibernationConfig());
|
|
154
|
+
// Initialize RPC registry with default methods
|
|
155
|
+
this.rpcRegistry = new MethodRegistry();
|
|
156
|
+
registerSystemMethods(this.rpcRegistry);
|
|
157
|
+
registerIdentityMethods(this.rpcRegistry);
|
|
158
|
+
// Register state methods with access to this.state
|
|
159
|
+
this.registerStateMethods();
|
|
160
|
+
// Allow subclasses to register additional methods
|
|
161
|
+
this.registerRPCMethods();
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Initialize the Digital Object
|
|
165
|
+
*
|
|
166
|
+
* Called automatically on first request. Loads identity from storage
|
|
167
|
+
* or creates it if this is a new DO.
|
|
168
|
+
*
|
|
169
|
+
* @internal
|
|
170
|
+
*/
|
|
171
|
+
async initialize() {
|
|
172
|
+
if (this.initialized)
|
|
173
|
+
return;
|
|
174
|
+
// Load or create identity (use raw storage, not state wrapper)
|
|
175
|
+
const identity = await this.ctx.storage.get('$identity');
|
|
176
|
+
if (identity) {
|
|
177
|
+
this.$id = identity.$id;
|
|
178
|
+
this.$type = identity.$type;
|
|
179
|
+
this.$context = identity.$context;
|
|
180
|
+
this.$version = identity.$version;
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
// New DO - set defaults
|
|
184
|
+
this.$id = await this.resolveId();
|
|
185
|
+
this.$type = this.getDefaultType();
|
|
186
|
+
this.$version = 1;
|
|
187
|
+
// Persist identity directly to storage (bypass state wrapper for system keys)
|
|
188
|
+
await this.ctx.storage.put('$identity', this.getIdentity());
|
|
189
|
+
}
|
|
190
|
+
// Call subclass initialization hook
|
|
191
|
+
await this.onInitialize();
|
|
192
|
+
this.initialized = true;
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Get the DO's identity object
|
|
196
|
+
*
|
|
197
|
+
* @returns The complete identity with $id, $type, $context, $version
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```typescript
|
|
201
|
+
* const identity = this.getIdentity()
|
|
202
|
+
* console.log(identity.$id) // 'https://headless.ly'
|
|
203
|
+
* ```
|
|
204
|
+
*/
|
|
205
|
+
getIdentity() {
|
|
206
|
+
return {
|
|
207
|
+
$id: this.$id,
|
|
208
|
+
$type: this.$type,
|
|
209
|
+
$context: this.$context,
|
|
210
|
+
$version: this.$version,
|
|
211
|
+
$createdAt: Date.now(), // TODO: Store actual creation time
|
|
212
|
+
$updatedAt: Date.now(),
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Set the parent context for CDC streaming
|
|
217
|
+
*
|
|
218
|
+
* @param context - Parent DO URL or undefined to clear
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```typescript
|
|
222
|
+
* // Set parent context
|
|
223
|
+
* await this.setContext('https://startups.studio')
|
|
224
|
+
*
|
|
225
|
+
* // Clear parent context
|
|
226
|
+
* await this.setContext(undefined)
|
|
227
|
+
* ```
|
|
228
|
+
*/
|
|
229
|
+
async setContext(context) {
|
|
230
|
+
this.$context = context;
|
|
231
|
+
await this.ctx.storage.put('$identity', this.getIdentity());
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get the parent context
|
|
235
|
+
*
|
|
236
|
+
* @returns Parent DO URL or undefined if no parent
|
|
237
|
+
*/
|
|
238
|
+
getContext() {
|
|
239
|
+
return this.$context;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Resolve the $id for this DO
|
|
243
|
+
*
|
|
244
|
+
* Override this method to customize ID resolution.
|
|
245
|
+
* Default implementation uses the DO's name from the runtime.
|
|
246
|
+
*
|
|
247
|
+
* @returns The HTTPS URL identifier for this DO
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```typescript
|
|
251
|
+
* protected async resolveId(): Promise<string> {
|
|
252
|
+
* // Custom ID resolution logic
|
|
253
|
+
* const name = this.ctx.id.name ?? this.ctx.id.toString()
|
|
254
|
+
* return `https://${name}`
|
|
255
|
+
* }
|
|
256
|
+
* ```
|
|
257
|
+
*/
|
|
258
|
+
async resolveId() {
|
|
259
|
+
// Default: use the DO's name or ID as the identifier
|
|
260
|
+
// In production, this would be a proper HTTPS URL
|
|
261
|
+
const id = this.ctx.id;
|
|
262
|
+
// DurableObjectId may have a name property if created via idFromName
|
|
263
|
+
const name = id.name ?? id.toString();
|
|
264
|
+
return `https://${name}`;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* Get the default type for this DO
|
|
268
|
+
*
|
|
269
|
+
* Override this method to set a custom default type.
|
|
270
|
+
* Default implementation uses the class name.
|
|
271
|
+
*
|
|
272
|
+
* @returns The default DOType for this class
|
|
273
|
+
*/
|
|
274
|
+
getDefaultType() {
|
|
275
|
+
return this.constructor.name;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Get hibernation configuration
|
|
279
|
+
*
|
|
280
|
+
* Override this method to customize hibernation behavior.
|
|
281
|
+
*
|
|
282
|
+
* @returns Hibernation configuration options
|
|
283
|
+
*/
|
|
284
|
+
getHibernationConfig() {
|
|
285
|
+
return {
|
|
286
|
+
idleTimeout: 10_000, // 10 seconds
|
|
287
|
+
maxHibernationDuration: 24 * 60 * 60 * 1000, // 24 hours
|
|
288
|
+
preserveWebSockets: true,
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Initialization hook for subclasses
|
|
293
|
+
*
|
|
294
|
+
* Override this method to perform custom initialization.
|
|
295
|
+
* Called once when the DO is first accessed.
|
|
296
|
+
*
|
|
297
|
+
* @example
|
|
298
|
+
* ```typescript
|
|
299
|
+
* async onInitialize(): Promise<void> {
|
|
300
|
+
* // Set up default state
|
|
301
|
+
* const existing = await this.state.get('config')
|
|
302
|
+
* if (!existing) {
|
|
303
|
+
* await this.state.set('config', { initialized: true })
|
|
304
|
+
* }
|
|
305
|
+
* }
|
|
306
|
+
* ```
|
|
307
|
+
*/
|
|
308
|
+
async onInitialize() {
|
|
309
|
+
// Override in subclasses
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Register state RPC methods (do.state.get, do.state.set, do.state.delete)
|
|
313
|
+
*
|
|
314
|
+
* These methods provide RPC access to the DO's state storage.
|
|
315
|
+
*
|
|
316
|
+
* @internal
|
|
317
|
+
*/
|
|
318
|
+
registerStateMethods() {
|
|
319
|
+
this.rpcRegistry.register('do.state.get', async (params) => {
|
|
320
|
+
const { key } = params;
|
|
321
|
+
return this.state.get(key);
|
|
322
|
+
}, {
|
|
323
|
+
description: 'Get a value from DO state',
|
|
324
|
+
params: {
|
|
325
|
+
key: { type: 'string', required: true, description: 'The key to retrieve' },
|
|
326
|
+
},
|
|
327
|
+
});
|
|
328
|
+
this.rpcRegistry.register('do.state.set', async (params) => {
|
|
329
|
+
const { key, value } = params;
|
|
330
|
+
await this.state.set(key, value);
|
|
331
|
+
return { ok: true };
|
|
332
|
+
}, {
|
|
333
|
+
description: 'Set a value in DO state',
|
|
334
|
+
params: {
|
|
335
|
+
key: { type: 'string', required: true, description: 'The key to set' },
|
|
336
|
+
value: { type: 'object', required: true, description: 'The value to store' },
|
|
337
|
+
},
|
|
338
|
+
});
|
|
339
|
+
this.rpcRegistry.register('do.state.delete', async (params) => {
|
|
340
|
+
const { key } = params;
|
|
341
|
+
const deleted = await this.state.delete(key);
|
|
342
|
+
return { deleted };
|
|
343
|
+
}, {
|
|
344
|
+
description: 'Delete a value from DO state',
|
|
345
|
+
params: {
|
|
346
|
+
key: { type: 'string', required: true, description: 'The key to delete' },
|
|
347
|
+
},
|
|
348
|
+
});
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Register custom RPC methods
|
|
352
|
+
*
|
|
353
|
+
* Override this method to register additional RPC methods
|
|
354
|
+
* for your Digital Object subclass.
|
|
355
|
+
*
|
|
356
|
+
* @example
|
|
357
|
+
* ```typescript
|
|
358
|
+
* protected registerRPCMethods(): void {
|
|
359
|
+
* this.rpcRegistry.register('my.custom.method', async (params, ctx) => {
|
|
360
|
+
* return { result: 'custom method called' }
|
|
361
|
+
* })
|
|
362
|
+
* }
|
|
363
|
+
* ```
|
|
364
|
+
*/
|
|
365
|
+
registerRPCMethods() {
|
|
366
|
+
// Override in subclasses to register custom methods
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Handle incoming HTTP requests
|
|
370
|
+
*
|
|
371
|
+
* This is the main entry point for all HTTP traffic to the DO.
|
|
372
|
+
* It routes requests based on path and method.
|
|
373
|
+
*
|
|
374
|
+
* @param request - The incoming HTTP request
|
|
375
|
+
* @returns HTTP response
|
|
376
|
+
*
|
|
377
|
+
* @example
|
|
378
|
+
* ```typescript
|
|
379
|
+
* // GET https://do.example.com/api/status
|
|
380
|
+
* // Routes to handlePath with path = '/api/status'
|
|
381
|
+
* ```
|
|
382
|
+
*/
|
|
383
|
+
async fetch(request) {
|
|
384
|
+
// Ensure initialization
|
|
385
|
+
await this.initialize();
|
|
386
|
+
// Reset hibernation timer on activity
|
|
387
|
+
this.hibernation.touch();
|
|
388
|
+
const url = new URL(request.url);
|
|
389
|
+
const path = url.pathname;
|
|
390
|
+
try {
|
|
391
|
+
// Built-in routes
|
|
392
|
+
switch (path) {
|
|
393
|
+
case '/':
|
|
394
|
+
return this.handleRoot(request);
|
|
395
|
+
case '/rpc':
|
|
396
|
+
return this.handleRPC(request);
|
|
397
|
+
case '/ws':
|
|
398
|
+
return this.handleWebSocket(request);
|
|
399
|
+
case '/cdc':
|
|
400
|
+
return this.handleCDC(request);
|
|
401
|
+
case '/$identity':
|
|
402
|
+
return Response.json(this.getIdentity());
|
|
403
|
+
default:
|
|
404
|
+
// Delegate to subclass
|
|
405
|
+
return await this.handlePath(request, path);
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
return this.handleError(error);
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
/**
|
|
413
|
+
* Handle requests to the root path (/)
|
|
414
|
+
*
|
|
415
|
+
* Default implementation returns DO identity.
|
|
416
|
+
* Override to customize.
|
|
417
|
+
*
|
|
418
|
+
* @param request - The incoming request
|
|
419
|
+
* @returns HTTP response with DO identity
|
|
420
|
+
*/
|
|
421
|
+
async handleRoot(request) {
|
|
422
|
+
return Response.json({
|
|
423
|
+
...this.getIdentity(),
|
|
424
|
+
status: 'active',
|
|
425
|
+
timestamp: Date.now(),
|
|
426
|
+
});
|
|
427
|
+
}
|
|
428
|
+
/**
|
|
429
|
+
* Handle JSON-RPC requests to /rpc
|
|
430
|
+
*
|
|
431
|
+
* Supports the DORPCMethods interface defined in types/rpc.ts
|
|
432
|
+
*
|
|
433
|
+
* @param request - The incoming RPC request
|
|
434
|
+
* @returns RPC response
|
|
435
|
+
*/
|
|
436
|
+
async handleRPC(request) {
|
|
437
|
+
if (request.method !== 'POST') {
|
|
438
|
+
return new Response('Method Not Allowed', { status: 405 });
|
|
439
|
+
}
|
|
440
|
+
const rpcRequest = await request.json();
|
|
441
|
+
const response = await this.processRPC(rpcRequest);
|
|
442
|
+
return Response.json(response);
|
|
443
|
+
}
|
|
444
|
+
/**
|
|
445
|
+
* Process a single RPC request
|
|
446
|
+
*
|
|
447
|
+
* Dispatches the request to the appropriate handler in the RPC registry.
|
|
448
|
+
*
|
|
449
|
+
* @param request - The RPC request object
|
|
450
|
+
* @returns RPC response object
|
|
451
|
+
*/
|
|
452
|
+
async processRPC(request) {
|
|
453
|
+
// Build method context with DO-specific properties
|
|
454
|
+
const methodContext = {
|
|
455
|
+
state: this.ctx,
|
|
456
|
+
env: this.env,
|
|
457
|
+
meta: request.meta,
|
|
458
|
+
getIdentity: () => this.getIdentity(),
|
|
459
|
+
setContext: (context) => this.setContext(context),
|
|
460
|
+
getContext: () => this.getContext(),
|
|
461
|
+
listChildren: (type) => this.listChildren(type),
|
|
462
|
+
};
|
|
463
|
+
// Dispatch to the registry
|
|
464
|
+
return dispatch(this.rpcRegistry, request, methodContext);
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Handle WebSocket upgrade requests to /ws
|
|
468
|
+
*
|
|
469
|
+
* Supports hibernatable WebSockets for RPC streaming.
|
|
470
|
+
*
|
|
471
|
+
* @param request - The incoming WebSocket upgrade request
|
|
472
|
+
* @returns WebSocket response
|
|
473
|
+
*/
|
|
474
|
+
async handleWebSocket(request) {
|
|
475
|
+
const upgradeHeader = request.headers.get('Upgrade');
|
|
476
|
+
if (upgradeHeader !== 'websocket') {
|
|
477
|
+
return new Response('Expected WebSocket', { status: 426 });
|
|
478
|
+
}
|
|
479
|
+
// Use hibernation manager to handle WebSocket
|
|
480
|
+
return this.hibernation.acceptWebSocket(request);
|
|
481
|
+
}
|
|
482
|
+
/**
|
|
483
|
+
* Handle CDC stream requests to /cdc
|
|
484
|
+
*
|
|
485
|
+
* Supports both WebSocket and SSE (Server-Sent Events) streaming.
|
|
486
|
+
* CDC events are emitted for all state mutations and propagated up the $context chain.
|
|
487
|
+
*
|
|
488
|
+
* Query parameters:
|
|
489
|
+
* - collections: comma-separated list of collections to subscribe to
|
|
490
|
+
* - operations: comma-separated list of operations (INSERT, UPDATE, DELETE)
|
|
491
|
+
* - fromSequence: starting sequence number for replay
|
|
492
|
+
* - fromTimestamp: starting timestamp for replay
|
|
493
|
+
* - includeDocuments: whether to include full before/after documents (default: true)
|
|
494
|
+
*
|
|
495
|
+
* @param request - The incoming request
|
|
496
|
+
* @returns Streaming response with CDC events (WebSocket 101 or SSE stream)
|
|
497
|
+
*
|
|
498
|
+
* @example WebSocket subscription
|
|
499
|
+
* ```typescript
|
|
500
|
+
* const ws = new WebSocket('wss://my.do/cdc?collections=users,orders')
|
|
501
|
+
* ws.onmessage = (event) => {
|
|
502
|
+
* const cdcEvent = JSON.parse(event.data)
|
|
503
|
+
* console.log(`${cdcEvent.operation} on ${cdcEvent.collection}`)
|
|
504
|
+
* }
|
|
505
|
+
* ```
|
|
506
|
+
*
|
|
507
|
+
* @example SSE subscription
|
|
508
|
+
* ```typescript
|
|
509
|
+
* const eventSource = new EventSource('https://my.do/cdc?operations=INSERT,UPDATE')
|
|
510
|
+
* eventSource.onmessage = (event) => {
|
|
511
|
+
* const cdcEvent = JSON.parse(event.data)
|
|
512
|
+
* console.log(`${cdcEvent.operation} on ${cdcEvent.collection}`)
|
|
513
|
+
* }
|
|
514
|
+
* ```
|
|
515
|
+
*/
|
|
516
|
+
async handleCDC(request) {
|
|
517
|
+
const url = new URL(request.url);
|
|
518
|
+
const upgradeHeader = request.headers.get('Upgrade');
|
|
519
|
+
// Parse CDC options from query parameters
|
|
520
|
+
const options = this.parseCDCOptions(url.searchParams);
|
|
521
|
+
// WebSocket upgrade for real-time streaming
|
|
522
|
+
if (upgradeHeader === 'websocket') {
|
|
523
|
+
return this.handleCDCWebSocket(request, options);
|
|
524
|
+
}
|
|
525
|
+
// SSE streaming for HTTP clients
|
|
526
|
+
return this.handleCDCSSE(request, options);
|
|
527
|
+
}
|
|
528
|
+
/**
|
|
529
|
+
* Parse CDC options from URL search parameters
|
|
530
|
+
*
|
|
531
|
+
* @param params - URL search parameters
|
|
532
|
+
* @returns Parsed CDC options
|
|
533
|
+
* @internal
|
|
534
|
+
*/
|
|
535
|
+
parseCDCOptions(params) {
|
|
536
|
+
const options = {};
|
|
537
|
+
// Parse collections filter
|
|
538
|
+
const collections = params.get('collections');
|
|
539
|
+
if (collections) {
|
|
540
|
+
options.collections = collections.split(',').map((c) => c.trim());
|
|
541
|
+
}
|
|
542
|
+
// Parse operations filter
|
|
543
|
+
const operations = params.get('operations');
|
|
544
|
+
if (operations) {
|
|
545
|
+
options.operations = operations.split(',').map((o) => o.trim().toUpperCase());
|
|
546
|
+
}
|
|
547
|
+
// Parse cursor for replay
|
|
548
|
+
const fromSequence = params.get('fromSequence');
|
|
549
|
+
const fromTimestamp = params.get('fromTimestamp');
|
|
550
|
+
if (fromSequence || fromTimestamp) {
|
|
551
|
+
options.fromCursor = {
|
|
552
|
+
sequence: fromSequence ? parseInt(fromSequence, 10) : 0,
|
|
553
|
+
timestamp: fromTimestamp ? parseInt(fromTimestamp, 10) : 0,
|
|
554
|
+
};
|
|
555
|
+
}
|
|
556
|
+
// Parse document inclusion preference
|
|
557
|
+
const includeDocuments = params.get('includeDocuments');
|
|
558
|
+
if (includeDocuments !== null) {
|
|
559
|
+
options.includeDocuments = includeDocuments !== 'false';
|
|
560
|
+
}
|
|
561
|
+
// Parse batch settings
|
|
562
|
+
const batchSize = params.get('batchSize');
|
|
563
|
+
if (batchSize) {
|
|
564
|
+
options.batchSize = parseInt(batchSize, 10);
|
|
565
|
+
}
|
|
566
|
+
const batchTimeout = params.get('batchTimeout');
|
|
567
|
+
if (batchTimeout) {
|
|
568
|
+
options.batchTimeout = parseInt(batchTimeout, 10);
|
|
569
|
+
}
|
|
570
|
+
return options;
|
|
571
|
+
}
|
|
572
|
+
/**
|
|
573
|
+
* Handle WebSocket CDC streaming
|
|
574
|
+
*
|
|
575
|
+
* @param request - The WebSocket upgrade request
|
|
576
|
+
* @param options - CDC subscription options
|
|
577
|
+
* @returns WebSocket response
|
|
578
|
+
* @internal
|
|
579
|
+
*/
|
|
580
|
+
async handleCDCWebSocket(request, options) {
|
|
581
|
+
// Create WebSocket pair
|
|
582
|
+
const pair = new WebSocketPair();
|
|
583
|
+
const [client, server] = [pair[0], pair[1]];
|
|
584
|
+
// Accept the WebSocket with CDC tag for hibernation
|
|
585
|
+
this.ctx.acceptWebSocket(server, ['cdc']);
|
|
586
|
+
server.cdcOptions = options;
|
|
587
|
+
// Set up mutation handler to forward events to this WebSocket
|
|
588
|
+
const unsubscribe = this.state.onMutation(async (event) => {
|
|
589
|
+
// Apply filters
|
|
590
|
+
if (!this.shouldSendCDCEvent(event, options)) {
|
|
591
|
+
return;
|
|
592
|
+
}
|
|
593
|
+
// Optionally strip document content
|
|
594
|
+
const eventToSend = options.includeDocuments === false ? this.stripDocuments(event) : event;
|
|
595
|
+
try {
|
|
596
|
+
server.send(JSON.stringify(eventToSend));
|
|
597
|
+
}
|
|
598
|
+
catch {
|
|
599
|
+
// WebSocket closed, ignore
|
|
600
|
+
}
|
|
601
|
+
});
|
|
602
|
+
server.cdcUnsubscribe = unsubscribe;
|
|
603
|
+
// Send initial replay if cursor provided
|
|
604
|
+
if (options.fromCursor) {
|
|
605
|
+
const events = await this.state.getChangesSince(options.fromCursor, options.batchSize ?? 100);
|
|
606
|
+
for (const event of events) {
|
|
607
|
+
if (this.shouldSendCDCEvent(event, options)) {
|
|
608
|
+
const eventToSend = options.includeDocuments === false ? this.stripDocuments(event) : event;
|
|
609
|
+
try {
|
|
610
|
+
server.send(JSON.stringify(eventToSend));
|
|
611
|
+
}
|
|
612
|
+
catch {
|
|
613
|
+
// WebSocket closed during replay
|
|
614
|
+
break;
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
// Propagate events to parent context
|
|
620
|
+
this.setupContextPropagation();
|
|
621
|
+
return new Response(null, {
|
|
622
|
+
status: 101,
|
|
623
|
+
webSocket: client,
|
|
624
|
+
});
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Handle SSE (Server-Sent Events) CDC streaming
|
|
628
|
+
*
|
|
629
|
+
* @param request - The HTTP request
|
|
630
|
+
* @param options - CDC subscription options
|
|
631
|
+
* @returns SSE streaming response
|
|
632
|
+
* @internal
|
|
633
|
+
*/
|
|
634
|
+
async handleCDCSSE(request, options) {
|
|
635
|
+
// Create a TransformStream for SSE
|
|
636
|
+
const { readable, writable } = new TransformStream();
|
|
637
|
+
const writer = writable.getWriter();
|
|
638
|
+
const encoder = new TextEncoder();
|
|
639
|
+
// Track if the stream is still open
|
|
640
|
+
let isOpen = true;
|
|
641
|
+
// Send SSE event helper
|
|
642
|
+
const sendSSE = async (event) => {
|
|
643
|
+
if (!isOpen)
|
|
644
|
+
return;
|
|
645
|
+
try {
|
|
646
|
+
const data = JSON.stringify(event);
|
|
647
|
+
await writer.write(encoder.encode(`data: ${data}\n\n`));
|
|
648
|
+
}
|
|
649
|
+
catch {
|
|
650
|
+
isOpen = false;
|
|
651
|
+
}
|
|
652
|
+
};
|
|
653
|
+
// Set up mutation handler
|
|
654
|
+
const unsubscribe = this.state.onMutation(async (event) => {
|
|
655
|
+
if (!this.shouldSendCDCEvent(event, options)) {
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
const eventToSend = options.includeDocuments === false ? this.stripDocuments(event) : event;
|
|
659
|
+
await sendSSE(eventToSend);
|
|
660
|
+
});
|
|
661
|
+
// Handle client disconnect
|
|
662
|
+
request.signal?.addEventListener('abort', () => {
|
|
663
|
+
isOpen = false;
|
|
664
|
+
unsubscribe();
|
|
665
|
+
writer.close().catch(() => {
|
|
666
|
+
// Ignore close errors
|
|
667
|
+
});
|
|
668
|
+
});
|
|
669
|
+
// Send initial replay if cursor provided
|
|
670
|
+
if (options.fromCursor) {
|
|
671
|
+
const events = await this.state.getChangesSince(options.fromCursor, options.batchSize ?? 100);
|
|
672
|
+
for (const event of events) {
|
|
673
|
+
if (this.shouldSendCDCEvent(event, options)) {
|
|
674
|
+
const eventToSend = options.includeDocuments === false ? this.stripDocuments(event) : event;
|
|
675
|
+
await sendSSE(eventToSend);
|
|
676
|
+
}
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
// Propagate events to parent context
|
|
680
|
+
this.setupContextPropagation();
|
|
681
|
+
return new Response(readable, {
|
|
682
|
+
headers: {
|
|
683
|
+
'Content-Type': 'text/event-stream',
|
|
684
|
+
'Cache-Control': 'no-cache',
|
|
685
|
+
Connection: 'keep-alive',
|
|
686
|
+
'X-Accel-Buffering': 'no',
|
|
687
|
+
},
|
|
688
|
+
});
|
|
689
|
+
}
|
|
690
|
+
/**
|
|
691
|
+
* Check if a CDC event matches the subscription filters
|
|
692
|
+
*
|
|
693
|
+
* @param event - The CDC event to check
|
|
694
|
+
* @param options - Subscription options with filters
|
|
695
|
+
* @returns True if the event should be sent
|
|
696
|
+
* @internal
|
|
697
|
+
*/
|
|
698
|
+
shouldSendCDCEvent(event, options) {
|
|
699
|
+
// Filter by collections
|
|
700
|
+
if (options.collections && options.collections.length > 0) {
|
|
701
|
+
if (!options.collections.includes(event.collection)) {
|
|
702
|
+
return false;
|
|
703
|
+
}
|
|
704
|
+
}
|
|
705
|
+
// Filter by operations
|
|
706
|
+
if (options.operations && options.operations.length > 0) {
|
|
707
|
+
if (!options.operations.includes(event.operation)) {
|
|
708
|
+
return false;
|
|
709
|
+
}
|
|
710
|
+
}
|
|
711
|
+
return true;
|
|
712
|
+
}
|
|
713
|
+
/**
|
|
714
|
+
* Strip document content from CDC event
|
|
715
|
+
*
|
|
716
|
+
* @param event - The CDC event
|
|
717
|
+
* @returns Event without before/after documents
|
|
718
|
+
* @internal
|
|
719
|
+
*/
|
|
720
|
+
stripDocuments(event) {
|
|
721
|
+
const { before, after, ...rest } = event;
|
|
722
|
+
return rest;
|
|
723
|
+
}
|
|
724
|
+
/**
|
|
725
|
+
* Set up CDC event propagation to parent context
|
|
726
|
+
*
|
|
727
|
+
* Events bubble up through the $context chain, enabling
|
|
728
|
+
* parent DOs to observe changes in all descendants.
|
|
729
|
+
*
|
|
730
|
+
* @internal
|
|
731
|
+
*/
|
|
732
|
+
setupContextPropagation() {
|
|
733
|
+
if (!this.$context || this.contextStreamerSetup) {
|
|
734
|
+
return;
|
|
735
|
+
}
|
|
736
|
+
// Create context streamer for parent propagation
|
|
737
|
+
const streamer = new ContextStreamer(this.$context, {
|
|
738
|
+
batchSize: 100,
|
|
739
|
+
batchTimeout: 1000,
|
|
740
|
+
});
|
|
741
|
+
// Register mutation handler to propagate events
|
|
742
|
+
this.state.onMutation(async (event) => {
|
|
743
|
+
// Enrich event with source information
|
|
744
|
+
const enrichedEvent = {
|
|
745
|
+
...event,
|
|
746
|
+
source: this.$id,
|
|
747
|
+
};
|
|
748
|
+
// Propagate to parent context
|
|
749
|
+
await streamer.propagate(enrichedEvent);
|
|
750
|
+
});
|
|
751
|
+
this.contextStreamerSetup = true;
|
|
752
|
+
}
|
|
753
|
+
/**
|
|
754
|
+
* Whether context streamer has been set up
|
|
755
|
+
* @internal
|
|
756
|
+
*/
|
|
757
|
+
contextStreamerSetup = false;
|
|
758
|
+
/**
|
|
759
|
+
* Handle custom paths not covered by built-in routes
|
|
760
|
+
*
|
|
761
|
+
* Override this method to implement custom path handling.
|
|
762
|
+
*
|
|
763
|
+
* @param request - The incoming request
|
|
764
|
+
* @param path - The URL path
|
|
765
|
+
* @returns HTTP response
|
|
766
|
+
*
|
|
767
|
+
* @example
|
|
768
|
+
* ```typescript
|
|
769
|
+
* async handlePath(request: Request, path: string): Promise<Response> {
|
|
770
|
+
* if (path.startsWith('/api/')) {
|
|
771
|
+
* return this.handleApi(request, path.slice(5))
|
|
772
|
+
* }
|
|
773
|
+
* return new Response('Not Found', { status: 404 })
|
|
774
|
+
* }
|
|
775
|
+
* ```
|
|
776
|
+
*/
|
|
777
|
+
async handlePath(request, path) {
|
|
778
|
+
return new Response('Not Found', { status: 404 });
|
|
779
|
+
}
|
|
780
|
+
/**
|
|
781
|
+
* Handle errors during request processing
|
|
782
|
+
*
|
|
783
|
+
* @param error - The error that occurred
|
|
784
|
+
* @returns Error response
|
|
785
|
+
*/
|
|
786
|
+
handleError(error) {
|
|
787
|
+
console.error('DigitalObject error:', error);
|
|
788
|
+
const message = error instanceof Error ? error.message : 'Internal Server Error';
|
|
789
|
+
const status = error instanceof DOError ? error.status : 500;
|
|
790
|
+
return Response.json({
|
|
791
|
+
error: {
|
|
792
|
+
message,
|
|
793
|
+
code: error instanceof DOError ? error.code : 'INTERNAL_ERROR',
|
|
794
|
+
},
|
|
795
|
+
}, { status });
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Create a child DO with this DO as the parent context
|
|
799
|
+
*
|
|
800
|
+
* The child DO will have its $context set to this DO's $id,
|
|
801
|
+
* enabling CDC event streaming up the hierarchy.
|
|
802
|
+
*
|
|
803
|
+
* @param type - The type of child DO to create
|
|
804
|
+
* @param name - The name/identifier for the child
|
|
805
|
+
* @returns Reference (URL) to the created child DO
|
|
806
|
+
*
|
|
807
|
+
* @example
|
|
808
|
+
* ```typescript
|
|
809
|
+
* // Create a tenant under this SaaS DO
|
|
810
|
+
* const tenantRef = await this.createChild('Tenant', 'acme')
|
|
811
|
+
* // tenantRef = 'https://crm.headless.ly/acme'
|
|
812
|
+
* ```
|
|
813
|
+
*/
|
|
814
|
+
async createChild(type, name) {
|
|
815
|
+
// Construct child ID based on this DO's ID
|
|
816
|
+
const childId = `${this.$id}/${name}`;
|
|
817
|
+
// Get a stub to the child DO
|
|
818
|
+
const childStub = this.env.DO.get(this.env.DO.idFromName(childId));
|
|
819
|
+
// Initialize the child with context pointing to this DO
|
|
820
|
+
await childStub.fetch(new Request(`https://${childId}/$init`, {
|
|
821
|
+
method: 'POST',
|
|
822
|
+
headers: { 'Content-Type': 'application/json' },
|
|
823
|
+
body: JSON.stringify({
|
|
824
|
+
$type: type,
|
|
825
|
+
$context: this.$id,
|
|
826
|
+
}),
|
|
827
|
+
}));
|
|
828
|
+
return childId;
|
|
829
|
+
}
|
|
830
|
+
/**
|
|
831
|
+
* Get a stub to a child DO
|
|
832
|
+
*
|
|
833
|
+
* @param name - The name/identifier of the child
|
|
834
|
+
* @returns Durable Object stub for the child
|
|
835
|
+
*
|
|
836
|
+
* @example
|
|
837
|
+
* ```typescript
|
|
838
|
+
* const tenantStub = this.getChild('acme')
|
|
839
|
+
* const response = await tenantStub.fetch(new Request('https://crm.headless.ly/acme/api'))
|
|
840
|
+
* ```
|
|
841
|
+
*/
|
|
842
|
+
getChild(name) {
|
|
843
|
+
const childId = `${this.$id}/${name}`;
|
|
844
|
+
return this.env.DO.get(this.env.DO.idFromName(childId));
|
|
845
|
+
}
|
|
846
|
+
/**
|
|
847
|
+
* List all child DOs of a specific type
|
|
848
|
+
*
|
|
849
|
+
* @param type - Optional type filter
|
|
850
|
+
* @returns Array of child DO references
|
|
851
|
+
*/
|
|
852
|
+
async listChildren(type) {
|
|
853
|
+
// TODO: Implement child listing via state storage
|
|
854
|
+
return [];
|
|
855
|
+
}
|
|
856
|
+
/**
|
|
857
|
+
* Handle alarm for hibernation wake-up
|
|
858
|
+
*
|
|
859
|
+
* Called by Cloudflare Workers runtime when an alarm fires.
|
|
860
|
+
*
|
|
861
|
+
* @internal
|
|
862
|
+
*/
|
|
863
|
+
async alarm() {
|
|
864
|
+
await this.initialize();
|
|
865
|
+
await this.hibernation.handleAlarm();
|
|
866
|
+
await this.onAlarm();
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Alarm hook for subclasses
|
|
870
|
+
*
|
|
871
|
+
* Override this method to handle scheduled tasks.
|
|
872
|
+
*
|
|
873
|
+
* @example
|
|
874
|
+
* ```typescript
|
|
875
|
+
* async onAlarm(): Promise<void> {
|
|
876
|
+
* // Perform scheduled cleanup
|
|
877
|
+
* await this.cleanupExpiredSessions()
|
|
878
|
+
* }
|
|
879
|
+
* ```
|
|
880
|
+
*/
|
|
881
|
+
async onAlarm() {
|
|
882
|
+
// Override in subclasses
|
|
883
|
+
}
|
|
884
|
+
/**
|
|
885
|
+
* Handle WebSocket message
|
|
886
|
+
*
|
|
887
|
+
* Called when a message is received on a hibernatable WebSocket.
|
|
888
|
+
*
|
|
889
|
+
* @param ws - The WebSocket that received the message
|
|
890
|
+
* @param message - The message data
|
|
891
|
+
*
|
|
892
|
+
* @internal
|
|
893
|
+
*/
|
|
894
|
+
async webSocketMessage(ws, message) {
|
|
895
|
+
await this.initialize();
|
|
896
|
+
this.hibernation.touch();
|
|
897
|
+
// Parse and handle as RPC if it's a string
|
|
898
|
+
if (typeof message === 'string') {
|
|
899
|
+
try {
|
|
900
|
+
const rpcRequest = JSON.parse(message);
|
|
901
|
+
const response = await this.processRPC(rpcRequest);
|
|
902
|
+
ws.send(JSON.stringify(response));
|
|
903
|
+
}
|
|
904
|
+
catch (error) {
|
|
905
|
+
ws.send(JSON.stringify({
|
|
906
|
+
error: { code: -32700, message: 'Parse error' },
|
|
907
|
+
}));
|
|
908
|
+
}
|
|
909
|
+
}
|
|
910
|
+
}
|
|
911
|
+
/**
|
|
912
|
+
* Handle WebSocket close
|
|
913
|
+
*
|
|
914
|
+
* Called when a hibernatable WebSocket is closed.
|
|
915
|
+
* Cleans up CDC subscriptions if this was a CDC WebSocket.
|
|
916
|
+
*
|
|
917
|
+
* @param ws - The WebSocket that was closed
|
|
918
|
+
* @param code - Close code
|
|
919
|
+
* @param reason - Close reason
|
|
920
|
+
* @param wasClean - Whether the close was clean
|
|
921
|
+
*
|
|
922
|
+
* @internal
|
|
923
|
+
*/
|
|
924
|
+
async webSocketClose(ws, code, reason, wasClean) {
|
|
925
|
+
// Clean up CDC subscription if this was a CDC WebSocket
|
|
926
|
+
const cdcWs = ws;
|
|
927
|
+
if (cdcWs.cdcUnsubscribe) {
|
|
928
|
+
cdcWs.cdcUnsubscribe();
|
|
929
|
+
}
|
|
930
|
+
this.hibernation.handleWebSocketClose(ws);
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* Handle WebSocket error
|
|
934
|
+
*
|
|
935
|
+
* Called when an error occurs on a hibernatable WebSocket.
|
|
936
|
+
*
|
|
937
|
+
* @param ws - The WebSocket that errored
|
|
938
|
+
* @param error - The error
|
|
939
|
+
*
|
|
940
|
+
* @internal
|
|
941
|
+
*/
|
|
942
|
+
async webSocketError(ws, error) {
|
|
943
|
+
console.error('WebSocket error:', error);
|
|
944
|
+
this.hibernation.handleWebSocketClose(ws);
|
|
945
|
+
}
|
|
946
|
+
}
|
|
947
|
+
/**
|
|
948
|
+
* Custom error class for Digital Object errors
|
|
949
|
+
*
|
|
950
|
+
* @example
|
|
951
|
+
* ```typescript
|
|
952
|
+
* throw new DOError('NOT_FOUND', 'Resource not found', 404)
|
|
953
|
+
* ```
|
|
954
|
+
*/
|
|
955
|
+
export class DOError extends Error {
|
|
956
|
+
code;
|
|
957
|
+
status;
|
|
958
|
+
details;
|
|
959
|
+
constructor(code, message, status = 500, details) {
|
|
960
|
+
super(message);
|
|
961
|
+
this.code = code;
|
|
962
|
+
this.status = status;
|
|
963
|
+
this.details = details;
|
|
964
|
+
this.name = 'DOError';
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
/**
|
|
968
|
+
* Export the DigitalObject class as default
|
|
969
|
+
*/
|
|
970
|
+
export default DigitalObject;
|
|
971
|
+
//# sourceMappingURL=DigitalObject.js.map
|