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,91 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Set an HttpOnly refresh token cookie.
|
|
3
|
+
*
|
|
4
|
+
* @param res - Response object with setHeader method
|
|
5
|
+
* @param token - Refresh token value
|
|
6
|
+
* @param options - Cookie configuration
|
|
7
|
+
*/
|
|
8
|
+
export function setRefreshTokenCookie(res, token, options) {
|
|
9
|
+
const maxAge = options.maxAgeDays * 24 * 60 * 60;
|
|
10
|
+
const secure = options.secure ?? process.env.NODE_ENV === 'production';
|
|
11
|
+
/**
|
|
12
|
+
* Lax prevents CSRF on cross-site POST while still sending the cookie
|
|
13
|
+
* on same-site navigations and Vite HMR reloads. Strict caused the
|
|
14
|
+
* refresh cookie to be dropped during dev hot reloads.
|
|
15
|
+
*/
|
|
16
|
+
const sameSite = options.sameSite ?? 'Lax';
|
|
17
|
+
const path = options.path ?? '/';
|
|
18
|
+
// URL-encode token to handle special characters (;, =, etc.)
|
|
19
|
+
const encodedToken = encodeURIComponent(token);
|
|
20
|
+
const parts = [
|
|
21
|
+
`${options.name}=${encodedToken}`,
|
|
22
|
+
'HttpOnly',
|
|
23
|
+
`Path=${path}`,
|
|
24
|
+
`Max-Age=${maxAge}`,
|
|
25
|
+
`SameSite=${sameSite}`,
|
|
26
|
+
];
|
|
27
|
+
if (secure) {
|
|
28
|
+
parts.push('Secure');
|
|
29
|
+
}
|
|
30
|
+
res.setHeader('Set-Cookie', parts.join('; '));
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Clear a refresh token cookie by setting it to expire immediately.
|
|
34
|
+
*
|
|
35
|
+
* @param res - Response object with setHeader method
|
|
36
|
+
* @param options - Cookie configuration (name, secure, path)
|
|
37
|
+
*/
|
|
38
|
+
export function clearRefreshTokenCookie(res, options) {
|
|
39
|
+
const secure = options.secure ?? process.env.NODE_ENV === 'production';
|
|
40
|
+
const sameSite = options.sameSite ?? 'Lax';
|
|
41
|
+
const path = options.path ?? '/';
|
|
42
|
+
const parts = [
|
|
43
|
+
`${options.name}=`,
|
|
44
|
+
'HttpOnly',
|
|
45
|
+
`Path=${path}`,
|
|
46
|
+
'Max-Age=0',
|
|
47
|
+
`SameSite=${sameSite}`,
|
|
48
|
+
];
|
|
49
|
+
if (secure) {
|
|
50
|
+
parts.push('Secure');
|
|
51
|
+
}
|
|
52
|
+
res.setHeader('Set-Cookie', parts.join('; '));
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Extract refresh token from a request.
|
|
56
|
+
* Checks parsed cookies first, then falls back to manual cookie header parsing.
|
|
57
|
+
* Automatically URL-decodes the cookie value.
|
|
58
|
+
*
|
|
59
|
+
* @param req - Request object with optional cookies or cookie header
|
|
60
|
+
* @param cookieName - Name of the cookie to extract
|
|
61
|
+
* @returns Cookie value if found, undefined otherwise
|
|
62
|
+
*/
|
|
63
|
+
export function getRefreshTokenFromRequest(req, cookieName) {
|
|
64
|
+
// Check parsed cookies first (if cookie-parser middleware was used)
|
|
65
|
+
// cookie-parser auto-decodes, so no need to decode again
|
|
66
|
+
if (req.cookies?.[cookieName]) {
|
|
67
|
+
return req.cookies[cookieName];
|
|
68
|
+
}
|
|
69
|
+
// Fall back to manual parsing from cookie header
|
|
70
|
+
const cookieHeader = req.headers?.cookie;
|
|
71
|
+
if (!cookieHeader) {
|
|
72
|
+
return undefined;
|
|
73
|
+
}
|
|
74
|
+
// Escape regex special characters in cookie name to prevent injection
|
|
75
|
+
const escapedName = cookieName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
76
|
+
const match = cookieHeader.match(
|
|
77
|
+
// eslint-disable-next-line security/detect-non-literal-regexp -- pattern is escaped above
|
|
78
|
+
new RegExp(`(?:^|;\\s*)${escapedName}=([^;]*)`));
|
|
79
|
+
if (!match) {
|
|
80
|
+
return undefined;
|
|
81
|
+
}
|
|
82
|
+
// URL-decode the cookie value (matches our encoding in setRefreshTokenCookie)
|
|
83
|
+
try {
|
|
84
|
+
return decodeURIComponent(match[1]);
|
|
85
|
+
}
|
|
86
|
+
catch {
|
|
87
|
+
// If decode fails, return raw value (backwards compatibility)
|
|
88
|
+
return match[1];
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=cookie-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cookie-utils.js","sourceRoot":"","sources":["../../../src/auth/server/cookie-utils.ts"],"names":[],"mappings":"AAiBA;;;;;;GAMG;AACH,MAAM,UAAU,qBAAqB,CACnC,GAAiB,EACjB,KAAa,EACb,OAAsB;IAEtB,MAAM,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;IAChD,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAA;IACtE;;;;OAIG;IACH,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAA;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,CAAA;IAEhC,6DAA6D;IAC7D,MAAM,YAAY,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAA;IAE9C,MAAM,KAAK,GAAG;QACZ,GAAG,OAAO,CAAC,IAAI,IAAI,YAAY,EAAE;QACjC,UAAU;QACV,QAAQ,IAAI,EAAE;QACd,WAAW,MAAM,EAAE;QACnB,YAAY,QAAQ,EAAE;KACvB,CAAA;IAED,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACtB,CAAC;IAED,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;AAC/C,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CACrC,GAAiB,EACjB,OAAqE;IAErE,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,CAAA;IACtE,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,KAAK,CAAA;IAC1C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,IAAI,GAAG,CAAA;IAEhC,MAAM,KAAK,GAAG;QACZ,GAAG,OAAO,CAAC,IAAI,GAAG;QAClB,UAAU;QACV,QAAQ,IAAI,EAAE;QACd,WAAW;QACX,YAAY,QAAQ,EAAE;KACvB,CAAA;IAED,IAAI,MAAM,EAAE,CAAC;QACX,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAA;IACtB,CAAC;IAED,GAAG,CAAC,SAAS,CAAC,YAAY,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;AAC/C,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,0BAA0B,CACxC,GAAgB,EAChB,UAAkB;IAElB,oEAAoE;IACpE,yDAAyD;IACzD,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC,UAAU,CAAC,EAAE,CAAC;QAC9B,OAAO,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAA;IAChC,CAAC;IAED,iDAAiD;IACjD,MAAM,YAAY,GAAG,GAAG,CAAC,OAAO,EAAE,MAAM,CAAA;IACxC,IAAI,CAAC,YAAY,EAAE,CAAC;QAClB,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,sEAAsE;IACtE,MAAM,WAAW,GAAG,UAAU,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,CAAA;IACrE,MAAM,KAAK,GAAG,YAAY,CAAC,KAAK;IAC9B,0FAA0F;IAC1F,IAAI,MAAM,CAAC,cAAc,WAAW,UAAU,CAAC,CAChD,CAAA;IAED,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,OAAO,SAAS,CAAA;IAClB,CAAC;IAED,8EAA8E;IAC9E,IAAI,CAAC;QACH,OAAO,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAA;IACrC,CAAC;IAAC,MAAM,CAAC;QACP,8DAA8D;QAC9D,OAAO,KAAK,CAAC,CAAC,CAAC,CAAA;IACjB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DeviceInfo } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Request-like object for extracting device information.
|
|
4
|
+
*/
|
|
5
|
+
interface RequestLike {
|
|
6
|
+
headers?: {
|
|
7
|
+
'user-agent'?: string;
|
|
8
|
+
'x-forwarded-for'?: string;
|
|
9
|
+
};
|
|
10
|
+
socket?: {
|
|
11
|
+
remoteAddress?: string;
|
|
12
|
+
};
|
|
13
|
+
ip?: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Parse device information from an HTTP request.
|
|
17
|
+
* Extracts IP address, user agent, browser, OS, and device type.
|
|
18
|
+
*
|
|
19
|
+
* @param req - Request object with headers and socket info
|
|
20
|
+
* @returns Parsed device information
|
|
21
|
+
*/
|
|
22
|
+
export declare function parseDeviceInfo(req: RequestLike): DeviceInfo;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { UAParser } from 'ua-parser-js';
|
|
2
|
+
/**
|
|
3
|
+
* Parse device information from an HTTP request.
|
|
4
|
+
* Extracts IP address, user agent, browser, OS, and device type.
|
|
5
|
+
*
|
|
6
|
+
* @param req - Request object with headers and socket info
|
|
7
|
+
* @returns Parsed device information
|
|
8
|
+
*/
|
|
9
|
+
export function parseDeviceInfo(req) {
|
|
10
|
+
if (!req) {
|
|
11
|
+
return {};
|
|
12
|
+
}
|
|
13
|
+
const uaString = req.headers?.['user-agent'];
|
|
14
|
+
const ip = getIpFromRequest(req);
|
|
15
|
+
if (!uaString) {
|
|
16
|
+
return { ip };
|
|
17
|
+
}
|
|
18
|
+
const parser = new UAParser(uaString);
|
|
19
|
+
const result = parser.getResult();
|
|
20
|
+
return {
|
|
21
|
+
ip,
|
|
22
|
+
userAgent: uaString,
|
|
23
|
+
browser: result.browser.name
|
|
24
|
+
? `${result.browser.name} ${result.browser.version || ''}`.trim()
|
|
25
|
+
: undefined,
|
|
26
|
+
os: result.os.name
|
|
27
|
+
? `${result.os.name} ${result.os.version || ''}`.trim()
|
|
28
|
+
: undefined,
|
|
29
|
+
deviceType: mapDeviceType(result.device.type),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Extract client IP address from request.
|
|
34
|
+
* Checks x-forwarded-for header first (for proxied requests),
|
|
35
|
+
* then falls back to the socket address or adapter-provided IP.
|
|
36
|
+
*/
|
|
37
|
+
function getIpFromRequest(req) {
|
|
38
|
+
return req.headers?.['x-forwarded-for'] || req.socket?.remoteAddress || req.ip;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Map UA parser device type to our DeviceInfo type.
|
|
42
|
+
*/
|
|
43
|
+
function mapDeviceType(type) {
|
|
44
|
+
if (!type)
|
|
45
|
+
return 'desktop';
|
|
46
|
+
if (type === 'mobile')
|
|
47
|
+
return 'mobile';
|
|
48
|
+
if (type === 'tablet')
|
|
49
|
+
return 'tablet';
|
|
50
|
+
return 'unknown';
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=device-info.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"device-info.js","sourceRoot":"","sources":["../../../src/auth/server/device-info.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAA;AAgBvC;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,GAAgB;IAC9C,IAAI,CAAC,GAAG,EAAE,CAAC;QACT,OAAO,EAAE,CAAA;IACX,CAAC;IAED,MAAM,QAAQ,GAAG,GAAG,CAAC,OAAO,EAAE,CAAC,YAAY,CAAC,CAAA;IAC5C,MAAM,EAAE,GAAG,gBAAgB,CAAC,GAAG,CAAC,CAAA;IAEhC,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,EAAE,EAAE,EAAE,CAAA;IACf,CAAC;IAED,MAAM,MAAM,GAAG,IAAI,QAAQ,CAAC,QAAQ,CAAC,CAAA;IACrC,MAAM,MAAM,GAAG,MAAM,CAAC,SAAS,EAAE,CAAA;IAEjC,OAAO;QACL,EAAE;QACF,SAAS,EAAE,QAAQ;QACnB,OAAO,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI;YAC1B,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,IAAI,MAAM,CAAC,OAAO,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;YACjE,CAAC,CAAC,SAAS;QACb,EAAE,EAAE,MAAM,CAAC,EAAE,CAAC,IAAI;YAChB,CAAC,CAAC,GAAG,MAAM,CAAC,EAAE,CAAC,IAAI,IAAI,MAAM,CAAC,EAAE,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE;YACvD,CAAC,CAAC,SAAS;QACb,UAAU,EAAE,aAAa,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC;KAC9C,CAAA;AACH,CAAC;AAED;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,GAAgB;IACxC,OAAO,GAAG,CAAC,OAAO,EAAE,CAAC,iBAAiB,CAAC,IAAI,GAAG,CAAC,MAAM,EAAE,aAAa,IAAI,GAAG,CAAC,EAAE,CAAA;AAChF,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,IAAa;IAClC,IAAI,CAAC,IAAI;QAAE,OAAO,SAAS,CAAA;IAC3B,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAA;IACtC,IAAI,IAAI,KAAK,QAAQ;QAAE,OAAO,QAAQ,CAAA;IACtC,OAAO,SAAS,CAAA;AAClB,CAAC"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export { clearRefreshTokenCookie, getRefreshTokenFromRequest, setRefreshTokenCookie, } from './cookie-utils.js';
|
|
2
|
+
export { parseDeviceInfo } from './device-info.js';
|
|
3
|
+
export { decodeToken, signAccessToken, verifyAccessToken } from './jwt-utils.js';
|
|
4
|
+
export { InMemorySessionManager } from './session-manager.js';
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { clearRefreshTokenCookie, getRefreshTokenFromRequest, setRefreshTokenCookie, } from './cookie-utils.js';
|
|
2
|
+
export { parseDeviceInfo } from './device-info.js';
|
|
3
|
+
export { decodeToken, signAccessToken, verifyAccessToken } from './jwt-utils.js';
|
|
4
|
+
export { InMemorySessionManager } from './session-manager.js';
|
|
5
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/auth/server/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,uBAAuB,EACvB,0BAA0B,EAC1B,qBAAqB,GACtB,MAAM,gBAAgB,CAAA;AACvB,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAA;AAC/C,OAAO,EAAE,WAAW,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAA;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,mBAAmB,CAAA"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { AccessTokenPayload, AuthConfig } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Sign an access token with the configured algorithm.
|
|
4
|
+
* Always uses explicit algorithm specification to prevent algorithm confusion attacks.
|
|
5
|
+
*
|
|
6
|
+
* @param payload - Token payload to sign
|
|
7
|
+
* @param config - Auth configuration with secret and algorithm
|
|
8
|
+
* @returns Signed JWT string
|
|
9
|
+
*/
|
|
10
|
+
export declare function signAccessToken(payload: AccessTokenPayload, config: AuthConfig): string;
|
|
11
|
+
/**
|
|
12
|
+
* Verify and decode an access token.
|
|
13
|
+
* Uses explicit algorithm whitelist to prevent algorithm confusion attacks.
|
|
14
|
+
*
|
|
15
|
+
* @param token - JWT to verify (may include 'Bearer ' prefix)
|
|
16
|
+
* @param config - Auth configuration with secret and algorithm
|
|
17
|
+
* @returns Decoded payload if valid, null otherwise
|
|
18
|
+
*/
|
|
19
|
+
export declare function verifyAccessToken(token: string, config: AuthConfig): AccessTokenPayload | null;
|
|
20
|
+
/**
|
|
21
|
+
* Decode a token without verification.
|
|
22
|
+
* Useful for reading claims from expired tokens or tokens signed by other parties.
|
|
23
|
+
*
|
|
24
|
+
* WARNING: Do not trust the contents without verification.
|
|
25
|
+
*
|
|
26
|
+
* @param token - JWT to decode
|
|
27
|
+
* @returns Decoded payload if parseable, null otherwise
|
|
28
|
+
*/
|
|
29
|
+
export declare function decodeToken(token: string): AccessTokenPayload | null;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import jwt from 'jsonwebtoken';
|
|
2
|
+
/**
|
|
3
|
+
* Sign an access token with the configured algorithm.
|
|
4
|
+
* Always uses explicit algorithm specification to prevent algorithm confusion attacks.
|
|
5
|
+
*
|
|
6
|
+
* @param payload - Token payload to sign
|
|
7
|
+
* @param config - Auth configuration with secret and algorithm
|
|
8
|
+
* @returns Signed JWT string
|
|
9
|
+
*/
|
|
10
|
+
export function signAccessToken(payload, config) {
|
|
11
|
+
const algorithm = config.algorithm ?? 'HS256';
|
|
12
|
+
return jwt.sign(payload, config.secret, { algorithm });
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Verify and decode an access token.
|
|
16
|
+
* Uses explicit algorithm whitelist to prevent algorithm confusion attacks.
|
|
17
|
+
*
|
|
18
|
+
* @param token - JWT to verify (may include 'Bearer ' prefix)
|
|
19
|
+
* @param config - Auth configuration with secret and algorithm
|
|
20
|
+
* @returns Decoded payload if valid, null otherwise
|
|
21
|
+
*/
|
|
22
|
+
export function verifyAccessToken(token, config) {
|
|
23
|
+
try {
|
|
24
|
+
const algorithm = config.algorithm ?? 'HS256';
|
|
25
|
+
const cleanToken = token.replace(/^Bearer\s+/i, '');
|
|
26
|
+
return jwt.verify(cleanToken, config.secret, {
|
|
27
|
+
algorithms: [algorithm],
|
|
28
|
+
maxAge: `${config.accessTokenExpiryMinutes ?? 15}m`,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return null;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Decode a token without verification.
|
|
37
|
+
* Useful for reading claims from expired tokens or tokens signed by other parties.
|
|
38
|
+
*
|
|
39
|
+
* WARNING: Do not trust the contents without verification.
|
|
40
|
+
*
|
|
41
|
+
* @param token - JWT to decode
|
|
42
|
+
* @returns Decoded payload if parseable, null otherwise
|
|
43
|
+
*/
|
|
44
|
+
export function decodeToken(token) {
|
|
45
|
+
try {
|
|
46
|
+
const cleanToken = token.replace(/^Bearer\s+/i, '');
|
|
47
|
+
return jwt.decode(cleanToken);
|
|
48
|
+
}
|
|
49
|
+
catch {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=jwt-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt-utils.js","sourceRoot":"","sources":["../../../src/auth/server/jwt-utils.ts"],"names":[],"mappings":"AAAA,OAAO,GAAG,MAAM,cAAc,CAAA;AAI9B;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAC7B,OAA2B,EAC3B,MAAkB;IAElB,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,OAAO,CAAA;IAC7C,OAAO,GAAG,CAAC,IAAI,CAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,EAAE,SAAS,EAAE,CAAC,CAAA;AACxD,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,iBAAiB,CAC/B,KAAa,EACb,MAAkB;IAElB,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,MAAM,CAAC,SAAS,IAAI,OAAO,CAAA;QAC7C,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAA;QAEnD,OAAO,GAAG,CAAC,MAAM,CAAC,UAAU,EAAE,MAAM,CAAC,MAAM,EAAE;YAC3C,UAAU,EAAE,CAAC,SAAS,CAAC;YACvB,MAAM,EAAE,GAAG,MAAM,CAAC,wBAAwB,IAAI,EAAE,GAAG;SACpD,CAAuB,CAAA;IAC1B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,UAAU,WAAW,CAAC,KAAa;IACvC,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAA;QACnD,OAAO,GAAG,CAAC,MAAM,CAAC,UAAU,CAAuB,CAAA;IACrD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAA;IACb,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { OAuthProvider, OAuthUserProfile } from './types.js';
|
|
2
|
+
export interface GoogleOAuthConfig {
|
|
3
|
+
clientId: string;
|
|
4
|
+
clientSecret: string;
|
|
5
|
+
/**
|
|
6
|
+
* Redirect URI for the OAuth flow.
|
|
7
|
+
* Defaults to `'postmessage'` for popup-based flows.
|
|
8
|
+
*/
|
|
9
|
+
redirectUri?: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Google OAuth provider that exchanges authorization codes for
|
|
13
|
+
* verified user profiles via the Google Identity Platform.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* ```ts
|
|
17
|
+
* const google = new GoogleOAuthProvider({
|
|
18
|
+
* clientId: process.env.GOOGLE_CLIENT_ID,
|
|
19
|
+
* clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
20
|
+
* })
|
|
21
|
+
*
|
|
22
|
+
* const profile = await google.exchangeCode(code)
|
|
23
|
+
* // → { providerId, provider: 'google', email, name, picture, ... }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export declare class GoogleOAuthProvider implements OAuthProvider {
|
|
27
|
+
readonly name: "google";
|
|
28
|
+
private readonly client;
|
|
29
|
+
constructor(config: GoogleOAuthConfig);
|
|
30
|
+
exchangeCode(code: string): Promise<OAuthUserProfile>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { OAuth2Client } from 'google-auth-library';
|
|
2
|
+
/**
|
|
3
|
+
* Google OAuth provider that exchanges authorization codes for
|
|
4
|
+
* verified user profiles via the Google Identity Platform.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* ```ts
|
|
8
|
+
* const google = new GoogleOAuthProvider({
|
|
9
|
+
* clientId: process.env.GOOGLE_CLIENT_ID,
|
|
10
|
+
* clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
11
|
+
* })
|
|
12
|
+
*
|
|
13
|
+
* const profile = await google.exchangeCode(code)
|
|
14
|
+
* // → { providerId, provider: 'google', email, name, picture, ... }
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export class GoogleOAuthProvider {
|
|
18
|
+
name = 'google';
|
|
19
|
+
client;
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.client = new OAuth2Client(config.clientId, config.clientSecret, config.redirectUri ?? 'postmessage');
|
|
22
|
+
}
|
|
23
|
+
async exchangeCode(code) {
|
|
24
|
+
const { tokens } = await this.client.getToken(code);
|
|
25
|
+
const ticket = await this.client.verifyIdToken({
|
|
26
|
+
idToken: tokens.id_token,
|
|
27
|
+
});
|
|
28
|
+
const payload = ticket.getPayload();
|
|
29
|
+
return {
|
|
30
|
+
providerId: payload.sub,
|
|
31
|
+
provider: this.name,
|
|
32
|
+
email: payload.email,
|
|
33
|
+
emailVerified: payload.email_verified,
|
|
34
|
+
name: payload.name,
|
|
35
|
+
picture: payload.picture,
|
|
36
|
+
raw: payload,
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
//# sourceMappingURL=google.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"google.js","sourceRoot":"","sources":["../../../../src/auth/server/oauth/google.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAclD;;;;;;;;;;;;;;GAcG;AACH,MAAM,OAAO,mBAAmB;IACrB,IAAI,GAAG,QAAiB,CAAA;IAChB,MAAM,CAAc;IAErC,YAAY,MAAyB;QACnC,IAAI,CAAC,MAAM,GAAG,IAAI,YAAY,CAC5B,MAAM,CAAC,QAAQ,EACf,MAAM,CAAC,YAAY,EACnB,MAAM,CAAC,WAAW,IAAI,aAAa,CACpC,CAAA;IACH,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,IAAY;QAC7B,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAA;QAEnD,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC;YAC7C,OAAO,EAAE,MAAM,CAAC,QAAS;SAC1B,CAAC,CAAA;QAEF,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,EAAG,CAAA;QAEpC,OAAO;YACL,UAAU,EAAE,OAAO,CAAC,GAAG;YACvB,QAAQ,EAAE,IAAI,CAAC,IAAI;YACnB,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,aAAa,EAAE,OAAO,CAAC,cAAc;YACrC,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,OAAO,EAAE,OAAO,CAAC,OAAO;YACxB,GAAG,EAAE,OAA6C;SACnD,CAAA;IACH,CAAC;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/auth/server/oauth/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,UAAU,CAAA"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Normalized user profile returned by any OAuth provider.
|
|
3
|
+
*
|
|
4
|
+
* Each provider populates the subset of fields it supports.
|
|
5
|
+
* The `raw` field carries the full provider-specific payload
|
|
6
|
+
* for app-level access when the normalized fields aren't enough.
|
|
7
|
+
*/
|
|
8
|
+
export interface OAuthUserProfile {
|
|
9
|
+
/** Provider-specific unique user identifier (e.g. Google `sub`). */
|
|
10
|
+
providerId: string;
|
|
11
|
+
/** Provider name for discrimination (e.g. `'google'`, `'github'`). */
|
|
12
|
+
provider: string;
|
|
13
|
+
email?: string;
|
|
14
|
+
emailVerified?: boolean;
|
|
15
|
+
name?: string;
|
|
16
|
+
picture?: string;
|
|
17
|
+
/** Raw identity payload from the provider. */
|
|
18
|
+
raw?: Record<string, unknown>;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Server-side OAuth provider contract.
|
|
22
|
+
*
|
|
23
|
+
* Implementations handle the provider-specific authorization-code
|
|
24
|
+
* exchange and ID-token verification, returning a normalized profile.
|
|
25
|
+
*/
|
|
26
|
+
export interface OAuthProvider {
|
|
27
|
+
/** Provider identifier (e.g. `'google'`). */
|
|
28
|
+
readonly name: string;
|
|
29
|
+
/**
|
|
30
|
+
* Exchange an authorization code for a verified user profile.
|
|
31
|
+
*
|
|
32
|
+
* @param code - Authorization code from the OAuth redirect/popup
|
|
33
|
+
* @returns Normalized user profile
|
|
34
|
+
* @throws On invalid code, network errors, or verification failure
|
|
35
|
+
*/
|
|
36
|
+
exchangeCode(code: string): Promise<OAuthUserProfile>;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/auth/server/oauth/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { AuthConfig, DeviceInfo, Session, SessionManager, TokenPair } from '../types.js';
|
|
2
|
+
/**
|
|
3
|
+
* In-memory session manager implementation.
|
|
4
|
+
* Useful for testing, development, or single-instance deployments.
|
|
5
|
+
*
|
|
6
|
+
* For production multi-instance deployments, implement SessionManager
|
|
7
|
+
* with a shared storage backend (MongoDB, Redis, etc.)
|
|
8
|
+
*/
|
|
9
|
+
export declare class InMemorySessionManager implements SessionManager {
|
|
10
|
+
private sessions;
|
|
11
|
+
private config;
|
|
12
|
+
private cleanupInterval;
|
|
13
|
+
constructor(config: AuthConfig);
|
|
14
|
+
createSession(userId: string, deviceInfo?: DeviceInfo): Promise<TokenPair>;
|
|
15
|
+
refreshSession(refreshToken: string, deviceInfo?: DeviceInfo): Promise<TokenPair | null>;
|
|
16
|
+
revokeSession(sessionId: string): Promise<boolean>;
|
|
17
|
+
revokeFamily(familyId: string): Promise<number>;
|
|
18
|
+
getUserSessions(userId: string): Promise<Session[]>;
|
|
19
|
+
revokeAllUserSessions(userId: string, exceptFamilyId?: string): Promise<number>;
|
|
20
|
+
/**
|
|
21
|
+
* Handle a token that has already been rotated.
|
|
22
|
+
* Implements grace period for concurrent requests,
|
|
23
|
+
* but revokes entire family if reuse is detected outside grace period.
|
|
24
|
+
*/
|
|
25
|
+
private handleReusedToken;
|
|
26
|
+
/**
|
|
27
|
+
* Rotate a session by creating a new token and marking the old one as replaced.
|
|
28
|
+
*/
|
|
29
|
+
private rotateSession;
|
|
30
|
+
/**
|
|
31
|
+
* Build a token pair with a signed access token.
|
|
32
|
+
*/
|
|
33
|
+
private buildTokenPair;
|
|
34
|
+
/**
|
|
35
|
+
* Clean up expired and revoked sessions.
|
|
36
|
+
*/
|
|
37
|
+
private cleanup;
|
|
38
|
+
/**
|
|
39
|
+
* Stop the cleanup interval and clear sessions.
|
|
40
|
+
*/
|
|
41
|
+
destroy(): void;
|
|
42
|
+
/**
|
|
43
|
+
* Get the current session count (for monitoring).
|
|
44
|
+
*/
|
|
45
|
+
get size(): number;
|
|
46
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import { v4 as uuid } from '@lukeed/uuid';
|
|
2
|
+
import { signAccessToken } from './jwt-utils.js';
|
|
3
|
+
/**
|
|
4
|
+
* In-memory session manager implementation.
|
|
5
|
+
* Useful for testing, development, or single-instance deployments.
|
|
6
|
+
*
|
|
7
|
+
* For production multi-instance deployments, implement SessionManager
|
|
8
|
+
* with a shared storage backend (MongoDB, Redis, etc.)
|
|
9
|
+
*/
|
|
10
|
+
export class InMemorySessionManager {
|
|
11
|
+
sessions = new Map();
|
|
12
|
+
config;
|
|
13
|
+
cleanupInterval;
|
|
14
|
+
constructor(config) {
|
|
15
|
+
this.config = config;
|
|
16
|
+
// Clean up expired and revoked sessions every minute
|
|
17
|
+
this.cleanupInterval = setInterval(() => this.cleanup(), 60_000);
|
|
18
|
+
}
|
|
19
|
+
async createSession(userId, deviceInfo) {
|
|
20
|
+
const familyId = uuid();
|
|
21
|
+
const token = uuid();
|
|
22
|
+
const sessionId = uuid();
|
|
23
|
+
const expiryDays = this.config.refreshTokenExpiryDays ?? 14;
|
|
24
|
+
const expiration = Math.floor(Date.now() / 1000) + expiryDays * 24 * 60 * 60;
|
|
25
|
+
const session = {
|
|
26
|
+
id: sessionId,
|
|
27
|
+
userId,
|
|
28
|
+
familyId,
|
|
29
|
+
token,
|
|
30
|
+
expiration,
|
|
31
|
+
deviceInfo,
|
|
32
|
+
};
|
|
33
|
+
this.sessions.set(token, session);
|
|
34
|
+
return this.buildTokenPair(token, userId, sessionId);
|
|
35
|
+
}
|
|
36
|
+
async refreshSession(refreshToken, deviceInfo) {
|
|
37
|
+
const session = this.sessions.get(refreshToken);
|
|
38
|
+
if (!session || session.isRevoked) {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
if (Date.now() / 1000 > session.expiration) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
// Token has already been used - check for theft
|
|
45
|
+
if (session.replacedBy) {
|
|
46
|
+
return this.handleReusedToken(session);
|
|
47
|
+
}
|
|
48
|
+
return this.rotateSession(session, deviceInfo);
|
|
49
|
+
}
|
|
50
|
+
async revokeSession(sessionId) {
|
|
51
|
+
for (const session of this.sessions.values()) {
|
|
52
|
+
if (session.id === sessionId) {
|
|
53
|
+
session.isRevoked = true;
|
|
54
|
+
return true;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
async revokeFamily(familyId) {
|
|
60
|
+
let count = 0;
|
|
61
|
+
for (const session of this.sessions.values()) {
|
|
62
|
+
if (session.familyId === familyId && !session.isRevoked) {
|
|
63
|
+
session.isRevoked = true;
|
|
64
|
+
count++;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
return count;
|
|
68
|
+
}
|
|
69
|
+
async getUserSessions(userId) {
|
|
70
|
+
const now = Date.now() / 1000;
|
|
71
|
+
return Array.from(this.sessions.values()).filter(s => s.userId === userId &&
|
|
72
|
+
!s.isRevoked &&
|
|
73
|
+
!s.replacedBy &&
|
|
74
|
+
s.expiration > now);
|
|
75
|
+
}
|
|
76
|
+
async revokeAllUserSessions(userId, exceptFamilyId) {
|
|
77
|
+
let count = 0;
|
|
78
|
+
for (const session of this.sessions.values()) {
|
|
79
|
+
if (session.userId === userId &&
|
|
80
|
+
!session.isRevoked &&
|
|
81
|
+
(!exceptFamilyId || session.familyId !== exceptFamilyId)) {
|
|
82
|
+
session.isRevoked = true;
|
|
83
|
+
count++;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return count;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Handle a token that has already been rotated.
|
|
90
|
+
* Implements grace period for concurrent requests,
|
|
91
|
+
* but revokes entire family if reuse is detected outside grace period.
|
|
92
|
+
*/
|
|
93
|
+
handleReusedToken(session) {
|
|
94
|
+
const graceSeconds = this.config.rotationGracePeriodSeconds ?? 15;
|
|
95
|
+
const now = Date.now();
|
|
96
|
+
// Check if reuse is within grace period from when token was rotated
|
|
97
|
+
if (!session.usedAt || now - session.usedAt > graceSeconds * 1000) {
|
|
98
|
+
// Token reuse outside grace period indicates theft - revoke entire family
|
|
99
|
+
this.revokeFamily(session.familyId);
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
// Within grace period - return the new token pair
|
|
103
|
+
const nextSession = this.sessions.get(session.replacedBy);
|
|
104
|
+
if (!nextSession || nextSession.isRevoked) {
|
|
105
|
+
return null;
|
|
106
|
+
}
|
|
107
|
+
return this.buildTokenPair(nextSession.token, nextSession.userId, nextSession.id);
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Rotate a session by creating a new token and marking the old one as replaced.
|
|
111
|
+
*/
|
|
112
|
+
async rotateSession(session, deviceInfo) {
|
|
113
|
+
const newToken = uuid();
|
|
114
|
+
const newSessionId = uuid();
|
|
115
|
+
const expiryDays = this.config.refreshTokenExpiryDays ?? 14;
|
|
116
|
+
const expiration = Math.floor(Date.now() / 1000) + expiryDays * 24 * 60 * 60;
|
|
117
|
+
const newSession = {
|
|
118
|
+
id: newSessionId,
|
|
119
|
+
userId: session.userId,
|
|
120
|
+
familyId: session.familyId,
|
|
121
|
+
token: newToken,
|
|
122
|
+
expiration,
|
|
123
|
+
deviceInfo,
|
|
124
|
+
};
|
|
125
|
+
// Mark old token as replaced and record when
|
|
126
|
+
session.replacedBy = newToken;
|
|
127
|
+
session.usedAt = Date.now();
|
|
128
|
+
this.sessions.set(newToken, newSession);
|
|
129
|
+
return this.buildTokenPair(newToken, session.userId, newSessionId);
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Build a token pair with a signed access token.
|
|
133
|
+
*/
|
|
134
|
+
buildTokenPair(refreshToken, userId, sessionId) {
|
|
135
|
+
const expiryMinutes = this.config.accessTokenExpiryMinutes ?? 15;
|
|
136
|
+
const iat = Math.floor(Date.now() / 1000);
|
|
137
|
+
const exp = iat + expiryMinutes * 60;
|
|
138
|
+
const payload = { userId, sessionId, iat, exp };
|
|
139
|
+
const accessToken = signAccessToken(payload, this.config);
|
|
140
|
+
return { accessToken, refreshToken, exp };
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Clean up expired and revoked sessions.
|
|
144
|
+
*/
|
|
145
|
+
cleanup() {
|
|
146
|
+
const now = Date.now() / 1000;
|
|
147
|
+
for (const [key, session] of this.sessions) {
|
|
148
|
+
if (session.isRevoked || session.expiration <= now) {
|
|
149
|
+
this.sessions.delete(key);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
/**
|
|
154
|
+
* Stop the cleanup interval and clear sessions.
|
|
155
|
+
*/
|
|
156
|
+
destroy() {
|
|
157
|
+
clearInterval(this.cleanupInterval);
|
|
158
|
+
this.sessions.clear();
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Get the current session count (for monitoring).
|
|
162
|
+
*/
|
|
163
|
+
get size() {
|
|
164
|
+
return this.sessions.size;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=session-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.js","sourceRoot":"","sources":["../../../src/auth/server/session-manager.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,EAAE,IAAI,IAAI,EAAE,MAAM,cAAc,CAAA;AAUzC,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE7C;;;;;;GAMG;AACH,MAAM,OAAO,sBAAsB;IACzB,QAAQ,GAAG,IAAI,GAAG,EAAmB,CAAA;IACrC,MAAM,CAAY;IAClB,eAAe,CAAgB;IAEvC,YAAY,MAAkB;QAC5B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAA;QACpB,qDAAqD;QACrD,IAAI,CAAC,eAAe,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAA;IAClE,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,MAAc,EACd,UAAuB;QAEvB,MAAM,QAAQ,GAAG,IAAI,EAAE,CAAA;QACvB,MAAM,KAAK,GAAG,IAAI,EAAE,CAAA;QACpB,MAAM,SAAS,GAAG,IAAI,EAAE,CAAA;QAExB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,sBAAsB,IAAI,EAAE,CAAA;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QAE5E,MAAM,OAAO,GAAY;YACvB,EAAE,EAAE,SAAS;YACb,MAAM;YACN,QAAQ;YACR,KAAK;YACL,UAAU;YACV,UAAU;SACX,CAAA;QAED,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;QAEjC,OAAO,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC,CAAA;IACtD,CAAC;IAED,KAAK,CAAC,cAAc,CAClB,YAAoB,EACpB,UAAuB;QAEvB,MAAM,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,YAAY,CAAC,CAAA;QAE/C,IAAI,CAAC,OAAO,IAAI,OAAO,CAAC,SAAS,EAAE,CAAC;YAClC,OAAO,IAAI,CAAA;QACb,CAAC;QAED,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;YAC3C,OAAO,IAAI,CAAA;QACb,CAAC;QAED,gDAAgD;QAChD,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;YACvB,OAAO,IAAI,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAA;QACxC,CAAC;QAED,OAAO,IAAI,CAAC,aAAa,CAAC,OAAO,EAAE,UAAU,CAAC,CAAA;IAChD,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,SAAiB;QACnC,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;gBAC7B,OAAO,CAAC,SAAS,GAAG,IAAI,CAAA;gBACxB,OAAO,IAAI,CAAA;YACb,CAAC;QACH,CAAC;QACD,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAAgB;QACjC,IAAI,KAAK,GAAG,CAAC,CAAA;QAEb,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,IAAI,OAAO,CAAC,QAAQ,KAAK,QAAQ,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC;gBACxD,OAAO,CAAC,SAAS,GAAG,IAAI,CAAA;gBACxB,KAAK,EAAE,CAAA;YACT,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,MAAc;QAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;QAE7B,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAC9C,CAAC,CAAC,EAAE,CACF,CAAC,CAAC,MAAM,KAAK,MAAM;YACnB,CAAC,CAAC,CAAC,SAAS;YACZ,CAAC,CAAC,CAAC,UAAU;YACb,CAAC,CAAC,UAAU,GAAG,GAAG,CACrB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,qBAAqB,CACzB,MAAc,EACd,cAAuB;QAEvB,IAAI,KAAK,GAAG,CAAC,CAAA;QAEb,KAAK,MAAM,OAAO,IAAI,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,EAAE,CAAC;YAC7C,IACE,OAAO,CAAC,MAAM,KAAK,MAAM;gBACzB,CAAC,OAAO,CAAC,SAAS;gBAClB,CAAC,CAAC,cAAc,IAAI,OAAO,CAAC,QAAQ,KAAK,cAAc,CAAC,EACxD,CAAC;gBACD,OAAO,CAAC,SAAS,GAAG,IAAI,CAAA;gBACxB,KAAK,EAAE,CAAA;YACT,CAAC;QACH,CAAC;QAED,OAAO,KAAK,CAAA;IACd,CAAC;IAED;;;;OAIG;IACK,iBAAiB,CAAC,OAAgB;QACxC,MAAM,YAAY,GAAG,IAAI,CAAC,MAAM,CAAC,0BAA0B,IAAI,EAAE,CAAA;QACjE,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAEtB,oEAAoE;QACpE,IAAI,CAAC,OAAO,CAAC,MAAM,IAAI,GAAG,GAAG,OAAO,CAAC,MAAM,GAAG,YAAY,GAAG,IAAI,EAAE,CAAC;YAClE,0EAA0E;YAC1E,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;YACnC,OAAO,IAAI,CAAA;QACb,CAAC;QAED,kDAAkD;QAClD,MAAM,WAAW,GAAG,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,OAAO,CAAC,UAAW,CAAC,CAAA;QAC1D,IAAI,CAAC,WAAW,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;YAC1C,OAAO,IAAI,CAAA;QACb,CAAC;QAED,OAAO,IAAI,CAAC,cAAc,CACxB,WAAW,CAAC,KAAK,EACjB,WAAW,CAAC,MAAM,EAClB,WAAW,CAAC,EAAE,CACf,CAAA;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,aAAa,CACzB,OAAgB,EAChB,UAAuB;QAEvB,MAAM,QAAQ,GAAG,IAAI,EAAE,CAAA;QACvB,MAAM,YAAY,GAAG,IAAI,EAAE,CAAA;QAE3B,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAAC,sBAAsB,IAAI,EAAE,CAAA;QAC3D,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,GAAG,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QAE5E,MAAM,UAAU,GAAY;YAC1B,EAAE,EAAE,YAAY;YAChB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,QAAQ,EAAE,OAAO,CAAC,QAAQ;YAC1B,KAAK,EAAE,QAAQ;YACf,UAAU;YACV,UAAU;SACX,CAAA;QAED,6CAA6C;QAC7C,OAAO,CAAC,UAAU,GAAG,QAAQ,CAAA;QAC7B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,GAAG,EAAE,CAAA;QAC3B,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAA;QAEvC,OAAO,IAAI,CAAC,cAAc,CAAC,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;IACpE,CAAC;IAED;;OAEG;IACK,cAAc,CACpB,YAAoB,EACpB,MAAc,EACd,SAAiB;QAEjB,MAAM,aAAa,GAAG,IAAI,CAAC,MAAM,CAAC,wBAAwB,IAAI,EAAE,CAAA;QAChE,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAC,CAAA;QACzC,MAAM,GAAG,GAAG,GAAG,GAAG,aAAa,GAAG,EAAE,CAAA;QAEpC,MAAM,OAAO,GAAuB,EAAE,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,GAAG,EAAE,CAAA;QACnE,MAAM,WAAW,GAAG,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,MAAM,CAAC,CAAA;QAEzD,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,GAAG,EAAE,CAAA;IAC3C,CAAC;IAED;;OAEG;IACK,OAAO;QACb,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,IAAI,CAAA;QAE7B,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAC3C,IAAI,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,UAAU,IAAI,GAAG,EAAE,CAAC;gBACnD,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;YAC3B,CAAC;QACH,CAAC;IACH,CAAC;IAED;;OAEG;IACH,OAAO;QACL,aAAa,CAAC,IAAI,CAAC,eAAe,CAAC,CAAA;QACnC,IAAI,CAAC,QAAQ,CAAC,KAAK,EAAE,CAAA;IACvB,CAAC;IAED;;OAEG;IACH,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAA;IAC3B,CAAC;CACF"}
|