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
package/README.md
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# typeferry
|
|
2
|
+
|
|
3
|
+
The TypeScript implementation of TypeFerry provides the reference Node.js server, browser/Node client, React hooks, authentication helpers, EJSON, and an optional MongoDB extension.
|
|
4
|
+
|
|
5
|
+
Install the public TypeScript package with `npm install typeferry`. Repository contributors can use the local [`template/`](../template/) workflow described in the [quickstart](../docs/getting-started.md).
|
|
6
|
+
|
|
7
|
+
## Runtime requirements
|
|
8
|
+
|
|
9
|
+
- Node.js `24.19.0`
|
|
10
|
+
- npm `11.17.0`
|
|
11
|
+
- Node.js for the server runtime
|
|
12
|
+
- A browser or WebSocket-capable JavaScript runtime for clients
|
|
13
|
+
|
|
14
|
+
## Public entry points
|
|
15
|
+
|
|
16
|
+
| Import | Purpose |
|
|
17
|
+
|---|---|
|
|
18
|
+
| `typeferry/server` | Server, methods, events, channels, and runtime types |
|
|
19
|
+
| `typeferry/server/decorators` | Namespace and method decorators |
|
|
20
|
+
| `typeferry/server/transports` | Node HTTP, WebSocket, and Redis transports |
|
|
21
|
+
| `typeferry/client` | Core client and connection APIs |
|
|
22
|
+
| `typeferry/react` | React provider and hooks |
|
|
23
|
+
| `typeferry/auth` | Shared auth, token, session, and cookie helpers |
|
|
24
|
+
| `typeferry/auth/server/oauth` | Server OAuth providers |
|
|
25
|
+
| `typeferry/auth/client/oauth` | Client OAuth helpers |
|
|
26
|
+
| `typeferry/ejson` | Extended JSON namespace |
|
|
27
|
+
| `typeferry/mongodb` | Native-driver MongoDB extension |
|
|
28
|
+
| `typeferry/mongodb/decorators` | MongoDB collection decorators |
|
|
29
|
+
|
|
30
|
+
Applications should import these compiled package exports. Do not alias or import TypeFerry source files from application code.
|
|
31
|
+
|
|
32
|
+
## Define and serve a typed method
|
|
33
|
+
|
|
34
|
+
```ts
|
|
35
|
+
import { Server } from 'typeferry/server'
|
|
36
|
+
import type { ClientNode } from 'typeferry/server'
|
|
37
|
+
import {
|
|
38
|
+
type InferNamespace,
|
|
39
|
+
Method,
|
|
40
|
+
Namespace,
|
|
41
|
+
registerNamespace,
|
|
42
|
+
Schema,
|
|
43
|
+
} from 'typeferry/server/decorators'
|
|
44
|
+
import { z } from 'zod'
|
|
45
|
+
|
|
46
|
+
const greetingSchema = z.object({
|
|
47
|
+
name: z.string().trim().min(1),
|
|
48
|
+
})
|
|
49
|
+
|
|
50
|
+
type GreetingInput = z.infer<typeof greetingSchema>
|
|
51
|
+
|
|
52
|
+
@Namespace('greeting')
|
|
53
|
+
export class GreetingMethods {
|
|
54
|
+
@Method()
|
|
55
|
+
@Schema(greetingSchema)
|
|
56
|
+
async hello(
|
|
57
|
+
_client: ClientNode,
|
|
58
|
+
input: GreetingInput,
|
|
59
|
+
): Promise<string> {
|
|
60
|
+
return `Hello, ${input.name}!`
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export type GreetingApi = InferNamespace<GreetingMethods, 'greeting'>
|
|
65
|
+
|
|
66
|
+
const server = new Server({ host: '127.0.0.1', port: 8002 })
|
|
67
|
+
registerNamespace(GreetingMethods)
|
|
68
|
+
await server.isReady()
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
Clients can call the method as `client.m.greeting.hello({ name: 'Ada' })` when parameterized with `GreetingApi`. The decorators turn the class method into an HTTP and WebSocket RPC endpoint, while `@Schema()` validates network input at runtime. The `Server` constructor installs both transports; call `server.close()` during graceful shutdown.
|
|
72
|
+
|
|
73
|
+
## Development
|
|
74
|
+
|
|
75
|
+
Run commands from `typeferry-ts/`:
|
|
76
|
+
|
|
77
|
+
```sh
|
|
78
|
+
npm ci
|
|
79
|
+
npm run lint
|
|
80
|
+
npm run typecheck
|
|
81
|
+
npm test
|
|
82
|
+
npm run build
|
|
83
|
+
npm pack --dry-run
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Guides
|
|
87
|
+
|
|
88
|
+
Start at the [documentation home](../docs/README.md) or jump to [server and RPC](../docs/typescript/server-rpc.md), [client](../docs/typescript/client.md), [React](../docs/typescript/react.md), [authentication](../docs/typescript/authentication.md), [events and channels](../docs/typescript/events-and-channels.md), [MongoDB](../docs/typescript/mongodb.md), [EJSON](../docs/typescript/ejson.md), or [deployment](../docs/typescript/deployment.md).
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Client } from '../../client/index.js';
|
|
2
|
+
import type { CrossTabSyncConfig } from '../types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Set up cross-tab token synchronization using BroadcastChannel.
|
|
5
|
+
* When one tab refreshes the token, all other tabs receive the update.
|
|
6
|
+
*
|
|
7
|
+
* @param client - TypeFerry client instance
|
|
8
|
+
* @param config - Sync configuration
|
|
9
|
+
* @returns Cleanup function
|
|
10
|
+
*/
|
|
11
|
+
export declare function setupCrossTabSync(client: Client, config: CrossTabSyncConfig): () => void;
|
|
12
|
+
/**
|
|
13
|
+
* Broadcast a token refresh to all other tabs.
|
|
14
|
+
* Call this after successfully refreshing the token.
|
|
15
|
+
*
|
|
16
|
+
* @param channelName - BroadcastChannel name
|
|
17
|
+
* @param token - New access token
|
|
18
|
+
* @param exp - Token expiration (Unix timestamp in seconds)
|
|
19
|
+
* @param iat - Token issued-at time (Unix timestamp in seconds) for clock-skew compensation
|
|
20
|
+
*/
|
|
21
|
+
export declare function broadcastTokenRefresh(channelName: string, token: string, exp: number, iat?: number): void;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
const TOKEN_REFRESHED = 'TOKEN_REFRESHED';
|
|
2
|
+
/**
|
|
3
|
+
* Set up cross-tab token synchronization using BroadcastChannel.
|
|
4
|
+
* When one tab refreshes the token, all other tabs receive the update.
|
|
5
|
+
*
|
|
6
|
+
* @param client - TypeFerry client instance
|
|
7
|
+
* @param config - Sync configuration
|
|
8
|
+
* @returns Cleanup function
|
|
9
|
+
*/
|
|
10
|
+
export function setupCrossTabSync(client, config) {
|
|
11
|
+
// BroadcastChannel not available in SSR or older browsers
|
|
12
|
+
if (typeof BroadcastChannel === 'undefined') {
|
|
13
|
+
return () => { };
|
|
14
|
+
}
|
|
15
|
+
const channel = new BroadcastChannel(config.channelName);
|
|
16
|
+
const handleMessage = (event) => {
|
|
17
|
+
// Validate message structure before trusting data from other tabs
|
|
18
|
+
if (event.data?.type === TOKEN_REFRESHED &&
|
|
19
|
+
typeof event.data.token === 'string' &&
|
|
20
|
+
typeof event.data.exp === 'number') {
|
|
21
|
+
const { token, exp, iat } = event.data;
|
|
22
|
+
const context = { token, exp };
|
|
23
|
+
if (typeof iat === 'number') {
|
|
24
|
+
context.iat = iat;
|
|
25
|
+
context._tokenReceivedAt = Date.now();
|
|
26
|
+
}
|
|
27
|
+
client.updateContext(context);
|
|
28
|
+
if (config.tokenRefreshedEvent) {
|
|
29
|
+
client.emit(config.tokenRefreshedEvent, { token, exp });
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
channel.addEventListener('message', handleMessage);
|
|
34
|
+
return () => {
|
|
35
|
+
channel.removeEventListener('message', handleMessage);
|
|
36
|
+
channel.close();
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Broadcast a token refresh to all other tabs.
|
|
41
|
+
* Call this after successfully refreshing the token.
|
|
42
|
+
*
|
|
43
|
+
* @param channelName - BroadcastChannel name
|
|
44
|
+
* @param token - New access token
|
|
45
|
+
* @param exp - Token expiration (Unix timestamp in seconds)
|
|
46
|
+
* @param iat - Token issued-at time (Unix timestamp in seconds) for clock-skew compensation
|
|
47
|
+
*/
|
|
48
|
+
export function broadcastTokenRefresh(channelName, token, exp, iat) {
|
|
49
|
+
if (typeof BroadcastChannel === 'undefined') {
|
|
50
|
+
return;
|
|
51
|
+
}
|
|
52
|
+
const channel = new BroadcastChannel(channelName);
|
|
53
|
+
channel.postMessage({ type: TOKEN_REFRESHED, token, exp, iat });
|
|
54
|
+
channel.close();
|
|
55
|
+
}
|
|
56
|
+
//# sourceMappingURL=cross-tab-sync.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cross-tab-sync.js","sourceRoot":"","sources":["../../../src/auth/client/cross-tab-sync.ts"],"names":[],"mappings":"AAGA,MAAM,eAAe,GAAG,iBAAiB,CAAA;AAEzC;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,MAA0B;IAE1B,0DAA0D;IAC1D,IAAI,OAAO,gBAAgB,KAAK,WAAW,EAAE,CAAC;QAC5C,OAAO,GAAG,EAAE,GAAE,CAAC,CAAA;IACjB,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,MAAM,CAAC,WAAW,CAAC,CAAA;IAExD,MAAM,aAAa,GAAG,CAAC,KAAmB,EAAE,EAAE;QAC5C,kEAAkE;QAClE,IACE,KAAK,CAAC,IAAI,EAAE,IAAI,KAAK,eAAe;YACpC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,KAAK,QAAQ;YACpC,OAAO,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,QAAQ,EAClC,CAAC;YACD,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,CAAC,IAAI,CAAA;YAEtC,MAAM,OAAO,GAA4B,EAAE,KAAK,EAAE,GAAG,EAAE,CAAA;YACvD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE,CAAC;gBAC5B,OAAO,CAAC,GAAG,GAAG,GAAG,CAAA;gBACjB,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;YACvC,CAAC;YAED,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,CAAA;YAE7B,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;gBAC/B,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,mBAAmB,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,CAAC,CAAA;YACzD,CAAC;QACH,CAAC;IACH,CAAC,CAAA;IAED,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;IAElD,OAAO,GAAG,EAAE;QACV,OAAO,CAAC,mBAAmB,CAAC,SAAS,EAAE,aAAa,CAAC,CAAA;QACrD,OAAO,CAAC,KAAK,EAAE,CAAA;IACjB,CAAC,CAAA;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,qBAAqB,CACnC,WAAmB,EACnB,KAAa,EACb,GAAW,EACX,GAAY;IAEZ,IAAI,OAAO,gBAAgB,KAAK,WAAW,EAAE,CAAC;QAC5C,OAAM;IACR,CAAC;IAED,MAAM,OAAO,GAAG,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAA;IACjD,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAA;IAC/D,OAAO,CAAC,KAAK,EAAE,CAAA;AACjB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/client/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAC3E,OAAO,EAAE,kBAAkB,EAAE,yBAAyB,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ReactNode } from 'react';
|
|
2
|
+
export interface GoogleOAuthProviderProps {
|
|
3
|
+
clientId: string;
|
|
4
|
+
children: ReactNode;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Wraps the application tree with Google OAuth context.
|
|
8
|
+
* Thin re-export of `@react-oauth/google`'s provider for
|
|
9
|
+
* consistency with the typeferry auth module surface.
|
|
10
|
+
*/
|
|
11
|
+
export declare function GoogleOAuthProvider({ clientId, children, }: GoogleOAuthProviderProps): ReactNode;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { GoogleOAuthProvider as ReactGoogleOAuthProvider } from '@react-oauth/google';
|
|
3
|
+
/**
|
|
4
|
+
* Wraps the application tree with Google OAuth context.
|
|
5
|
+
* Thin re-export of `@react-oauth/google`'s provider for
|
|
6
|
+
* consistency with the typeferry auth module surface.
|
|
7
|
+
*/
|
|
8
|
+
export function GoogleOAuthProvider({ clientId, children, }) {
|
|
9
|
+
return (_jsx(ReactGoogleOAuthProvider, { clientId: clientId, children: children }));
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=google-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google-provider.js","sourceRoot":"","sources":["../../../../src/auth/client/oauth/google-provider.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,mBAAmB,IAAI,wBAAwB,EAAE,MAAM,qBAAqB,CAAA;AAQrF;;;;GAIG;AACH,MAAM,UAAU,mBAAmB,CAAC,EAClC,QAAQ,EACR,QAAQ,GACiB;IACzB,OAAO,CACL,KAAC,wBAAwB,IAAC,QAAQ,EAAE,QAAQ,YACzC,QAAQ,GACgB,CAC5B,CAAA;AACH,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/auth/client/oauth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAEvD,OAAO,EAAE,uBAAuB,EAAE,MAAM,oBAAoB,CAAA"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export interface UseGoogleLoginOptions {
|
|
2
|
+
/**
|
|
3
|
+
* Server method to call with the authorization code.
|
|
4
|
+
* @default 'auth.google'
|
|
5
|
+
*/
|
|
6
|
+
method?: string;
|
|
7
|
+
/**
|
|
8
|
+
* Async hook that runs after Google returns the auth code but
|
|
9
|
+
* before the server call. Return additional params to merge
|
|
10
|
+
* with `{ code }`, or return `false` to abort the flow.
|
|
11
|
+
*
|
|
12
|
+
* Useful for reCAPTCHA, analytics, or pre-flight checks.
|
|
13
|
+
*/
|
|
14
|
+
beforeServerCall?: (code: string) => Promise<Record<string, unknown> | false>;
|
|
15
|
+
/** Called after successful authentication and context update. */
|
|
16
|
+
onSuccess?: () => void;
|
|
17
|
+
/** Called when any step of the flow fails. */
|
|
18
|
+
onError?: (error: unknown) => void;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Hook that returns a trigger function for the Google OAuth popup flow.
|
|
22
|
+
*
|
|
23
|
+
* On user consent it exchanges the authorization code with the server,
|
|
24
|
+
* updates the typeferry client context, and reconnects the socket with
|
|
25
|
+
* the new credentials.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* ```tsx
|
|
29
|
+
* const login = useTypeFerryGoogleLogin({
|
|
30
|
+
* beforeServerCall: async () => {
|
|
31
|
+
* const token = await executeRecaptcha('google_signup')
|
|
32
|
+
* return token ? { recaptchaToken: token } : false
|
|
33
|
+
* },
|
|
34
|
+
* })
|
|
35
|
+
*
|
|
36
|
+
* <button onClick={() => login()}>Sign in with Google</button>
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function useTypeFerryGoogleLogin(options?: UseGoogleLoginOptions): () => void;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { useGoogleLogin } from '@react-oauth/google';
|
|
2
|
+
import { useCallback } from 'react';
|
|
3
|
+
import { useClient } from '../../../react/hooks/use-client.js';
|
|
4
|
+
/**
|
|
5
|
+
* Hook that returns a trigger function for the Google OAuth popup flow.
|
|
6
|
+
*
|
|
7
|
+
* On user consent it exchanges the authorization code with the server,
|
|
8
|
+
* updates the typeferry client context, and reconnects the socket with
|
|
9
|
+
* the new credentials.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```tsx
|
|
13
|
+
* const login = useTypeFerryGoogleLogin({
|
|
14
|
+
* beforeServerCall: async () => {
|
|
15
|
+
* const token = await executeRecaptcha('google_signup')
|
|
16
|
+
* return token ? { recaptchaToken: token } : false
|
|
17
|
+
* },
|
|
18
|
+
* })
|
|
19
|
+
*
|
|
20
|
+
* <button onClick={() => login()}>Sign in with Google</button>
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function useTypeFerryGoogleLogin(options = {}) {
|
|
24
|
+
const { method = 'auth.google', beforeServerCall, onSuccess, onError, } = options;
|
|
25
|
+
const client = useClient();
|
|
26
|
+
const login = useGoogleLogin({
|
|
27
|
+
onSuccess: async ({ code }) => {
|
|
28
|
+
try {
|
|
29
|
+
let extraParams = {};
|
|
30
|
+
if (beforeServerCall) {
|
|
31
|
+
const result = await beforeServerCall(code);
|
|
32
|
+
if (result === false)
|
|
33
|
+
return;
|
|
34
|
+
extraParams = result;
|
|
35
|
+
}
|
|
36
|
+
const { token, exp, iat } = await client.call(method, { code, ...extraParams }, { http: true });
|
|
37
|
+
await client.setContextAndReInit({
|
|
38
|
+
isGoogleAuth: true,
|
|
39
|
+
token,
|
|
40
|
+
exp,
|
|
41
|
+
iat,
|
|
42
|
+
_tokenReceivedAt: Date.now(),
|
|
43
|
+
});
|
|
44
|
+
onSuccess?.();
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
onError?.(error);
|
|
48
|
+
}
|
|
49
|
+
},
|
|
50
|
+
flow: 'auth-code',
|
|
51
|
+
select_account: true,
|
|
52
|
+
});
|
|
53
|
+
return useCallback(() => login(), [login]);
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=use-google-login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-google-login.js","sourceRoot":"","sources":["../../../../src/auth/client/oauth/use-google-login.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAA;AACpD,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAA;AAEnC,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AA2B3D;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,UAAU,uBAAuB,CACrC,UAAiC,EAAE;IAEnC,MAAM,EACJ,MAAM,GAAG,aAAa,EACtB,gBAAgB,EAChB,SAAS,EACT,OAAO,GACR,GAAG,OAAO,CAAA;IAEX,MAAM,MAAM,GAAG,SAAS,EAAE,CAAA;IAE1B,MAAM,KAAK,GAAG,cAAc,CAAC;QAC3B,SAAS,EAAE,KAAK,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE;YAC5B,IAAI,CAAC;gBACH,IAAI,WAAW,GAA4B,EAAE,CAAA;gBAE7C,IAAI,gBAAgB,EAAE,CAAC;oBACrB,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC,IAAI,CAAC,CAAA;oBAC3C,IAAI,MAAM,KAAK,KAAK;wBAAE,OAAM;oBAC5B,WAAW,GAAG,MAAM,CAAA;gBACtB,CAAC;gBAED,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,MAAM,MAAM,CAAC,IAAI,CAC3C,MAAM,EACN,EAAE,IAAI,EAAE,GAAG,WAAW,EAAE,EACxB,EAAE,IAAI,EAAE,IAAI,EAAE,CACf,CAAA;gBAED,MAAM,MAAM,CAAC,mBAAmB,CAAC;oBAC/B,YAAY,EAAE,IAAI;oBAClB,KAAK;oBACL,GAAG;oBACH,GAAG;oBACH,gBAAgB,EAAE,IAAI,CAAC,GAAG,EAAE;iBAC7B,CAAC,CAAA;gBAEF,SAAS,EAAE,EAAE,CAAA;YACf,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC,KAAK,CAAC,CAAA;YAClB,CAAC;QACH,CAAC;QACD,IAAI,EAAE,WAAW;QACjB,cAAc,EAAE,IAAI;KACrB,CAAC,CAAA;IAEF,OAAO,WAAW,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAA;AAC5C,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Client } from '../../client/index.js';
|
|
2
|
+
import type { TokenRefreshConfig } from '../types.js';
|
|
3
|
+
export type { TokenRefreshConfig };
|
|
4
|
+
/**
|
|
5
|
+
* Refresh the access token using the configured refresh method.
|
|
6
|
+
* Handles concurrent refresh requests by queueing them per-client.
|
|
7
|
+
*
|
|
8
|
+
* @param client - TypeFerry client instance
|
|
9
|
+
* @param config - Optional configuration overrides
|
|
10
|
+
* @returns New access token, or null if refresh failed
|
|
11
|
+
*/
|
|
12
|
+
export declare function refreshAccessToken(client: Client, config?: Partial<TokenRefreshConfig>): Promise<string | null>;
|
|
13
|
+
/**
|
|
14
|
+
* Set up automatic token refresh before expiry.
|
|
15
|
+
* Returns a cleanup function to stop the refresh timer.
|
|
16
|
+
*
|
|
17
|
+
* @param client - TypeFerry client instance
|
|
18
|
+
* @param config - Optional configuration overrides
|
|
19
|
+
* @returns Cleanup function
|
|
20
|
+
*/
|
|
21
|
+
export declare function setupTokenRefreshOnExpiry(client: Client, config?: Partial<TokenRefreshConfig>): () => void;
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { LogLevel } from '../../client/logger.js';
|
|
2
|
+
import { broadcastTokenRefresh, setupCrossTabSync } from './cross-tab-sync.js';
|
|
3
|
+
const defaultConfig = {
|
|
4
|
+
refreshMethod: 'auth.refresh',
|
|
5
|
+
refreshBeforeExpirySec: 60,
|
|
6
|
+
broadcastChannelName: 'typeferry-token-sync',
|
|
7
|
+
};
|
|
8
|
+
/** Delay before retrying a failed refresh on transient (network) errors. */
|
|
9
|
+
const RETRY_DELAY_MS = 5_000;
|
|
10
|
+
const refreshStateMap = new WeakMap();
|
|
11
|
+
function getRefreshState(client) {
|
|
12
|
+
let state = refreshStateMap.get(client);
|
|
13
|
+
if (!state) {
|
|
14
|
+
state = { isRefreshing: false, failedQueue: [] };
|
|
15
|
+
refreshStateMap.set(client, state);
|
|
16
|
+
}
|
|
17
|
+
return state;
|
|
18
|
+
}
|
|
19
|
+
function processQueue(state, error, token) {
|
|
20
|
+
state.failedQueue.forEach(({ resolve, reject }) => {
|
|
21
|
+
if (error) {
|
|
22
|
+
reject(error);
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
resolve(token);
|
|
26
|
+
}
|
|
27
|
+
});
|
|
28
|
+
state.failedQueue = [];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Check if error is a terminal auth failure vs a transient network error.
|
|
32
|
+
* Terminal failures clear the context and redirect to login. Transient
|
|
33
|
+
* failures schedule a retry.
|
|
34
|
+
*/
|
|
35
|
+
function isAuthFailureError(err) {
|
|
36
|
+
if (err.status === 401 || err.status === 403)
|
|
37
|
+
return true;
|
|
38
|
+
if (err.code === 'AUTHENTICATION_FAILED')
|
|
39
|
+
return true;
|
|
40
|
+
const msg = err.message;
|
|
41
|
+
if (msg === 'Token refresh failed')
|
|
42
|
+
return true;
|
|
43
|
+
if (msg.includes('missingRefreshToken'))
|
|
44
|
+
return true;
|
|
45
|
+
if (msg.includes('invalidOrExpiredRefreshToken'))
|
|
46
|
+
return true;
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Refresh the access token using the configured refresh method.
|
|
51
|
+
* Handles concurrent refresh requests by queueing them per-client.
|
|
52
|
+
*
|
|
53
|
+
* @param client - TypeFerry client instance
|
|
54
|
+
* @param config - Optional configuration overrides
|
|
55
|
+
* @returns New access token, or null if refresh failed
|
|
56
|
+
*/
|
|
57
|
+
export async function refreshAccessToken(client, config = {}) {
|
|
58
|
+
const opts = { ...defaultConfig, ...config };
|
|
59
|
+
const state = getRefreshState(client);
|
|
60
|
+
// Queue concurrent requests for the same client
|
|
61
|
+
if (state.isRefreshing) {
|
|
62
|
+
return new Promise((resolve, reject) => {
|
|
63
|
+
state.failedQueue.push({ resolve, reject });
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
state.isRefreshing = true;
|
|
67
|
+
try {
|
|
68
|
+
/**
|
|
69
|
+
* Refresh token is sent exclusively via the HttpOnly cookie
|
|
70
|
+
* (credentials: 'include' on fetch). No body param needed — the
|
|
71
|
+
* server reads from the cookie header directly.
|
|
72
|
+
*/
|
|
73
|
+
client.logger.auth(LogLevel.INFO, 'Attempting token refresh', {
|
|
74
|
+
method: opts.refreshMethod,
|
|
75
|
+
hasToken: !!client.context.token,
|
|
76
|
+
exp: client.context.exp,
|
|
77
|
+
});
|
|
78
|
+
const result = await client.call(opts.refreshMethod, {}, {
|
|
79
|
+
ignoreInit: true,
|
|
80
|
+
http: true,
|
|
81
|
+
});
|
|
82
|
+
if (!result) {
|
|
83
|
+
throw new Error('Token refresh failed');
|
|
84
|
+
}
|
|
85
|
+
client.logger.auth(LogLevel.INFO, 'Token refresh succeeded', {
|
|
86
|
+
newExp: result.exp,
|
|
87
|
+
});
|
|
88
|
+
client.updateContext({
|
|
89
|
+
token: result.accessToken,
|
|
90
|
+
exp: result.exp,
|
|
91
|
+
iat: result.iat,
|
|
92
|
+
_tokenReceivedAt: Date.now(),
|
|
93
|
+
});
|
|
94
|
+
if (opts.broadcastChannelName) {
|
|
95
|
+
broadcastTokenRefresh(opts.broadcastChannelName, result.accessToken, result.exp, result.iat);
|
|
96
|
+
}
|
|
97
|
+
processQueue(state, null, result.accessToken);
|
|
98
|
+
return result.accessToken;
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
const err = error;
|
|
102
|
+
const isAuthFailure = isAuthFailureError(err);
|
|
103
|
+
client.logger.auth(isAuthFailure ? LogLevel.WARN : LogLevel.ERROR, 'Token refresh failed', {
|
|
104
|
+
isAuthFailure,
|
|
105
|
+
status: err.status,
|
|
106
|
+
code: err.code,
|
|
107
|
+
hasToken: !!client.context.token,
|
|
108
|
+
}, err);
|
|
109
|
+
if (isAuthFailure)
|
|
110
|
+
client.clearContext();
|
|
111
|
+
processQueue(state, err, null);
|
|
112
|
+
throw error;
|
|
113
|
+
}
|
|
114
|
+
finally {
|
|
115
|
+
state.isRefreshing = false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Set up automatic token refresh before expiry.
|
|
120
|
+
* Returns a cleanup function to stop the refresh timer.
|
|
121
|
+
*
|
|
122
|
+
* @param client - TypeFerry client instance
|
|
123
|
+
* @param config - Optional configuration overrides
|
|
124
|
+
* @returns Cleanup function
|
|
125
|
+
*/
|
|
126
|
+
export function setupTokenRefreshOnExpiry(client, config = {}) {
|
|
127
|
+
const opts = { ...defaultConfig, ...config };
|
|
128
|
+
let refreshTimeout = null;
|
|
129
|
+
const cleanupCrossTab = opts.broadcastChannelName
|
|
130
|
+
? setupCrossTabSync(client, { channelName: opts.broadcastChannelName })
|
|
131
|
+
: () => { };
|
|
132
|
+
const scheduleRefresh = () => {
|
|
133
|
+
if (refreshTimeout) {
|
|
134
|
+
clearTimeout(refreshTimeout);
|
|
135
|
+
refreshTimeout = null;
|
|
136
|
+
}
|
|
137
|
+
const { exp, iat, _tokenReceivedAt } = client.context;
|
|
138
|
+
if (!exp)
|
|
139
|
+
return;
|
|
140
|
+
/**
|
|
141
|
+
* Clock-skew-safe scheduling: when server-issued `iat` and local
|
|
142
|
+
* `_tokenReceivedAt` are available, compute remaining lifetime using
|
|
143
|
+
* only server-side TTL and client-side elapsed time — both immune
|
|
144
|
+
* to absolute clock differences between client and server.
|
|
145
|
+
*
|
|
146
|
+
* Falls back to the classic `exp - now` calculation for tokens
|
|
147
|
+
* issued before the iat migration.
|
|
148
|
+
*/
|
|
149
|
+
let timeUntilRefresh;
|
|
150
|
+
if (iat && _tokenReceivedAt) {
|
|
151
|
+
const tokenTtlMs = (exp - iat) * 1000;
|
|
152
|
+
const elapsedMs = Date.now() - _tokenReceivedAt;
|
|
153
|
+
timeUntilRefresh =
|
|
154
|
+
tokenTtlMs - elapsedMs - opts.refreshBeforeExpirySec * 1000;
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
const now = Math.floor(Date.now() / 1000);
|
|
158
|
+
timeUntilRefresh = (exp - now - opts.refreshBeforeExpirySec) * 1000;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Attempt a refresh and retry once on transient (non-auth) failures.
|
|
162
|
+
*
|
|
163
|
+
* Auth failures (401/403) are terminal — the session is invalid and
|
|
164
|
+
* clearContext already ran inside refreshAccessToken. Network errors
|
|
165
|
+
* are transient, so we schedule a single retry after a short delay
|
|
166
|
+
* to avoid the token expiring silently.
|
|
167
|
+
*/
|
|
168
|
+
const attemptRefresh = (meta) => {
|
|
169
|
+
refreshAccessToken(client, opts).catch(error => {
|
|
170
|
+
const err = error;
|
|
171
|
+
client.logger.auth(LogLevel.ERROR, 'Scheduled token refresh failed', meta, err);
|
|
172
|
+
if (!isAuthFailureError(err)) {
|
|
173
|
+
refreshTimeout = setTimeout(scheduleRefresh, RETRY_DELAY_MS);
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
// If already expired or about to expire, refresh immediately
|
|
178
|
+
if (timeUntilRefresh <= 0) {
|
|
179
|
+
/**
|
|
180
|
+
* If a refresh is already in progress (e.g. this handler was called
|
|
181
|
+
* from the CONTEXT_CHANGED event emitted inside refreshAccessToken),
|
|
182
|
+
* defer rescheduling instead of queueing a redundant refresh call.
|
|
183
|
+
* The queued path would resolve but never reschedule, leaving the
|
|
184
|
+
* next automatic refresh unscheduled.
|
|
185
|
+
*/
|
|
186
|
+
const state = getRefreshState(client);
|
|
187
|
+
if (state.isRefreshing) {
|
|
188
|
+
refreshTimeout = setTimeout(scheduleRefresh, 1000);
|
|
189
|
+
return;
|
|
190
|
+
}
|
|
191
|
+
attemptRefresh({ immediate: true });
|
|
192
|
+
return;
|
|
193
|
+
}
|
|
194
|
+
refreshTimeout = setTimeout(() => {
|
|
195
|
+
attemptRefresh({ scheduledDelayMs: timeUntilRefresh });
|
|
196
|
+
}, timeUntilRefresh);
|
|
197
|
+
};
|
|
198
|
+
// Schedule initial refresh
|
|
199
|
+
scheduleRefresh();
|
|
200
|
+
// Reschedule when context changes (e.g., after refresh)
|
|
201
|
+
const handleContextChange = () => scheduleRefresh();
|
|
202
|
+
client.on('context:changed', handleContextChange);
|
|
203
|
+
// Cleanup function
|
|
204
|
+
return () => {
|
|
205
|
+
if (refreshTimeout) {
|
|
206
|
+
clearTimeout(refreshTimeout);
|
|
207
|
+
}
|
|
208
|
+
client.off('context:changed', handleContextChange);
|
|
209
|
+
cleanupCrossTab();
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=token-refresh.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-refresh.js","sourceRoot":"","sources":["../../../src/auth/client/token-refresh.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export type { AccessTokenPayload, AuthConfig, AuthContext, CookieOptions, CrossTabSyncConfig, DeviceInfo, Session, SessionManager, TokenPair, TokenRefreshConfig, } from './types.js';
|
|
2
|
+
export { clearRefreshTokenCookie, getRefreshTokenFromRequest, setRefreshTokenCookie, } from './server/cookie-utils.js';
|
|
3
|
+
export { parseDeviceInfo } from './server/device-info.js';
|
|
4
|
+
export { decodeToken, signAccessToken, verifyAccessToken, } from './server/jwt-utils.js';
|
|
5
|
+
export { InMemorySessionManager } from './server/session-manager.js';
|
|
6
|
+
export { broadcastTokenRefresh, setupCrossTabSync, } from './client/cross-tab-sync.js';
|
|
7
|
+
export { refreshAccessToken, setupTokenRefreshOnExpiry, } from './client/token-refresh.js';
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
// Server utilities
|
|
2
|
+
export { clearRefreshTokenCookie, getRefreshTokenFromRequest, setRefreshTokenCookie, } from './server/cookie-utils.js';
|
|
3
|
+
export { parseDeviceInfo } from './server/device-info.js';
|
|
4
|
+
export { decodeToken, signAccessToken, verifyAccessToken, } from './server/jwt-utils.js';
|
|
5
|
+
export { InMemorySessionManager } from './server/session-manager.js';
|
|
6
|
+
// Client utilities
|
|
7
|
+
export { broadcastTokenRefresh, setupCrossTabSync, } from './client/cross-tab-sync.js';
|
|
8
|
+
export { refreshAccessToken, setupTokenRefreshOnExpiry, } from './client/token-refresh.js';
|
|
9
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/auth/index.ts"],"names":[],"mappings":"AAcA,mBAAmB;AACnB,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,uBAAuB,CAAA;AAC9B,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AACtD,OAAO,EACL,WAAW,EACX,eAAe,EACf,iBAAiB,GAClB,MAAM,oBAAoB,CAAA;AAC3B,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAA;AAEjE,mBAAmB;AACnB,OAAO,EACL,qBAAqB,EACrB,iBAAiB,GAClB,MAAM,yBAAyB,CAAA;AAChC,OAAO,EACL,kBAAkB,EAClB,yBAAyB,GAC1B,MAAM,wBAAwB,CAAA"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import type { CookieOptions } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Response-like object that can set headers.
|
|
4
|
+
*/
|
|
5
|
+
interface ResponseLike {
|
|
6
|
+
setHeader: (name: string, value: string) => void;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Request-like object that may contain cookies.
|
|
10
|
+
*/
|
|
11
|
+
interface RequestLike {
|
|
12
|
+
cookies?: Record<string, string>;
|
|
13
|
+
headers?: {
|
|
14
|
+
cookie?: string;
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Set an HttpOnly refresh token cookie.
|
|
19
|
+
*
|
|
20
|
+
* @param res - Response object with setHeader method
|
|
21
|
+
* @param token - Refresh token value
|
|
22
|
+
* @param options - Cookie configuration
|
|
23
|
+
*/
|
|
24
|
+
export declare function setRefreshTokenCookie(res: ResponseLike, token: string, options: CookieOptions): void;
|
|
25
|
+
/**
|
|
26
|
+
* Clear a refresh token cookie by setting it to expire immediately.
|
|
27
|
+
*
|
|
28
|
+
* @param res - Response object with setHeader method
|
|
29
|
+
* @param options - Cookie configuration (name, secure, path)
|
|
30
|
+
*/
|
|
31
|
+
export declare function clearRefreshTokenCookie(res: ResponseLike, options: Pick<CookieOptions, 'name' | 'secure' | 'sameSite' | 'path'>): void;
|
|
32
|
+
/**
|
|
33
|
+
* Extract refresh token from a request.
|
|
34
|
+
* Checks parsed cookies first, then falls back to manual cookie header parsing.
|
|
35
|
+
* Automatically URL-decodes the cookie value.
|
|
36
|
+
*
|
|
37
|
+
* @param req - Request object with optional cookies or cookie header
|
|
38
|
+
* @param cookieName - Name of the cookie to extract
|
|
39
|
+
* @returns Cookie value if found, undefined otherwise
|
|
40
|
+
*/
|
|
41
|
+
export declare function getRefreshTokenFromRequest(req: RequestLike, cookieName: string): string | undefined;
|
|
42
|
+
export {};
|