typeferry 0.6.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 +88 -0
- package/dist/auth/client/cross-tab-sync.d.ts +21 -0
- package/dist/auth/client/cross-tab-sync.js +56 -0
- package/dist/auth/client/cross-tab-sync.js.map +1 -0
- package/dist/auth/client/index.d.ts +2 -0
- package/dist/auth/client/index.js +3 -0
- package/dist/auth/client/index.js.map +1 -0
- package/dist/auth/client/oauth/google-provider.d.ts +11 -0
- package/dist/auth/client/oauth/google-provider.js +11 -0
- package/dist/auth/client/oauth/google-provider.js.map +1 -0
- package/dist/auth/client/oauth/index.d.ts +4 -0
- package/dist/auth/client/oauth/index.js +3 -0
- package/dist/auth/client/oauth/index.js.map +1 -0
- package/dist/auth/client/oauth/use-google-login.d.ts +39 -0
- package/dist/auth/client/oauth/use-google-login.js +55 -0
- package/dist/auth/client/oauth/use-google-login.js.map +1 -0
- package/dist/auth/client/token-refresh.d.ts +21 -0
- package/dist/auth/client/token-refresh.js +212 -0
- package/dist/auth/client/token-refresh.js.map +1 -0
- package/dist/auth/index.d.ts +7 -0
- package/dist/auth/index.js +9 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/server/cookie-utils.d.ts +42 -0
- package/dist/auth/server/cookie-utils.js +91 -0
- package/dist/auth/server/cookie-utils.js.map +1 -0
- package/dist/auth/server/device-info.d.ts +23 -0
- package/dist/auth/server/device-info.js +52 -0
- package/dist/auth/server/device-info.js.map +1 -0
- package/dist/auth/server/index.d.ts +4 -0
- package/dist/auth/server/index.js +5 -0
- package/dist/auth/server/index.js.map +1 -0
- package/dist/auth/server/jwt-utils.d.ts +29 -0
- package/dist/auth/server/jwt-utils.js +53 -0
- package/dist/auth/server/jwt-utils.js.map +1 -0
- package/dist/auth/server/oauth/google.d.ts +31 -0
- package/dist/auth/server/oauth/google.js +40 -0
- package/dist/auth/server/oauth/google.js.map +1 -0
- package/dist/auth/server/oauth/index.d.ts +3 -0
- package/dist/auth/server/oauth/index.js +2 -0
- package/dist/auth/server/oauth/index.js.map +1 -0
- package/dist/auth/server/oauth/types.d.ts +37 -0
- package/dist/auth/server/oauth/types.js +2 -0
- package/dist/auth/server/oauth/types.js.map +1 -0
- package/dist/auth/server/session-manager.d.ts +46 -0
- package/dist/auth/server/session-manager.js +167 -0
- package/dist/auth/server/session-manager.js.map +1 -0
- package/dist/auth/types.d.ts +197 -0
- package/dist/auth/types.js +2 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/client/call-method-proxy.d.ts +2 -0
- package/dist/client/call-method-proxy.js +22 -0
- package/dist/client/call-method-proxy.js.map +1 -0
- package/dist/client/client-channel.d.ts +43 -0
- package/dist/client/client-channel.js +148 -0
- package/dist/client/client-channel.js.map +1 -0
- package/dist/client/client-http.d.ts +27 -0
- package/dist/client/client-http.js +106 -0
- package/dist/client/client-http.js.map +1 -0
- package/dist/client/client-socket.d.ts +85 -0
- package/dist/client/client-socket.js +317 -0
- package/dist/client/client-socket.js.map +1 -0
- package/dist/client/client.d.ts +149 -0
- package/dist/client/client.js +401 -0
- package/dist/client/client.js.map +1 -0
- package/dist/client/context-manager.d.ts +54 -0
- package/dist/client/context-manager.js +89 -0
- package/dist/client/context-manager.js.map +1 -0
- package/dist/client/idle-timer.d.ts +35 -0
- package/dist/client/idle-timer.js +101 -0
- package/dist/client/idle-timer.js.map +1 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +7 -0
- package/dist/client/index.js.map +1 -0
- package/dist/client/logger.d.ts +76 -0
- package/dist/client/logger.js +129 -0
- package/dist/client/logger.js.map +1 -0
- package/dist/client/visibility-manager.d.ts +62 -0
- package/dist/client/visibility-manager.js +177 -0
- package/dist/client/visibility-manager.js.map +1 -0
- package/dist/ejson/adjust-types-from-json-value.d.ts +1 -0
- package/dist/ejson/adjust-types-from-json-value.js +35 -0
- package/dist/ejson/adjust-types-from-json-value.js.map +1 -0
- package/dist/ejson/base64.d.ts +11 -0
- package/dist/ejson/base64.js +87 -0
- package/dist/ejson/base64.js.map +1 -0
- package/dist/ejson/built-in-converters.d.ts +1 -0
- package/dist/ejson/built-in-converters.js +137 -0
- package/dist/ejson/built-in-converters.js.map +1 -0
- package/dist/ejson/clone.d.ts +1 -0
- package/dist/ejson/clone.js +80 -0
- package/dist/ejson/clone.js.map +1 -0
- package/dist/ejson/custom-models.d.ts +38 -0
- package/dist/ejson/custom-models.js +76 -0
- package/dist/ejson/custom-models.js.map +1 -0
- package/dist/ejson/custom-types.d.ts +1 -0
- package/dist/ejson/custom-types.js +2 -0
- package/dist/ejson/custom-types.js.map +1 -0
- package/dist/ejson/equals.d.ts +1 -0
- package/dist/ejson/equals.js +117 -0
- package/dist/ejson/equals.js.map +1 -0
- package/dist/ejson/from-json-value.d.ts +1 -0
- package/dist/ejson/from-json-value.js +13 -0
- package/dist/ejson/from-json-value.js.map +1 -0
- package/dist/ejson/helpers/adjust-types-to-json-value.d.ts +1 -0
- package/dist/ejson/helpers/adjust-types-to-json-value.js +36 -0
- package/dist/ejson/helpers/adjust-types-to-json-value.js.map +1 -0
- package/dist/ejson/helpers/from-json-value-helper.d.ts +1 -0
- package/dist/ejson/helpers/from-json-value-helper.js +24 -0
- package/dist/ejson/helpers/from-json-value-helper.js.map +1 -0
- package/dist/ejson/helpers/to-json-value-helper.d.ts +1 -0
- package/dist/ejson/helpers/to-json-value-helper.js +15 -0
- package/dist/ejson/helpers/to-json-value-helper.js.map +1 -0
- package/dist/ejson/index.d.ts +27 -0
- package/dist/ejson/index.js +54 -0
- package/dist/ejson/index.js.map +1 -0
- package/dist/ejson/is-binary.d.ts +2 -0
- package/dist/ejson/is-binary.js +5 -0
- package/dist/ejson/is-binary.js.map +1 -0
- package/dist/ejson/parse.d.ts +6 -0
- package/dist/ejson/parse.js +12 -0
- package/dist/ejson/parse.js.map +1 -0
- package/dist/ejson/stable-stringify.d.ts +10 -0
- package/dist/ejson/stable-stringify.js +25 -0
- package/dist/ejson/stable-stringify.js.map +1 -0
- package/dist/ejson/stringify.d.ts +5 -0
- package/dist/ejson/stringify.js +15 -0
- package/dist/ejson/stringify.js.map +1 -0
- package/dist/ejson/to-json-value.d.ts +1 -0
- package/dist/ejson/to-json-value.js +17 -0
- package/dist/ejson/to-json-value.js.map +1 -0
- package/dist/ejson/utils.d.ts +18 -0
- package/dist/ejson/utils.js +43 -0
- package/dist/ejson/utils.js.map +1 -0
- package/dist/mongodb/change-streams.d.ts +31 -0
- package/dist/mongodb/change-streams.js +142 -0
- package/dist/mongodb/change-streams.js.map +1 -0
- package/dist/mongodb/client.d.ts +13 -0
- package/dist/mongodb/client.js +30 -0
- package/dist/mongodb/client.js.map +1 -0
- package/dist/mongodb/decorators/collection.d.ts +9 -0
- package/dist/mongodb/decorators/collection.js +26 -0
- package/dist/mongodb/decorators/collection.js.map +1 -0
- package/dist/mongodb/decorators/index.d.ts +4 -0
- package/dist/mongodb/decorators/index.js +5 -0
- package/dist/mongodb/decorators/index.js.map +1 -0
- package/dist/mongodb/decorators/metadata.d.ts +21 -0
- package/dist/mongodb/decorators/metadata.js +29 -0
- package/dist/mongodb/decorators/metadata.js.map +1 -0
- package/dist/mongodb/decorators/register.d.ts +3 -0
- package/dist/mongodb/decorators/register.js +10 -0
- package/dist/mongodb/decorators/register.js.map +1 -0
- package/dist/mongodb/decorators/watch.d.ts +4 -0
- package/dist/mongodb/decorators/watch.js +10 -0
- package/dist/mongodb/decorators/watch.js.map +1 -0
- package/dist/mongodb/filters.d.ts +20 -0
- package/dist/mongodb/filters.js +40 -0
- package/dist/mongodb/filters.js.map +1 -0
- package/dist/mongodb/find-one-or-create.d.ts +4 -0
- package/dist/mongodb/find-one-or-create.js +16 -0
- package/dist/mongodb/find-one-or-create.js.map +1 -0
- package/dist/mongodb/index.d.ts +10 -0
- package/dist/mongodb/index.js +11 -0
- package/dist/mongodb/index.js.map +1 -0
- package/dist/mongodb/live/client.d.ts +52 -0
- package/dist/mongodb/live/client.js +266 -0
- package/dist/mongodb/live/client.js.map +1 -0
- package/dist/mongodb/live/engine.d.ts +55 -0
- package/dist/mongodb/live/engine.js +440 -0
- package/dist/mongodb/live/engine.js.map +1 -0
- package/dist/mongodb/live/index.d.ts +5 -0
- package/dist/mongodb/live/index.js +6 -0
- package/dist/mongodb/live/index.js.map +1 -0
- package/dist/mongodb/live/observer.d.ts +58 -0
- package/dist/mongodb/live/observer.js +246 -0
- package/dist/mongodb/live/observer.js.map +1 -0
- package/dist/mongodb/live/publication.d.ts +4 -0
- package/dist/mongodb/live/publication.js +30 -0
- package/dist/mongodb/live/publication.js.map +1 -0
- package/dist/mongodb/live/source.d.ts +55 -0
- package/dist/mongodb/live/source.js +197 -0
- package/dist/mongodb/live/source.js.map +1 -0
- package/dist/mongodb/live/types.d.ts +266 -0
- package/dist/mongodb/live/types.js +29 -0
- package/dist/mongodb/live/types.js.map +1 -0
- package/dist/mongodb/live/window.d.ts +7 -0
- package/dist/mongodb/live/window.js +93 -0
- package/dist/mongodb/live/window.js.map +1 -0
- package/dist/mongodb/registry.d.ts +35 -0
- package/dist/mongodb/registry.js +129 -0
- package/dist/mongodb/registry.js.map +1 -0
- package/dist/mongodb/schema.d.ts +16 -0
- package/dist/mongodb/schema.js +43 -0
- package/dist/mongodb/schema.js.map +1 -0
- package/dist/mongodb/timestamps.d.ts +17 -0
- package/dist/mongodb/timestamps.js +27 -0
- package/dist/mongodb/timestamps.js.map +1 -0
- package/dist/mongodb/types.d.ts +120 -0
- package/dist/mongodb/types.js +10 -0
- package/dist/mongodb/types.js.map +1 -0
- package/dist/react/components/client-provider.d.ts +8 -0
- package/dist/react/components/client-provider.js +23 -0
- package/dist/react/components/client-provider.js.map +1 -0
- package/dist/react/components/index.d.ts +1 -0
- package/dist/react/components/index.js +2 -0
- package/dist/react/components/index.js.map +1 -0
- package/dist/react/hooks/index.d.ts +13 -0
- package/dist/react/hooks/index.js +14 -0
- package/dist/react/hooks/index.js.map +1 -0
- package/dist/react/hooks/use-auth.d.ts +4 -0
- package/dist/react/hooks/use-auth.js +35 -0
- package/dist/react/hooks/use-auth.js.map +1 -0
- package/dist/react/hooks/use-caller.d.ts +5 -0
- package/dist/react/hooks/use-caller.js +13 -0
- package/dist/react/hooks/use-caller.js.map +1 -0
- package/dist/react/hooks/use-channel.d.ts +1 -0
- package/dist/react/hooks/use-channel.js +7 -0
- package/dist/react/hooks/use-channel.js.map +1 -0
- package/dist/react/hooks/use-circuit-breaker.d.ts +6 -0
- package/dist/react/hooks/use-circuit-breaker.js +16 -0
- package/dist/react/hooks/use-circuit-breaker.js.map +1 -0
- package/dist/react/hooks/use-client.d.ts +3 -0
- package/dist/react/hooks/use-client.js +13 -0
- package/dist/react/hooks/use-client.js.map +1 -0
- package/dist/react/hooks/use-connection-state.d.ts +13 -0
- package/dist/react/hooks/use-connection-state.js +55 -0
- package/dist/react/hooks/use-connection-state.js.map +1 -0
- package/dist/react/hooks/use-creation.d.ts +5 -0
- package/dist/react/hooks/use-creation.js +17 -0
- package/dist/react/hooks/use-creation.js.map +1 -0
- package/dist/react/hooks/use-deps-change.d.ts +1 -0
- package/dist/react/hooks/use-deps-change.js +11 -0
- package/dist/react/hooks/use-deps-change.js.map +1 -0
- package/dist/react/hooks/use-local-event.d.ts +13 -0
- package/dist/react/hooks/use-local-event.js +32 -0
- package/dist/react/hooks/use-local-event.js.map +1 -0
- package/dist/react/hooks/use-method-refresh.d.ts +15 -0
- package/dist/react/hooks/use-method-refresh.js +48 -0
- package/dist/react/hooks/use-method-refresh.js.map +1 -0
- package/dist/react/hooks/use-method.d.ts +26 -0
- package/dist/react/hooks/use-method.js +161 -0
- package/dist/react/hooks/use-method.js.map +1 -0
- package/dist/react/hooks/use-mongodb-live-publication.d.ts +13 -0
- package/dist/react/hooks/use-mongodb-live-publication.js +26 -0
- package/dist/react/hooks/use-mongodb-live-publication.js.map +1 -0
- package/dist/react/hooks/use-object.d.ts +2 -0
- package/dist/react/hooks/use-object.js +22 -0
- package/dist/react/hooks/use-object.js.map +1 -0
- package/dist/react/hooks/use-subscribe.d.ts +8 -0
- package/dist/react/hooks/use-subscribe.js +49 -0
- package/dist/react/hooks/use-subscribe.js.map +1 -0
- package/dist/react/hooks/use-throttled-events.d.ts +7 -0
- package/dist/react/hooks/use-throttled-events.js +11 -0
- package/dist/react/hooks/use-throttled-events.js.map +1 -0
- package/dist/react/hooks/use-token-refresh.d.ts +13 -0
- package/dist/react/hooks/use-token-refresh.js +40 -0
- package/dist/react/hooks/use-token-refresh.js.map +1 -0
- package/dist/react/index.d.ts +2 -0
- package/dist/react/index.js +3 -0
- package/dist/react/index.js.map +1 -0
- package/dist/server/client-node.d.ts +76 -0
- package/dist/server/client-node.js +159 -0
- package/dist/server/client-node.js.map +1 -0
- package/dist/server/create-method-proxy.d.ts +2 -0
- package/dist/server/create-method-proxy.js +16 -0
- package/dist/server/create-method-proxy.js.map +1 -0
- package/dist/server/decorators/cached.d.ts +37 -0
- package/dist/server/decorators/cached.js +65 -0
- package/dist/server/decorators/cached.js.map +1 -0
- package/dist/server/decorators/index.d.ts +14 -0
- package/dist/server/decorators/index.js +13 -0
- package/dist/server/decorators/index.js.map +1 -0
- package/dist/server/decorators/infer.d.ts +78 -0
- package/dist/server/decorators/infer.js +11 -0
- package/dist/server/decorators/infer.js.map +1 -0
- package/dist/server/decorators/metadata.d.ts +60 -0
- package/dist/server/decorators/metadata.js +77 -0
- package/dist/server/decorators/metadata.js.map +1 -0
- package/dist/server/decorators/method.d.ts +14 -0
- package/dist/server/decorators/method.js +25 -0
- package/dist/server/decorators/method.js.map +1 -0
- package/dist/server/decorators/namespace.d.ts +25 -0
- package/dist/server/decorators/namespace.js +34 -0
- package/dist/server/decorators/namespace.js.map +1 -0
- package/dist/server/decorators/protected.d.ts +36 -0
- package/dist/server/decorators/protected.js +61 -0
- package/dist/server/decorators/protected.js.map +1 -0
- package/dist/server/decorators/register.d.ts +25 -0
- package/dist/server/decorators/register.js +72 -0
- package/dist/server/decorators/register.js.map +1 -0
- package/dist/server/decorators/schema.d.ts +17 -0
- package/dist/server/decorators/schema.js +27 -0
- package/dist/server/decorators/schema.js.map +1 -0
- package/dist/server/decorators/use.d.ts +22 -0
- package/dist/server/decorators/use.js +32 -0
- package/dist/server/decorators/use.js.map +1 -0
- package/dist/server/default-methods.d.ts +8 -0
- package/dist/server/default-methods.js +8 -0
- package/dist/server/default-methods.js.map +1 -0
- package/dist/server/event.d.ts +42 -0
- package/dist/server/event.js +53 -0
- package/dist/server/event.js.map +1 -0
- package/dist/server/index.d.ts +10 -0
- package/dist/server/index.js +11 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/method.d.ts +95 -0
- package/dist/server/method.js +113 -0
- package/dist/server/method.js.map +1 -0
- package/dist/server/methods.d.ts +11 -0
- package/dist/server/methods.js +74 -0
- package/dist/server/methods.js.map +1 -0
- package/dist/server/request-types.d.ts +20 -0
- package/dist/server/request-types.js +8 -0
- package/dist/server/request-types.js.map +1 -0
- package/dist/server/room-registry.d.ts +28 -0
- package/dist/server/room-registry.js +83 -0
- package/dist/server/room-registry.js.map +1 -0
- package/dist/server/server-channel.d.ts +32 -0
- package/dist/server/server-channel.js +104 -0
- package/dist/server/server-channel.js.map +1 -0
- package/dist/server/server.d.ts +124 -0
- package/dist/server/server.js +243 -0
- package/dist/server/server.js.map +1 -0
- package/dist/server/transports/hono-rate-limit.d.ts +15 -0
- package/dist/server/transports/hono-rate-limit.js +36 -0
- package/dist/server/transports/hono-rate-limit.js.map +1 -0
- package/dist/server/transports/index.d.ts +4 -0
- package/dist/server/transports/index.js +5 -0
- package/dist/server/transports/index.js.map +1 -0
- package/dist/server/transports/node-hono-transport-contract.d.ts +16 -0
- package/dist/server/transports/node-hono-transport-contract.js +18 -0
- package/dist/server/transports/node-hono-transport-contract.js.map +1 -0
- package/dist/server/transports/node-hono-transport.d.ts +47 -0
- package/dist/server/transports/node-hono-transport.js +327 -0
- package/dist/server/transports/node-hono-transport.js.map +1 -0
- package/dist/server/transports/redis-transport.d.ts +34 -0
- package/dist/server/transports/redis-transport.js +84 -0
- package/dist/server/transports/redis-transport.js.map +1 -0
- package/dist/server/transports/websocket-transport.d.ts +42 -0
- package/dist/server/transports/websocket-transport.js +174 -0
- package/dist/server/transports/websocket-transport.js.map +1 -0
- package/dist/server/transports/ws-shared.d.ts +37 -0
- package/dist/server/transports/ws-shared.js +188 -0
- package/dist/server/transports/ws-shared.js.map +1 -0
- package/dist/server/typeferry-async-local-storage.d.ts +5 -0
- package/dist/server/typeferry-async-local-storage.js +6 -0
- package/dist/server/typeferry-async-local-storage.js.map +1 -0
- package/dist/server/types.d.ts +27 -0
- package/dist/server/types.js +11 -0
- package/dist/server/types.js.map +1 -0
- package/dist/utils/constants.d.ts +72 -0
- package/dist/utils/constants.js +79 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/environment.d.ts +8 -0
- package/dist/utils/environment.js +17 -0
- package/dist/utils/environment.js.map +1 -0
- package/dist/utils/errors.d.ts +26 -0
- package/dist/utils/errors.js +35 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/event-emitter.d.ts +37 -0
- package/dist/utils/event-emitter.js +104 -0
- package/dist/utils/event-emitter.js.map +1 -0
- package/dist/utils/events.d.ts +7 -0
- package/dist/utils/events.js +23 -0
- package/dist/utils/events.js.map +1 -0
- package/dist/utils/helpers.d.ts +14 -0
- package/dist/utils/helpers.js +40 -0
- package/dist/utils/helpers.js.map +1 -0
- package/dist/utils/index.d.ts +11 -0
- package/dist/utils/index.js +12 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/intercept.d.ts +7 -0
- package/dist/utils/intercept.js +21 -0
- package/dist/utils/intercept.js.map +1 -0
- package/dist/utils/iterator.d.ts +9 -0
- package/dist/utils/iterator.js +28 -0
- package/dist/utils/iterator.js.map +1 -0
- package/dist/utils/lodash.d.ts +33 -0
- package/dist/utils/lodash.js +123 -0
- package/dist/utils/lodash.js.map +1 -0
- package/dist/utils/presentation.d.ts +19 -0
- package/dist/utils/presentation.js +25 -0
- package/dist/utils/presentation.js.map +1 -0
- package/dist/utils/promise.d.ts +6 -0
- package/dist/utils/promise.js +17 -0
- package/dist/utils/promise.js.map +1 -0
- package/dist/utils/protocol.d.ts +110 -0
- package/dist/utils/protocol.js +59 -0
- package/dist/utils/protocol.js.map +1 -0
- package/dist/utils/types.d.ts +23 -0
- package/dist/utils/types.js +2 -0
- package/dist/utils/types.js.map +1 -0
- package/package.json +187 -0
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import perf_hooks from 'perf_hooks';
|
|
2
|
+
import { isEmpty } from '../utils/lodash.js';
|
|
3
|
+
import { EJSON } from '../ejson/index.js';
|
|
4
|
+
import { Errors, intercept, Presentation, SchemaValidationError, ServerEvents, } from '../utils/index.js';
|
|
5
|
+
import { TypeFerryAsyncLocalStorage } from './typeferry-async-local-storage.js';
|
|
6
|
+
/** Stable marker used when sensitive method telemetry is intentionally hidden. */
|
|
7
|
+
export const REDACTED_METHOD_TELEMETRY = '[REDACTED]';
|
|
8
|
+
/** Returns a method telemetry field with the configured sensitivity applied. */
|
|
9
|
+
export function redactMethodTelemetry(method, value) {
|
|
10
|
+
return method.isSensitive ? REDACTED_METHOD_TELEMETRY : value;
|
|
11
|
+
}
|
|
12
|
+
function customMemoize(fn, options = {}) {
|
|
13
|
+
const cache = new Map();
|
|
14
|
+
const { maxAge = 60000 } = options;
|
|
15
|
+
return function (...args) {
|
|
16
|
+
const key = EJSON.stringify(args[0]); // Normalize first argument (params)
|
|
17
|
+
const now = Date.now();
|
|
18
|
+
const cached = cache.get(key);
|
|
19
|
+
if (cached && now - cached.timestamp < maxAge) {
|
|
20
|
+
return cached.value;
|
|
21
|
+
}
|
|
22
|
+
const result = fn.apply(this, args);
|
|
23
|
+
cache.set(key, { value: result, timestamp: now });
|
|
24
|
+
return result;
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Represents a registered TypeFerry RPC method with validation and middleware support.
|
|
29
|
+
*
|
|
30
|
+
* Methods are the core RPC primitives in TypeFerry. Each method can have:
|
|
31
|
+
* - Input validation via Zod schemas
|
|
32
|
+
* - Middleware chain for authentication/authorization
|
|
33
|
+
* - Result caching with configurable TTL
|
|
34
|
+
* - Execution time tracking
|
|
35
|
+
*
|
|
36
|
+
* @typeParam Schema - The Zod schema type for input validation
|
|
37
|
+
* @typeParam Result - The return type of the method
|
|
38
|
+
*/
|
|
39
|
+
export class Method {
|
|
40
|
+
uuid;
|
|
41
|
+
fn;
|
|
42
|
+
isProtected;
|
|
43
|
+
isSensitive;
|
|
44
|
+
middleware;
|
|
45
|
+
schema = null;
|
|
46
|
+
name;
|
|
47
|
+
server;
|
|
48
|
+
constructor(server, name, fn, opts) {
|
|
49
|
+
const { cache, maxAge = 60000, schema } = opts ?? {};
|
|
50
|
+
this.server = server;
|
|
51
|
+
this.name = name;
|
|
52
|
+
this.uuid = Presentation.uuid();
|
|
53
|
+
this.isProtected = opts?.protected;
|
|
54
|
+
this.isSensitive = opts?.sensitive ?? false;
|
|
55
|
+
this.middleware = opts?.middleware;
|
|
56
|
+
this.fn = cache ? customMemoize(fn, { maxAge }) : fn;
|
|
57
|
+
this.schema = schema;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Executes the middleware chain, passing params through each middleware.
|
|
61
|
+
* Each middleware can transform or augment the params before passing to the next.
|
|
62
|
+
*/
|
|
63
|
+
async runMiddleware(parameters, node) {
|
|
64
|
+
if (isEmpty(this.middleware))
|
|
65
|
+
return parameters;
|
|
66
|
+
const wrapped = this.middleware.map((m) => intercept(m));
|
|
67
|
+
let buffer = parameters;
|
|
68
|
+
for (const step of wrapped) {
|
|
69
|
+
buffer = await step.call(node, buffer);
|
|
70
|
+
}
|
|
71
|
+
return buffer;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Executes the method with validation, middleware, and timing.
|
|
75
|
+
*
|
|
76
|
+
* Execution flow:
|
|
77
|
+
* 1. Validate params against Zod schema (if provided)
|
|
78
|
+
* 2. Run middleware chain
|
|
79
|
+
* 3. Execute method handler
|
|
80
|
+
* 4. Emit execution event with timing data
|
|
81
|
+
*
|
|
82
|
+
* @throws {SchemaValidationError} When params fail Zod validation
|
|
83
|
+
*/
|
|
84
|
+
async exec(parameters, node) {
|
|
85
|
+
const start = perf_hooks.performance.now();
|
|
86
|
+
let cleanParameters = parameters;
|
|
87
|
+
if (this.schema) {
|
|
88
|
+
// Normalize undefined/null params to empty object for schema validation.
|
|
89
|
+
// This allows methods with all-optional fields to be called without params.
|
|
90
|
+
const parametersToValidate = parameters ?? {};
|
|
91
|
+
const result = this.schema.safeParse(parametersToValidate);
|
|
92
|
+
if (!result.success) {
|
|
93
|
+
const errorMessages = result.error.issues.map((issue) => `${issue.path.join('.')}: ${issue.message}`);
|
|
94
|
+
console.error(`Schema validation failed for ${this.name}:`, errorMessages);
|
|
95
|
+
throw new SchemaValidationError(`${Errors.INVALID_PARAMS}: ${errorMessages.join(', ')}`, errorMessages);
|
|
96
|
+
}
|
|
97
|
+
cleanParameters = result.data;
|
|
98
|
+
}
|
|
99
|
+
const result = await TypeFerryAsyncLocalStorage.run({ executionId: Presentation.uuid(), context: node.context }, async () => {
|
|
100
|
+
const middlewareResult = await this.runMiddleware(cleanParameters, node);
|
|
101
|
+
return this.fn.call(node, middlewareResult);
|
|
102
|
+
});
|
|
103
|
+
const end = perf_hooks.performance.now();
|
|
104
|
+
this.server.emit(ServerEvents.METHOD_EXECUTION, {
|
|
105
|
+
method: this.name,
|
|
106
|
+
time: end - start,
|
|
107
|
+
params: redactMethodTelemetry(this, cleanParameters),
|
|
108
|
+
result: redactMethodTelemetry(this, result),
|
|
109
|
+
});
|
|
110
|
+
return result;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=method.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"method.js","sourceRoot":"","sources":["../../src/server/method.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { z } from 'zod';
|
|
2
|
+
import { Method } from './method.js';
|
|
3
|
+
import { Server } from './server.js';
|
|
4
|
+
/**
|
|
5
|
+
* Generates a room name for a channel/event subscription.
|
|
6
|
+
* Format: `typeferry:${channel}:${event}`
|
|
7
|
+
*/
|
|
8
|
+
export declare function getRoomName(channel: string, eventName: string): string;
|
|
9
|
+
export declare const rpcOff: (server: Server, method: string) => Method<z.ZodType, unknown>;
|
|
10
|
+
export declare const rpcOn: (server: Server, method: string) => Method<z.ZodType, unknown>;
|
|
11
|
+
export declare const rpcLogout: (server: Server, method: string) => Method<z.ZodType, unknown>;
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { isEmpty } from '../utils/lodash.js';
|
|
2
|
+
import { NO_CHANNEL, ServerEvents } from '../utils/index.js';
|
|
3
|
+
import { Method } from './method.js';
|
|
4
|
+
import { Server } from './server.js';
|
|
5
|
+
/**
|
|
6
|
+
* Generates a room name for a channel/event subscription.
|
|
7
|
+
* Format: `typeferry:${channel}:${event}`
|
|
8
|
+
*/
|
|
9
|
+
export function getRoomName(channel, eventName) {
|
|
10
|
+
return `typeferry:${channel}:${eventName}`;
|
|
11
|
+
}
|
|
12
|
+
export const rpcOff = (server, method) => new Method(server, method, function ({ events, channel = NO_CHANNEL }) {
|
|
13
|
+
if (!this.socket)
|
|
14
|
+
return {};
|
|
15
|
+
const rooms = server.webSocketTransport?.rooms;
|
|
16
|
+
if (!rooms)
|
|
17
|
+
return {};
|
|
18
|
+
return events.reduce((acc, eventName) => {
|
|
19
|
+
const event = server.events.get(eventName);
|
|
20
|
+
if (!event) {
|
|
21
|
+
console.log('[TypeFerry] Event Not Found:', eventName);
|
|
22
|
+
return { ...acc, [eventName]: false };
|
|
23
|
+
}
|
|
24
|
+
const roomName = getRoomName(channel, eventName);
|
|
25
|
+
rooms.leave(this.socket, roomName);
|
|
26
|
+
return { ...acc, [eventName]: true };
|
|
27
|
+
}, {});
|
|
28
|
+
}, { protected: false });
|
|
29
|
+
/**
|
|
30
|
+
* Checks if a client can subscribe to an event and joins the room.
|
|
31
|
+
*/
|
|
32
|
+
async function canSubscribeToEvent(server, client, eventName, channel) {
|
|
33
|
+
const event = server.events.get(eventName);
|
|
34
|
+
if (!event) {
|
|
35
|
+
console.log('[TypeFerry] Event Not Found:', eventName);
|
|
36
|
+
return false;
|
|
37
|
+
}
|
|
38
|
+
const eventAllowed = !event.isProtected || client.authenticated;
|
|
39
|
+
if (!eventAllowed)
|
|
40
|
+
return false;
|
|
41
|
+
const subscribeAllowed = await event.shouldSubscribe(client, eventName, channel);
|
|
42
|
+
if (!subscribeAllowed)
|
|
43
|
+
return false;
|
|
44
|
+
if (!client.socket)
|
|
45
|
+
return false;
|
|
46
|
+
const rooms = server.webSocketTransport?.rooms;
|
|
47
|
+
if (!rooms)
|
|
48
|
+
return false;
|
|
49
|
+
const roomName = getRoomName(channel, eventName);
|
|
50
|
+
rooms.join(client.socket, roomName);
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
export const rpcOn = (server, method) => new Method(server, method, async function ({ events, channel = NO_CHANNEL }) {
|
|
54
|
+
if (isEmpty(events))
|
|
55
|
+
return {};
|
|
56
|
+
const channelAllowed = await server.shouldAllowChannelSubscribe(this, channel);
|
|
57
|
+
const acc = {};
|
|
58
|
+
for (const eventName of events) {
|
|
59
|
+
if (!channelAllowed) {
|
|
60
|
+
acc[eventName] = false;
|
|
61
|
+
continue;
|
|
62
|
+
}
|
|
63
|
+
acc[eventName] = await canSubscribeToEvent(server, this, eventName, channel);
|
|
64
|
+
}
|
|
65
|
+
return acc;
|
|
66
|
+
}, { protected: false });
|
|
67
|
+
export const rpcLogout = (server, method) => new Method(server, method, async function () {
|
|
68
|
+
this.context = null;
|
|
69
|
+
this.authenticated = false;
|
|
70
|
+
this.userId = null;
|
|
71
|
+
server.emit(ServerEvents.LOGOUT, this);
|
|
72
|
+
return true;
|
|
73
|
+
}, { protected: true });
|
|
74
|
+
//# sourceMappingURL=methods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"methods.js","sourceRoot":"","sources":["../../src/server/methods.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic request/response interfaces for TypeFerry.
|
|
3
|
+
*
|
|
4
|
+
* Hono request adapters satisfy these contracts, keeping `ClientNode` and
|
|
5
|
+
* authentication logic independent from the HTTP adapter internals.
|
|
6
|
+
*/
|
|
7
|
+
/** Minimal request interface for auth and tracking. */
|
|
8
|
+
export interface TypeFerryRequest {
|
|
9
|
+
headers: Record<string, string | string[] | undefined>;
|
|
10
|
+
ip?: string;
|
|
11
|
+
path?: string;
|
|
12
|
+
get?: (name: string) => string | undefined;
|
|
13
|
+
socket?: {
|
|
14
|
+
remoteAddress?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/** Minimal response interface for cookie/header setting. */
|
|
18
|
+
export interface TypeFerryResponse {
|
|
19
|
+
setHeader(name: string, value: string): void;
|
|
20
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Framework-agnostic request/response interfaces for TypeFerry.
|
|
3
|
+
*
|
|
4
|
+
* Hono request adapters satisfy these contracts, keeping `ClientNode` and
|
|
5
|
+
* authentication logic independent from the HTTP adapter internals.
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
|
8
|
+
//# sourceMappingURL=request-types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request-types.js","sourceRoot":"","sources":["../../src/server/request-types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { TypeFerrySocket } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* In-memory room/subscription registry replacing Socket.IO's room system.
|
|
4
|
+
*
|
|
5
|
+
* Maintains a bidirectional index for O(1) join/leave/broadcast and O(1)
|
|
6
|
+
* cleanup when a socket disconnects (via the reverse index).
|
|
7
|
+
*/
|
|
8
|
+
export declare class RoomRegistry {
|
|
9
|
+
/** room name → set of sockets subscribed to that room */
|
|
10
|
+
private rooms;
|
|
11
|
+
/** socket → set of rooms it has joined (reverse index for fast cleanup) */
|
|
12
|
+
private socketRooms;
|
|
13
|
+
/** Adds a socket to a room. Idempotent. */
|
|
14
|
+
join(ws: TypeFerrySocket, room: string): void;
|
|
15
|
+
/** Removes a socket from a room. Cleans up empty rooms. */
|
|
16
|
+
leave(ws: TypeFerrySocket, room: string): void;
|
|
17
|
+
/** Removes a socket from all rooms. Called on disconnect. */
|
|
18
|
+
leaveAll(ws: TypeFerrySocket): void;
|
|
19
|
+
/**
|
|
20
|
+
* Sends `data` to every socket in `room`.
|
|
21
|
+
* Optionally excludes a single socket (e.g. the originator).
|
|
22
|
+
*/
|
|
23
|
+
broadcast(room: string, data: string, exclude?: TypeFerrySocket): void;
|
|
24
|
+
/** Returns true if `ws` is a member of `room`. */
|
|
25
|
+
has(ws: TypeFerrySocket, room: string): boolean;
|
|
26
|
+
/** Returns the number of sockets in a room. */
|
|
27
|
+
getRoomSize(room: string): number;
|
|
28
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { SocketState } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* In-memory room/subscription registry replacing Socket.IO's room system.
|
|
4
|
+
*
|
|
5
|
+
* Maintains a bidirectional index for O(1) join/leave/broadcast and O(1)
|
|
6
|
+
* cleanup when a socket disconnects (via the reverse index).
|
|
7
|
+
*/
|
|
8
|
+
export class RoomRegistry {
|
|
9
|
+
/** room name → set of sockets subscribed to that room */
|
|
10
|
+
rooms = new Map();
|
|
11
|
+
/** socket → set of rooms it has joined (reverse index for fast cleanup) */
|
|
12
|
+
socketRooms = new Map();
|
|
13
|
+
/** Adds a socket to a room. Idempotent. */
|
|
14
|
+
join(ws, room) {
|
|
15
|
+
let members = this.rooms.get(room);
|
|
16
|
+
if (!members) {
|
|
17
|
+
members = new Set();
|
|
18
|
+
this.rooms.set(room, members);
|
|
19
|
+
}
|
|
20
|
+
members.add(ws);
|
|
21
|
+
let joined = this.socketRooms.get(ws);
|
|
22
|
+
if (!joined) {
|
|
23
|
+
joined = new Set();
|
|
24
|
+
this.socketRooms.set(ws, joined);
|
|
25
|
+
}
|
|
26
|
+
joined.add(room);
|
|
27
|
+
}
|
|
28
|
+
/** Removes a socket from a room. Cleans up empty rooms. */
|
|
29
|
+
leave(ws, room) {
|
|
30
|
+
const members = this.rooms.get(room);
|
|
31
|
+
if (members) {
|
|
32
|
+
members.delete(ws);
|
|
33
|
+
if (members.size === 0)
|
|
34
|
+
this.rooms.delete(room);
|
|
35
|
+
}
|
|
36
|
+
const joined = this.socketRooms.get(ws);
|
|
37
|
+
if (joined) {
|
|
38
|
+
joined.delete(room);
|
|
39
|
+
if (joined.size === 0)
|
|
40
|
+
this.socketRooms.delete(ws);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** Removes a socket from all rooms. Called on disconnect. */
|
|
44
|
+
leaveAll(ws) {
|
|
45
|
+
const joined = this.socketRooms.get(ws);
|
|
46
|
+
if (!joined)
|
|
47
|
+
return;
|
|
48
|
+
for (const room of joined) {
|
|
49
|
+
const members = this.rooms.get(room);
|
|
50
|
+
if (members) {
|
|
51
|
+
members.delete(ws);
|
|
52
|
+
if (members.size === 0)
|
|
53
|
+
this.rooms.delete(room);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
this.socketRooms.delete(ws);
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Sends `data` to every socket in `room`.
|
|
60
|
+
* Optionally excludes a single socket (e.g. the originator).
|
|
61
|
+
*/
|
|
62
|
+
broadcast(room, data, exclude) {
|
|
63
|
+
const members = this.rooms.get(room);
|
|
64
|
+
if (!members)
|
|
65
|
+
return;
|
|
66
|
+
for (const ws of members) {
|
|
67
|
+
if (ws === exclude)
|
|
68
|
+
continue;
|
|
69
|
+
if (ws.readyState === SocketState.OPEN) {
|
|
70
|
+
ws.send(data);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/** Returns true if `ws` is a member of `room`. */
|
|
75
|
+
has(ws, room) {
|
|
76
|
+
return this.rooms.get(room)?.has(ws) ?? false;
|
|
77
|
+
}
|
|
78
|
+
/** Returns the number of sockets in a room. */
|
|
79
|
+
getRoomSize(room) {
|
|
80
|
+
return this.rooms.get(room)?.size ?? 0;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=room-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"room-registry.js","sourceRoot":"","sources":["../../src/server/room-registry.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import EventEmitter2 from '../utils/event-emitter.js';
|
|
2
|
+
import type { ClientNode } from './client-node.js';
|
|
3
|
+
import type { EventOptions } from './event.js';
|
|
4
|
+
import { Event } from './event.js';
|
|
5
|
+
import type { Server } from './server.js';
|
|
6
|
+
export declare class ServerChannel extends EventEmitter2 {
|
|
7
|
+
channelName: string;
|
|
8
|
+
server: Server;
|
|
9
|
+
constructor(channelName: string);
|
|
10
|
+
setServer(server: Server): void;
|
|
11
|
+
/**
|
|
12
|
+
* Broadcasts a pre-encoded event payload to all subscribed clients.
|
|
13
|
+
* The payload already contains the wire protocol `t` field (set by
|
|
14
|
+
* Event.handler), so no re-encoding is needed.
|
|
15
|
+
* @param excludeUuid - Optional client uuid to exclude from receiving the event
|
|
16
|
+
*/
|
|
17
|
+
propagate(event: string, payload: string, excludeUuid?: string): void;
|
|
18
|
+
defer<T = any>(event: string, params?: T): void;
|
|
19
|
+
/** Refreshes a method by its identifier. */
|
|
20
|
+
refresh(method: string): void;
|
|
21
|
+
/** Declares a new event. */
|
|
22
|
+
addEvent(name: string, opts?: EventOptions): void;
|
|
23
|
+
get list(): string[];
|
|
24
|
+
get length(): number;
|
|
25
|
+
get(event: string): Event;
|
|
26
|
+
has(event: string): boolean;
|
|
27
|
+
delete(event: string): boolean;
|
|
28
|
+
/**
|
|
29
|
+
* Checks if a client is subscribed to an event via the RoomRegistry.
|
|
30
|
+
*/
|
|
31
|
+
isSubscribed(client: ClientNode, event: Event): boolean;
|
|
32
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
import { TypeFerryEvents, ServerEvents } from '../utils/index.js';
|
|
2
|
+
import EventEmitter2 from '../utils/event-emitter.js';
|
|
3
|
+
import { Event } from './event.js';
|
|
4
|
+
import { getRoomName } from './methods.js';
|
|
5
|
+
import { HttpTransportEvents, WebSocketTransportEvents } from './transports/index.js';
|
|
6
|
+
const SystemEvents = [
|
|
7
|
+
...Object.values(HttpTransportEvents),
|
|
8
|
+
...Object.values(ServerEvents),
|
|
9
|
+
...Object.values(WebSocketTransportEvents),
|
|
10
|
+
];
|
|
11
|
+
export class ServerChannel extends EventEmitter2 {
|
|
12
|
+
channelName;
|
|
13
|
+
server;
|
|
14
|
+
constructor(channelName) {
|
|
15
|
+
super({
|
|
16
|
+
maxListeners: 1024,
|
|
17
|
+
});
|
|
18
|
+
this.channelName = channelName;
|
|
19
|
+
this.onAny((event, value) => {
|
|
20
|
+
if (!this.server.events.has(event) &&
|
|
21
|
+
!SystemEvents.includes(event)) {
|
|
22
|
+
console.warn('Event Not Registered:', event);
|
|
23
|
+
}
|
|
24
|
+
if (this.server.events.has(event)) {
|
|
25
|
+
const eventObject = this.server.events.get(event);
|
|
26
|
+
eventObject.handler(this, value);
|
|
27
|
+
}
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
setServer(server) {
|
|
31
|
+
this.server = server;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Broadcasts a pre-encoded event payload to all subscribed clients.
|
|
35
|
+
* The payload already contains the wire protocol `t` field (set by
|
|
36
|
+
* Event.handler), so no re-encoding is needed.
|
|
37
|
+
* @param excludeUuid - Optional client uuid to exclude from receiving the event
|
|
38
|
+
*/
|
|
39
|
+
propagate(event, payload, excludeUuid) {
|
|
40
|
+
const eventObject = this.server.events.get(event);
|
|
41
|
+
if (!eventObject) {
|
|
42
|
+
console.log('Event Not Registered:', event);
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
const transport = this.server.webSocketTransport;
|
|
46
|
+
if (!transport) {
|
|
47
|
+
console.warn('[TypeFerry] WebSocket transport not available for propagate');
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
const roomName = getRoomName(this.channelName, event);
|
|
51
|
+
if (excludeUuid) {
|
|
52
|
+
const excludeClient = this.server.allClients.get(excludeUuid);
|
|
53
|
+
transport.rooms.broadcast(roomName, payload, excludeClient?.socket);
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
transport.rooms.broadcast(roomName, payload);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
defer(event, params) {
|
|
60
|
+
process.nextTick(() => {
|
|
61
|
+
this.emit(event, params);
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
/** Refreshes a method by its identifier. */
|
|
65
|
+
refresh(method) {
|
|
66
|
+
this.emit(TypeFerryEvents.METHOD_REFRESH, method);
|
|
67
|
+
}
|
|
68
|
+
/** Declares a new event. */
|
|
69
|
+
addEvent(name, opts) {
|
|
70
|
+
if (this.server.events.has(name)) {
|
|
71
|
+
this.server.events.delete(name);
|
|
72
|
+
}
|
|
73
|
+
const event = new Event(name, this.server, this, opts);
|
|
74
|
+
this.server.events.set(name, event);
|
|
75
|
+
}
|
|
76
|
+
get list() {
|
|
77
|
+
return Array.from(this.server.events.keys());
|
|
78
|
+
}
|
|
79
|
+
get length() {
|
|
80
|
+
return this.server.events.size;
|
|
81
|
+
}
|
|
82
|
+
get(event) {
|
|
83
|
+
return this.server.events.get(event);
|
|
84
|
+
}
|
|
85
|
+
has(event) {
|
|
86
|
+
return this.server.events.has(event);
|
|
87
|
+
}
|
|
88
|
+
delete(event) {
|
|
89
|
+
return this.server.events.delete(event);
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Checks if a client is subscribed to an event via the RoomRegistry.
|
|
93
|
+
*/
|
|
94
|
+
isSubscribed(client, event) {
|
|
95
|
+
if (!client.socket)
|
|
96
|
+
return false;
|
|
97
|
+
const rooms = this.server.webSocketTransport?.rooms;
|
|
98
|
+
if (!rooms)
|
|
99
|
+
return false;
|
|
100
|
+
const roomName = getRoomName(this.channelName, event.name);
|
|
101
|
+
return rooms.has(client.socket, roomName);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
//# sourceMappingURL=server-channel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-channel.js","sourceRoot":"","sources":["../../src/server/server-channel.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { RequestListener } from 'node:http';
|
|
2
|
+
import type { Hono } from 'hono';
|
|
3
|
+
import type { RedisClientOptions } from 'redis';
|
|
4
|
+
import type { z } from 'zod';
|
|
5
|
+
import type { MethodParams as MethodParameters, ServerMethods } from '../utils/index.js';
|
|
6
|
+
import { ClientNode } from './client-node.js';
|
|
7
|
+
import type { Event } from './event.js';
|
|
8
|
+
import type { MethodFunction, MethodOptions } from './method.js';
|
|
9
|
+
import { Method } from './method.js';
|
|
10
|
+
import { ServerChannel } from './server-channel.js';
|
|
11
|
+
import { NodeHonoTransport, RedisTransport, WebSocketTransport } from './transports/index.js';
|
|
12
|
+
declare global {
|
|
13
|
+
var TypeFerry: Server;
|
|
14
|
+
}
|
|
15
|
+
export type ChannelChecker = (node: ClientNode, channel: string) => Promise<boolean>;
|
|
16
|
+
export type AuthFunction = (this: ClientNode, context: any) => any;
|
|
17
|
+
/**
|
|
18
|
+
* Configuration for server authentication.
|
|
19
|
+
*/
|
|
20
|
+
export type AuthSetup = {
|
|
21
|
+
/** Authentication function called to validate tokens */
|
|
22
|
+
auth: AuthFunction;
|
|
23
|
+
/** Login method handler */
|
|
24
|
+
logIn: MethodFunction;
|
|
25
|
+
};
|
|
26
|
+
export type RateLimit = boolean | {
|
|
27
|
+
max: number;
|
|
28
|
+
interval: number;
|
|
29
|
+
};
|
|
30
|
+
/** Default request-body ceiling retained across the runtime migration. */
|
|
31
|
+
export declare const DEFAULT_MAX_REQUEST_BODY_SIZE_BYTES: number;
|
|
32
|
+
export type ServerOptions = {
|
|
33
|
+
host?: string;
|
|
34
|
+
port?: number;
|
|
35
|
+
auth?: AuthFunction;
|
|
36
|
+
origins?: string[];
|
|
37
|
+
debug?: boolean;
|
|
38
|
+
ws?: Record<string, unknown>;
|
|
39
|
+
redis?: RedisClientOptions | boolean;
|
|
40
|
+
/**
|
|
41
|
+
* Observes Node request metadata and synchronous `data` events without owning
|
|
42
|
+
* transport backpressure. Pausing or reading the observer does not pause Hono.
|
|
43
|
+
*/
|
|
44
|
+
requestListener?: RequestListener;
|
|
45
|
+
globalInstance?: boolean;
|
|
46
|
+
allowedContextKeys?: string[];
|
|
47
|
+
rateLimit?: RateLimit;
|
|
48
|
+
/** Maximum request body accepted by the HTTP listener. */
|
|
49
|
+
maxRequestBodySize?: number;
|
|
50
|
+
shouldAllowChannelSubscribe?: ChannelChecker;
|
|
51
|
+
};
|
|
52
|
+
export type ProxyMethodCreation = {
|
|
53
|
+
[key: string]: ProxyMethodCreation;
|
|
54
|
+
} & any;
|
|
55
|
+
export declare class Server<Methods extends ServerMethods = ServerMethods> extends ServerChannel {
|
|
56
|
+
uuid: string;
|
|
57
|
+
httpTransport: NodeHonoTransport;
|
|
58
|
+
webSocketTransport: WebSocketTransport;
|
|
59
|
+
redisTransport: RedisTransport;
|
|
60
|
+
host: string;
|
|
61
|
+
port: number;
|
|
62
|
+
requestListener: RequestListener;
|
|
63
|
+
allowedContextKeys: string[];
|
|
64
|
+
isAuthEnabled: boolean;
|
|
65
|
+
auth: AuthFunction;
|
|
66
|
+
debug: boolean;
|
|
67
|
+
rateLimit: RateLimit;
|
|
68
|
+
maxRequestBodySize: number;
|
|
69
|
+
methods: Map<string, Method<any, any>>;
|
|
70
|
+
allClients: Map<string, ClientNode>;
|
|
71
|
+
/** Reverse index: userId → connected client nodes for efficient user-level operations */
|
|
72
|
+
private clientsByUserId;
|
|
73
|
+
channels: Map<string, ServerChannel>;
|
|
74
|
+
events: Map<string, Event>;
|
|
75
|
+
m: ProxyMethodCreation;
|
|
76
|
+
acceptConnections: boolean;
|
|
77
|
+
ready: boolean;
|
|
78
|
+
shouldAllowChannelSubscribe: ChannelChecker;
|
|
79
|
+
static ERROR_EVENT: string;
|
|
80
|
+
handlers: Methods;
|
|
81
|
+
private closePromise?;
|
|
82
|
+
private initializeGlobalInstance;
|
|
83
|
+
private initializeTransports;
|
|
84
|
+
private setupHttpListening;
|
|
85
|
+
constructor({ host, port, debug, origins, ws, redis, requestListener, globalInstance, allowedContextKeys, rateLimit, maxRequestBodySize, }?: ServerOptions);
|
|
86
|
+
/**
|
|
87
|
+
* Resolves when startup transports have emitted their readiness signals.
|
|
88
|
+
*
|
|
89
|
+
* Already-ready servers must not retain `READY` listeners because callers
|
|
90
|
+
* commonly use this as a low-cost guard before request handling.
|
|
91
|
+
*/
|
|
92
|
+
isReady(): Promise<boolean>;
|
|
93
|
+
/**
|
|
94
|
+
* Returns the authoritative Hono application for route registration.
|
|
95
|
+
*/
|
|
96
|
+
get app(): Hono;
|
|
97
|
+
setAuth({ auth, logIn }: AuthSetup): void;
|
|
98
|
+
setChannelAuthorization(checker: ChannelChecker): void;
|
|
99
|
+
close(): Promise<boolean>;
|
|
100
|
+
private closeTransports;
|
|
101
|
+
static(path: string, catchAll: boolean): void;
|
|
102
|
+
debugger(...args: any[]): void;
|
|
103
|
+
call<T = Record<string, unknown>>(method: string, parameters?: MethodParameters<T>): Promise<unknown>;
|
|
104
|
+
createDefaultMethods(): void;
|
|
105
|
+
getMethod(method: string): Method<any, any>;
|
|
106
|
+
addClient(node: ClientNode): void;
|
|
107
|
+
deleteClient(node: ClientNode): void;
|
|
108
|
+
/** Registers a client node in the userId reverse index */
|
|
109
|
+
indexClientByUserId(node: ClientNode): void;
|
|
110
|
+
/** Removes a client node from the userId reverse index */
|
|
111
|
+
removeClientFromUserIndex(node: ClientNode): void;
|
|
112
|
+
/** Returns all connected client nodes for a given userId */
|
|
113
|
+
getClientsByUserId(userId: string): ReadonlySet<ClientNode>;
|
|
114
|
+
/**
|
|
115
|
+
* Disconnects all WebSocket clients for a userId.
|
|
116
|
+
* Used during session revocation to enforce immediate logout.
|
|
117
|
+
* @returns Number of clients disconnected
|
|
118
|
+
*/
|
|
119
|
+
disconnectUser(userId: string, exceptNodeUuid?: string): number;
|
|
120
|
+
addMethod<T = any, R = any, Schema extends z.ZodType = z.ZodType>(method: string, fn: MethodFunction<T, R>, opts?: MethodOptions<Schema>): void;
|
|
121
|
+
channel(name?: string | object): ServerChannel;
|
|
122
|
+
}
|
|
123
|
+
export type InferServerMethods<T extends Server<any>> = T['handlers'];
|
|
124
|
+
export declare function createServer(options?: ServerOptions): Server<ServerMethods>;
|