@estifanos-sh/convex-auth 0.0.1-preview.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 +52 -0
- package/dist/_generated/component.d.ts +2981 -0
- package/dist/bin.js +7194 -0
- package/dist/browser/index.d.ts +22 -0
- package/dist/browser/index.js +61 -0
- package/dist/browser/locks.js +20 -0
- package/dist/browser/navigation.js +14 -0
- package/dist/browser/runtime.js +90 -0
- package/dist/browser/webauthn.js +99 -0
- package/dist/client/core/types.d.ts +615 -0
- package/dist/client/core/types.js +23 -0
- package/dist/client/errors.js +30 -0
- package/dist/client/factors/device.js +100 -0
- package/dist/client/factors/totp.js +111 -0
- package/dist/client/factors/webauthn.js +69 -0
- package/dist/client/index.d.ts +60 -0
- package/dist/client/index.js +976 -0
- package/dist/client/runtime/invite.js +50 -0
- package/dist/client/runtime/mutex.js +25 -0
- package/dist/client/runtime/proxy.js +75 -0
- package/dist/client/runtime/storage.js +65 -0
- package/dist/component/_generated/api.js +26 -0
- package/dist/component/_generated/component.d.ts +2981 -0
- package/dist/component/_generated/component.js +1 -0
- package/dist/component/_generated/dataModel.js +1 -0
- package/dist/component/_generated/server.js +74 -0
- package/dist/component/account.js +197 -0
- package/dist/component/connection/audit.js +152 -0
- package/dist/component/connection/cache.js +205 -0
- package/dist/component/connection/domain/verification.js +63 -0
- package/dist/component/connection/domain.js +108 -0
- package/dist/component/connection/saml/assertion.js +41 -0
- package/dist/component/connection/saml/request.js +61 -0
- package/dist/component/connection/scim/config.js +55 -0
- package/dist/component/connection/scim/identity.js +162 -0
- package/dist/component/connection/secret.js +65 -0
- package/dist/component/connection/webhook/delivery.js +396 -0
- package/dist/component/connection/webhook/endpoint.js +77 -0
- package/dist/component/connection.js +204 -0
- package/dist/component/convex.config.d.ts +7 -0
- package/dist/component/convex.config.js +15 -0
- package/dist/component/crons.js +27 -0
- package/dist/component/event.js +341 -0
- package/dist/component/factor/device.js +141 -0
- package/dist/component/factor/passkey.js +385 -0
- package/dist/component/factor/totp.js +253 -0
- package/dist/component/functions.js +3 -0
- package/dist/component/group/active.js +63 -0
- package/dist/component/group/invite.js +300 -0
- package/dist/component/group/member.js +188 -0
- package/dist/component/group.js +431 -0
- package/dist/component/http.js +9 -0
- package/dist/component/index.d.ts +5 -0
- package/dist/component/index.js +3 -0
- package/dist/component/limits.js +103 -0
- package/dist/component/maintenance.js +205 -0
- package/dist/component/migrations.js +277 -0
- package/dist/component/model.d.ts +384 -0
- package/dist/component/model.js +709 -0
- package/dist/component/modules.js +53 -0
- package/dist/component/oauth/client.js +196 -0
- package/dist/component/oauth/code.js +97 -0
- package/dist/component/oauth/refresh.js +230 -0
- package/dist/component/schema.d.ts +1530 -0
- package/dist/component/schema.js +401 -0
- package/dist/component/session.js +134 -0
- package/dist/component/token/pkce.js +121 -0
- package/dist/component/token/refresh.js +189 -0
- package/dist/component/token/verification.js +155 -0
- package/dist/component/user/email.js +147 -0
- package/dist/component/user/key.js +273 -0
- package/dist/component/user.js +173 -0
- package/dist/core/index.d.ts +531 -0
- package/dist/core/index.js +81 -0
- package/dist/expo/index.d.ts +43 -0
- package/dist/expo/index.js +131 -0
- package/dist/expo/webauthn.js +88 -0
- package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/NoopLogger.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/api/logs.d.ts +3 -0
- package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/index.d.ts +7 -0
- package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/types/AnyValue.d.ts +21 -0
- package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/types/LogRecord.d.ts +36 -0
- package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/types/Logger.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/types/LoggerOptions.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_api-logs@0.214.0/node_modules/@opentelemetry/api-logs/build/src/types/LoggerProvider.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/baggage/propagation/W3CBaggagePropagator.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/baggage/utils.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/common/attributes.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/common/global-error-handler.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/common/logging-error-handler.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/common/time.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/common/types.d.ts +16 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/index.d.ts +13 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/propagation/composite.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/trace/TraceState.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/trace/W3CTraceContextPropagator.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/trace/rpc-metadata.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/trace/suppress-tracing.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_core@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/core/build/src/utils/configuration.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/LogRecordProcessor.d.ts +24 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/LoggerProvider.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/config/LoggerConfigurators.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/BatchLogRecordProcessorBase.d.ts +4 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/ConsoleLogRecordExporter.d.ts +3 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/InMemoryLogRecordExporter.d.ts +3 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/LogRecordExporter.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/ReadableLogRecord.d.ts +4 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/SdkLogRecord.d.ts +71 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/export/SimpleLogRecordProcessor.d.ts +3 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/index.d.ts +11 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/platform/index.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/platform/node/export/BatchLogRecordProcessor.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/platform/node/index.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-logs@0.214.0_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-logs/build/src/types.d.ts +4 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/InstrumentDescriptor.d.ts +3 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/MeterProvider.d.ts +4 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/Drop.d.ts +4 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/ExponentialHistogram.d.ts +5 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/Histogram.d.ts +5 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/LastValue.d.ts +5 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/Sum.d.ts +5 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/index.d.ts +6 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/aggregator/types.d.ts +53 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/AggregationSelector.d.ts +16 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/AggregationTemporality.d.ts +11 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/CardinalitySelector.d.ts +10 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/ConsoleMetricExporter.d.ts +4 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/InMemoryMetricExporter.d.ts +3 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/MetricData.d.ts +148 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/MetricExporter.d.ts +3 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/MetricProducer.d.ts +27 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/MetricReader.d.ts +138 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/export/PeriodicExportingMetricReader.d.ts +3 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/index.d.ts +15 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/types.d.ts +10 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/utils.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/view/Aggregation.d.ts +4 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/view/AggregationOption.d.ts +41 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/view/AttributesProcessor.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/view/InstrumentSelector.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-metrics@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-metrics/build/src/view/View.d.ts +5 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/BasicTracerProvider.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/IdGenerator.d.ts +11 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/Sampler.d.ts +74 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/Span.d.ts +17 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/SpanProcessor.d.ts +43 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/TimedEvent.d.ts +19 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/BatchSpanProcessorBase.d.ts +6 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/ConsoleSpanExporter.d.ts +3 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/InMemorySpanExporter.d.ts +3 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/NoopSpanProcessor.d.ts +4 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/ReadableSpan.d.ts +29 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/SimpleSpanProcessor.d.ts +5 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/export/SpanExporter.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/index.d.ts +18 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/platform/index.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/platform/node/export/BatchSpanProcessor.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/platform/node/index.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/sampler/AlwaysOffSampler.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/sampler/AlwaysOnSampler.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/sampler/ParentBasedSampler.d.ts +2 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/sampler/TraceIdRatioBasedSampler.d.ts +1 -0
- package/dist/node_modules/.pnpm/@opentelemetry_sdk-trace-base@2.6.1_@opentelemetry_api@1.9.1/node_modules/@opentelemetry/sdk-trace-base/build/src/types.d.ts +66 -0
- package/dist/otel.d.ts +73 -0
- package/dist/otel.js +82 -0
- package/dist/permissions/index.d.ts +81 -0
- package/dist/permissions/index.js +18 -0
- package/dist/providers/anonymous.d.ts +35 -0
- package/dist/providers/anonymous.js +40 -0
- package/dist/providers/apple.d.ts +61 -0
- package/dist/providers/apple.js +57 -0
- package/dist/providers/connection.d.ts +30 -0
- package/dist/providers/connection.js +33 -0
- package/dist/providers/credentials.d.ts +78 -0
- package/dist/providers/credentials.js +31 -0
- package/dist/providers/custom.d.ts +96 -0
- package/dist/providers/custom.js +108 -0
- package/dist/providers/device.d.ts +33 -0
- package/dist/providers/device.js +30 -0
- package/dist/providers/email.d.ts +45 -0
- package/dist/providers/email.js +52 -0
- package/dist/providers/github.d.ts +56 -0
- package/dist/providers/github.js +79 -0
- package/dist/providers/google.d.ts +56 -0
- package/dist/providers/google.js +59 -0
- package/dist/providers/index.d.ts +16 -0
- package/dist/providers/index.js +16 -0
- package/dist/providers/microsoft.d.ts +59 -0
- package/dist/providers/microsoft.js +98 -0
- package/dist/providers/password.d.ts +68 -0
- package/dist/providers/password.js +348 -0
- package/dist/providers/phone.d.ts +33 -0
- package/dist/providers/phone.js +35 -0
- package/dist/providers/redirect.d.ts +1 -0
- package/dist/providers/redirect.js +11 -0
- package/dist/providers/totp.d.ts +29 -0
- package/dist/providers/totp.js +29 -0
- package/dist/providers/webauthn/attestation.d.ts +42 -0
- package/dist/providers/webauthn/attestation.js +167 -0
- package/dist/providers/webauthn.d.ts +83 -0
- package/dist/providers/webauthn.js +57 -0
- package/dist/react/index.d.ts +55 -0
- package/dist/react/index.js +80 -0
- package/dist/server/auth.d.ts +443 -0
- package/dist/server/auth.js +178 -0
- package/dist/server/cache/context.js +94 -0
- package/dist/server/component/api.d.ts +14 -0
- package/dist/server/component/api.js +13 -0
- package/dist/server/component/context.d.ts +16 -0
- package/dist/server/component/context.js +1 -0
- package/dist/server/component/factor/db.js +71 -0
- package/dist/server/config.d.ts +3 -0
- package/dist/server/config.js +78 -0
- package/dist/server/connection/config.js +101 -0
- package/dist/server/connection/domain.d.ts +878 -0
- package/dist/server/connection/domain.js +1122 -0
- package/dist/server/connection/group/service.d.ts +25 -0
- package/dist/server/connection/group/service.js +250 -0
- package/dist/server/connection/http.js +1485 -0
- package/dist/server/connection/oidc.js +366 -0
- package/dist/server/connection/policy/domain.js +59 -0
- package/dist/server/connection/policy.d.ts +1 -0
- package/dist/server/connection/policy.js +163 -0
- package/dist/server/connection/profile.js +22 -0
- package/dist/server/connection/provision.js +182 -0
- package/dist/server/connection/saml/api.js +70 -0
- package/dist/server/connection/saml/binding/post.js +140 -0
- package/dist/server/connection/saml/binding/redirect.js +139 -0
- package/dist/server/connection/saml/binding/shared.js +18 -0
- package/dist/server/connection/saml/c14n.js +224 -0
- package/dist/server/connection/saml/constants.js +100 -0
- package/dist/server/connection/saml/crypto.js +170 -0
- package/dist/server/connection/saml/dom/select.js +299 -0
- package/dist/server/connection/saml/encoding.js +93 -0
- package/dist/server/connection/saml/encryption.js +34 -0
- package/dist/server/connection/saml/entity.js +24 -0
- package/dist/server/connection/saml/extractor.js +408 -0
- package/dist/server/connection/saml/flow.js +150 -0
- package/dist/server/connection/saml/identity/provider.js +66 -0
- package/dist/server/connection/saml/index.js +5 -0
- package/dist/server/connection/saml/metadata.js +294 -0
- package/dist/server/connection/saml/service/provider.js +117 -0
- package/dist/server/connection/saml/signature.js +214 -0
- package/dist/server/connection/saml/template.js +68 -0
- package/dist/server/connection/saml/types.js +1 -0
- package/dist/server/connection/saml/validator.js +32 -0
- package/dist/server/connection/saml/xml/builder.js +68 -0
- package/dist/server/connection/saml/xmldsig.js +598 -0
- package/dist/server/connection/saml/xmlenc.js +162 -0
- package/dist/server/connection/saml.d.ts +56 -0
- package/dist/server/connection/saml.js +762 -0
- package/dist/server/connection/scim.js +115 -0
- package/dist/server/connection/shared.js +74 -0
- package/dist/server/connection/webhook.js +163 -0
- package/dist/server/context.d.ts +137 -0
- package/dist/server/context.js +108 -0
- package/dist/server/contract.d.ts +48 -0
- package/dist/server/contract.js +107 -0
- package/dist/server/cookies.js +90 -0
- package/dist/server/core.js +163 -0
- package/dist/server/cors.d.ts +22 -0
- package/dist/server/cors.js +93 -0
- package/dist/server/crypto.js +43 -0
- package/dist/server/db.js +88 -0
- package/dist/server/device.js +140 -0
- package/dist/server/domains/access.js +29 -0
- package/dist/server/domains/account.d.ts +16 -0
- package/dist/server/domains/account.js +92 -0
- package/dist/server/domains/factor.d.ts +28 -0
- package/dist/server/domains/factor.js +115 -0
- package/dist/server/domains/group.js +87 -0
- package/dist/server/domains/invite.js +76 -0
- package/dist/server/domains/key.js +253 -0
- package/dist/server/domains/member.js +149 -0
- package/dist/server/domains/session.js +29 -0
- package/dist/server/domains/user.js +119 -0
- package/dist/server/env.d.ts +46 -0
- package/dist/server/env.js +96 -0
- package/dist/server/errors.js +38 -0
- package/dist/server/events.d.ts +880 -0
- package/dist/server/events.js +406 -0
- package/dist/server/facade.d.ts +83 -0
- package/dist/server/facade.js +124 -0
- package/dist/server/http.d.ts +125 -0
- package/dist/server/http.js +566 -0
- package/dist/server/identity/claims.js +58 -0
- package/dist/server/identity/convex.d.ts +15 -0
- package/dist/server/identity/convex.js +1 -0
- package/dist/server/index.d.ts +17 -0
- package/dist/server/index.js +11 -0
- package/dist/server/keys.js +60 -0
- package/dist/server/limits.js +41 -0
- package/dist/server/log.js +28 -0
- package/dist/server/mcp.d.ts +19 -0
- package/dist/server/mcp.js +250 -0
- package/dist/server/mutations/account.js +47 -0
- package/dist/server/mutations/calls.js +16 -0
- package/dist/server/mutations/code.js +91 -0
- package/dist/server/mutations/credentials/signin.js +210 -0
- package/dist/server/mutations/invalidate.js +60 -0
- package/dist/server/mutations/oauth.js +251 -0
- package/dist/server/mutations/refresh.js +152 -0
- package/dist/server/mutations/register.js +93 -0
- package/dist/server/mutations/retrieve.js +66 -0
- package/dist/server/mutations/signature.js +36 -0
- package/dist/server/mutations/signin.js +81 -0
- package/dist/server/mutations/signout.js +61 -0
- package/dist/server/mutations/store/refs.js +15 -0
- package/dist/server/mutations/store.js +82 -0
- package/dist/server/mutations/verifier.js +25 -0
- package/dist/server/mutations/verify.js +199 -0
- package/dist/server/oauth/authorize.js +98 -0
- package/dist/server/oauth/client.d.ts +93 -0
- package/dist/server/oauth/client.js +115 -0
- package/dist/server/oauth/code.d.ts +63 -0
- package/dist/server/oauth/code.js +124 -0
- package/dist/server/oauth/domain.d.ts +23 -0
- package/dist/server/oauth/domain.js +1 -0
- package/dist/server/oauth/factory.js +46 -0
- package/dist/server/oauth/grant.js +46 -0
- package/dist/server/oauth/handlers.js +108 -0
- package/dist/server/oauth/manage.js +121 -0
- package/dist/server/oauth/normalize.js +27 -0
- package/dist/server/oauth/refresh.d.ts +71 -0
- package/dist/server/oauth/refresh.js +132 -0
- package/dist/server/oauth/register.js +147 -0
- package/dist/server/oauth/runtime.js +280 -0
- package/dist/server/oauth/token.js +355 -0
- package/dist/server/payloads.d.ts +16 -0
- package/dist/server/payloads.js +30 -0
- package/dist/server/preload.d.ts +249 -0
- package/dist/server/preload.js +673 -0
- package/dist/server/random.js +25 -0
- package/dist/server/redirects.js +85 -0
- package/dist/server/runtime.d.ts +845 -0
- package/dist/server/runtime.js +387 -0
- package/dist/server/secret.js +46 -0
- package/dist/server/services/factors.js +117 -0
- package/dist/server/services/providers.js +23 -0
- package/dist/server/services/resolve.js +17 -0
- package/dist/server/session/lifecycle.d.ts +23 -0
- package/dist/server/session/lifecycle.js +139 -0
- package/dist/server/signin/flow.js +359 -0
- package/dist/server/telemetry.js +68 -0
- package/dist/server/templates.js +91 -0
- package/dist/server/token/refresh.js +35 -0
- package/dist/server/tokens.js +164 -0
- package/dist/server/totp.js +282 -0
- package/dist/server/types.d.ts +1154 -0
- package/dist/server/types.js +1 -0
- package/dist/server/url.js +43 -0
- package/dist/server/user/account.js +325 -0
- package/dist/server/utils/bearer.js +24 -0
- package/dist/server/utils/cache.js +51 -0
- package/dist/server/utils/retry.js +3 -0
- package/dist/server/utils/span.js +59 -0
- package/dist/server/validators.d.ts +2061 -0
- package/dist/server/validators.js +320 -0
- package/dist/server/webauthn.js +699 -0
- package/dist/server/wellknown.d.ts +74 -0
- package/dist/server/wellknown.js +195 -0
- package/dist/shared/brand.d.ts +28 -0
- package/dist/shared/brand.js +13 -0
- package/dist/shared/codes.d.ts +99 -0
- package/dist/shared/codes.js +98 -0
- package/dist/shared/compare.js +23 -0
- package/dist/shared/errors.js +24 -0
- package/dist/shared/event/kinds.d.ts +188 -0
- package/dist/shared/event/kinds.js +103 -0
- package/dist/shared/fetch/guard.js +189 -0
- package/dist/shared/log.js +62 -0
- package/dist/shared/results.d.ts +58 -0
- package/dist/shared/retry.js +27 -0
- package/dist/shared/webauthn.js +9 -0
- package/dist/svelte/AuthLoading.svelte +13 -0
- package/dist/svelte/AuthLoading.svelte.d.ts +8 -0
- package/dist/svelte/SignedIn.svelte +14 -0
- package/dist/svelte/SignedIn.svelte.d.ts +8 -0
- package/dist/svelte/SignedOut.svelte +13 -0
- package/dist/svelte/SignedOut.svelte.d.ts +8 -0
- package/dist/svelte/context.svelte.d.ts +26 -0
- package/dist/svelte/context.svelte.js +61 -0
- package/dist/svelte/index.d.ts +5 -0
- package/dist/svelte/index.js +4 -0
- package/dist/test.d.ts +48 -0
- package/dist/test.js +54 -0
- package/package.json +247 -0
|
@@ -0,0 +1,976 @@
|
|
|
1
|
+
import { LOG_LEVELS, logMessage } from "../shared/log.js";
|
|
2
|
+
import { retryWithBackoff } from "../shared/retry.js";
|
|
3
|
+
import { createDeferred } from "./core/types.js";
|
|
4
|
+
import { createHandshakeError } from "./errors.js";
|
|
5
|
+
import { createDeviceClient } from "./factors/device.js";
|
|
6
|
+
import { createTotpClient } from "./factors/totp.js";
|
|
7
|
+
import { createInviteManager } from "./runtime/invite.js";
|
|
8
|
+
import { localMutex } from "./runtime/mutex.js";
|
|
9
|
+
import { ProxyRequestError, isAuthRefreshRejection, isRetriableProxyRefreshError, isTransientNetworkError, parseProxyErrorBody } from "./runtime/proxy.js";
|
|
10
|
+
import { createStorageHelpers } from "./runtime/storage.js";
|
|
11
|
+
import { ConvexError } from "convex/values";
|
|
12
|
+
|
|
13
|
+
//#region src/client/index.ts
|
|
14
|
+
/**
|
|
15
|
+
* Framework-agnostic auth client for `@estifanos-sh/convex-auth/client`.
|
|
16
|
+
*
|
|
17
|
+
* Exposes the {@link client} factory, which wires auth tokens into a Convex
|
|
18
|
+
* transport and returns `signIn`, `signOut`, `subscribe`, `getSnapshot`, and the
|
|
19
|
+
* factor helpers enabled by the configured providers. Platform entrypoints
|
|
20
|
+
* (`browser`, `expo`) layer concrete runtime defaults on top of this.
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
*/
|
|
24
|
+
const VERIFIER_STORAGE_KEY = "__convexAuthOAuthVerifier";
|
|
25
|
+
const JWT_STORAGE_KEY = "__convexAuthJWT";
|
|
26
|
+
const REFRESH_TOKEN_STORAGE_KEY = "__convexAuthRefreshToken";
|
|
27
|
+
const INVITE_TOKEN_KEY = "__convexAuthPendingInvite";
|
|
28
|
+
const INVITE_EMAIL_KEY = "__convexAuthPendingInviteEmail";
|
|
29
|
+
const RETRY_BASE_MS = 500;
|
|
30
|
+
const RETRY_MAX_RETRIES = 2;
|
|
31
|
+
const DEFAULT_AUTH_HANDSHAKE_TIMEOUT_MS = 5e3;
|
|
32
|
+
const FORCED_REFRESH_REUSE_MS = 1e4;
|
|
33
|
+
const retryWithJitteredBackoff = (fn, shouldRetry) => retryWithBackoff(fn, {
|
|
34
|
+
maxRetries: RETRY_MAX_RETRIES,
|
|
35
|
+
baseMs: RETRY_BASE_MS,
|
|
36
|
+
jitterMode: "centered",
|
|
37
|
+
shouldRetry
|
|
38
|
+
});
|
|
39
|
+
/**
|
|
40
|
+
* Resolve the Convex deployment URL from the client.
|
|
41
|
+
*
|
|
42
|
+
* `ConvexReactClient` exposes `.url` directly.
|
|
43
|
+
* `ConvexClient` exposes `.client.url` via `BaseConvexClient`.
|
|
44
|
+
*
|
|
45
|
+
* @param convex - The Convex transport to read the deployment URL from.
|
|
46
|
+
* @param explicit - An explicit URL that short-circuits discovery.
|
|
47
|
+
* @returns The resolved deployment URL.
|
|
48
|
+
* @throws {Error} When no URL can be determined and `explicit` is not provided.
|
|
49
|
+
* @internal
|
|
50
|
+
*/
|
|
51
|
+
function resolveUrl(convex, explicit) {
|
|
52
|
+
if (explicit) return explicit;
|
|
53
|
+
const candidate = convex;
|
|
54
|
+
const client = typeof candidate.client === "object" && candidate.client !== null ? candidate.client : void 0;
|
|
55
|
+
const url = candidate.url ?? client?.url;
|
|
56
|
+
if (typeof url === "string") return url;
|
|
57
|
+
throw new Error("Could not determine Convex deployment URL. Pass `url` explicitly.");
|
|
58
|
+
}
|
|
59
|
+
const STABLE_STRINGIFY_MAX_DEPTH = 32;
|
|
60
|
+
function stableStringify(value, depth = 0) {
|
|
61
|
+
if (depth > STABLE_STRINGIFY_MAX_DEPTH) throw new Error("stableStringify: input exceeds maximum nesting depth");
|
|
62
|
+
if (value === void 0) return "null";
|
|
63
|
+
if (Array.isArray(value)) return `[${value.map((item) => stableStringify(item, depth + 1)).join(",")}]`;
|
|
64
|
+
if (value !== null && typeof value === "object") return `{${Object.entries(value).filter(([, entryValue]) => entryValue !== void 0).sort(([left], [right]) => left.localeCompare(right)).map(([key, entryValue]) => `${JSON.stringify(key)}:${stableStringify(entryValue, depth + 1)}`).join(",")}}`;
|
|
65
|
+
return JSON.stringify(value);
|
|
66
|
+
}
|
|
67
|
+
function buildSignInRequestKey(provider, params) {
|
|
68
|
+
return stableStringify({
|
|
69
|
+
provider: provider ?? null,
|
|
70
|
+
params
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
function formDataEntries(formData) {
|
|
74
|
+
return formData;
|
|
75
|
+
}
|
|
76
|
+
function resolveExplicitToken(value) {
|
|
77
|
+
if (value === void 0) return void 0;
|
|
78
|
+
if (value === null) return null;
|
|
79
|
+
if (value.trim().length === 0) return null;
|
|
80
|
+
if (value.trim() !== value) throw new Error("The `token` option must not include leading or trailing whitespace.");
|
|
81
|
+
return value;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Decode the `sub` (subject / user id) claim from a JWT access token without
|
|
85
|
+
* verifying its signature. Used only to compare identities across browser tabs
|
|
86
|
+
* — never for authorization. Returns `null` when the token cannot be decoded.
|
|
87
|
+
*/
|
|
88
|
+
function decodeJwtSubject(jwt) {
|
|
89
|
+
try {
|
|
90
|
+
const payloadSegment = jwt.split(".")[1];
|
|
91
|
+
if (payloadSegment === void 0 || payloadSegment.length === 0) return null;
|
|
92
|
+
const normalized = payloadSegment.replace(/-/g, "+").replace(/_/g, "/");
|
|
93
|
+
const padded = normalized + "=".repeat((4 - normalized.length % 4) % 4);
|
|
94
|
+
if (typeof atob !== "function") return null;
|
|
95
|
+
const claims = JSON.parse(atob(padded));
|
|
96
|
+
return typeof claims.sub === "string" ? claims.sub : null;
|
|
97
|
+
} catch {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Create a framework-agnostic auth client.
|
|
103
|
+
*
|
|
104
|
+
* Returns an object with `signIn`, `signOut`, `subscribe`, `getSnapshot`, and any
|
|
105
|
+
* factor helpers enabled by your configured providers. Platform-specific
|
|
106
|
+
* WebAuthn support is added by higher-level entrypoints such as
|
|
107
|
+
* `@estifanos-sh/convex-auth/browser`.
|
|
108
|
+
*
|
|
109
|
+
* ### SPA mode (default)
|
|
110
|
+
*
|
|
111
|
+
* ```ts
|
|
112
|
+
* import { ConvexClient } from 'convex/browser';
|
|
113
|
+
* import { client } from '@estifanos-sh/convex-auth/client';
|
|
114
|
+
* import { api } from '../convex/_generated/api';
|
|
115
|
+
*
|
|
116
|
+
* const convex = new ConvexClient(CONVEX_URL);
|
|
117
|
+
* const auth = client({ convex, api: api.auth });
|
|
118
|
+
* ```
|
|
119
|
+
*
|
|
120
|
+
* ### Proxy mode
|
|
121
|
+
*
|
|
122
|
+
* ```ts
|
|
123
|
+
* const auth = client({
|
|
124
|
+
* convex,
|
|
125
|
+
* proxyPath: '/api/auth',
|
|
126
|
+
* runtime: myRuntime,
|
|
127
|
+
* });
|
|
128
|
+
* ```
|
|
129
|
+
*
|
|
130
|
+
* In proxy mode all auth operations go through the injected proxy runtime.
|
|
131
|
+
* Tokens are stored in httpOnly cookies server-side — the client
|
|
132
|
+
* holds the JWT in memory only.
|
|
133
|
+
*
|
|
134
|
+
* The client resolves auth through a Convex confirmation handshake. For SSR,
|
|
135
|
+
* pass the server-known token via `token` so hydration starts from the same
|
|
136
|
+
* resolved state. The returned client also auto-wires its tokens into the
|
|
137
|
+
* passed Convex client via `setAuth`, so queries and mutations are
|
|
138
|
+
* authenticated without further configuration.
|
|
139
|
+
*
|
|
140
|
+
* While a sign-in handshake is pending, a transient `false` from the Convex
|
|
141
|
+
* client does not reject the session: Convex can emit `false` mid-reauth and a
|
|
142
|
+
* subsequent `true` confirms the same session. Rejection happens only on
|
|
143
|
+
* timeout or when the token actually changes or clears.
|
|
144
|
+
*
|
|
145
|
+
* @param options - Client configuration. See {@link ClientOptions}.
|
|
146
|
+
* @typeParam Api - An AuthApiRefs type determining which factor helpers are available.
|
|
147
|
+
* @returns Auth client with conditional `totp` and `device` helpers.
|
|
148
|
+
* @throws {Error} When the Convex deployment URL cannot be determined and `url` is not passed explicitly.
|
|
149
|
+
* @throws {Error} When `proxyPath` is not set and the `api` option is missing.
|
|
150
|
+
* @throws {Error} When `proxyPath` is set and `runtime.proxy` is missing.
|
|
151
|
+
* @throws {Error} When `token` has leading or trailing whitespace. An empty or
|
|
152
|
+
* whitespace-only string is treated as an explicit signed-out seed, not an error.
|
|
153
|
+
*/
|
|
154
|
+
function client(options) {
|
|
155
|
+
const { convex, proxyPath, api: apiRefs } = options;
|
|
156
|
+
const proxy = proxyPath;
|
|
157
|
+
const runtime = options.runtime ?? {};
|
|
158
|
+
const adapters = options.adapters ?? {};
|
|
159
|
+
const adapterFactories = options.adapterFactories ?? {};
|
|
160
|
+
function requireProxyRuntime() {
|
|
161
|
+
if (!runtime.proxy) throw new Error("The `runtime.proxy` option is required when `proxyPath` is set. Use `@estifanos-sh/convex-auth/browser` for browser defaults or inject a proxy runtime explicitly.");
|
|
162
|
+
return runtime.proxy;
|
|
163
|
+
}
|
|
164
|
+
function requireApiRefs() {
|
|
165
|
+
if (!apiRefs) throw new Error("The `api` option is required when `proxyPath` is not set. Pass { api: api.auth }.");
|
|
166
|
+
return apiRefs;
|
|
167
|
+
}
|
|
168
|
+
function requireHttpClient() {
|
|
169
|
+
if (!httpClient) throw new Error("The `httpClient` option is required when `proxyPath` is not set in a non-browser runtime. Use `@estifanos-sh/convex-auth/browser` for browser defaults or pass an action-only transport explicitly.");
|
|
170
|
+
return httpClient;
|
|
171
|
+
}
|
|
172
|
+
const storage = options.storage !== void 0 ? options.storage : runtime.storage !== void 0 ? runtime.storage : null;
|
|
173
|
+
const proxyRuntime = proxy ? requireProxyRuntime() : null;
|
|
174
|
+
function getLocation() {
|
|
175
|
+
if (typeof options.location === "function") return options.location();
|
|
176
|
+
if (options.location instanceof URL) return options.location;
|
|
177
|
+
if (runtime.location) return runtime.location.get();
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
/**
|
|
181
|
+
* SSR-safe URL parameter reader.
|
|
182
|
+
*
|
|
183
|
+
* Uses the injected location source when provided.
|
|
184
|
+
*
|
|
185
|
+
* @param name - The query parameter name.
|
|
186
|
+
* @returns The parameter value, or `null` if not present or in SSR.
|
|
187
|
+
*
|
|
188
|
+
* @example
|
|
189
|
+
* ```ts
|
|
190
|
+
* const workspaceId = auth.param("workspace");
|
|
191
|
+
* const tab = auth.param("tab") ?? "issues";
|
|
192
|
+
* ```
|
|
193
|
+
*/
|
|
194
|
+
function param(name) {
|
|
195
|
+
return getLocation()?.searchParams.get(name) ?? null;
|
|
196
|
+
}
|
|
197
|
+
function cleanUrlParams(params) {
|
|
198
|
+
const loc = getLocation();
|
|
199
|
+
if (!loc) return;
|
|
200
|
+
if (!runtime.location) return;
|
|
201
|
+
const searchParams = new URLSearchParams(loc.search);
|
|
202
|
+
let changed = false;
|
|
203
|
+
for (const p of params) if (searchParams.has(p)) {
|
|
204
|
+
searchParams.delete(p);
|
|
205
|
+
changed = true;
|
|
206
|
+
}
|
|
207
|
+
if (changed) {
|
|
208
|
+
const next = searchParams.toString() ? `${loc.pathname}?${searchParams}` : loc.pathname;
|
|
209
|
+
runtime.location.replace(next);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const url = proxy ? void 0 : resolveUrl(convex, options.url);
|
|
213
|
+
const escapedNamespace = (proxy ?? url).replace(/^https?:\/\//, "").replace(/[^a-zA-Z0-9]/g, "_");
|
|
214
|
+
const key = (name) => `${name}_${escapedNamespace}`;
|
|
215
|
+
const { get: storageGet, set: storageSet, remove: storageRemove } = createStorageHelpers({
|
|
216
|
+
storage,
|
|
217
|
+
key
|
|
218
|
+
});
|
|
219
|
+
const withAuthStorageMutex = async (callback) => {
|
|
220
|
+
const mutexKey = `__convexAuthStorage_${escapedNamespace}`;
|
|
221
|
+
return runtime.mutex ? await runtime.mutex.withKey(mutexKey, callback) : await localMutex(mutexKey, callback);
|
|
222
|
+
};
|
|
223
|
+
const proxyFetch = async (body) => {
|
|
224
|
+
if (!proxy) throw new Error("Proxy fetch requested without proxyPath.");
|
|
225
|
+
const response = await proxyRuntime.fetch(body, proxy);
|
|
226
|
+
if (!response.ok) {
|
|
227
|
+
let errorBody = {};
|
|
228
|
+
try {
|
|
229
|
+
errorBody = parseProxyErrorBody(await response.json());
|
|
230
|
+
} catch {
|
|
231
|
+
errorBody = {};
|
|
232
|
+
}
|
|
233
|
+
if (typeof errorBody === "object" && errorBody !== null && "authError" in errorBody && typeof errorBody.authError === "object") throw new ConvexError(errorBody.authError);
|
|
234
|
+
throw new ProxyRequestError(response.status, errorBody.error);
|
|
235
|
+
}
|
|
236
|
+
try {
|
|
237
|
+
return await response.json();
|
|
238
|
+
} catch {
|
|
239
|
+
throw new Error("Proxy response was not valid JSON");
|
|
240
|
+
}
|
|
241
|
+
};
|
|
242
|
+
const subscribers = /* @__PURE__ */ new Set();
|
|
243
|
+
let disposeStorageListener = null;
|
|
244
|
+
const httpClient = proxy ? null : options.httpClient ?? null;
|
|
245
|
+
const readInitialToken = () => {
|
|
246
|
+
if (!storage) return null;
|
|
247
|
+
try {
|
|
248
|
+
const raw = storage.getItem(key(JWT_STORAGE_KEY));
|
|
249
|
+
return typeof raw === "string" && raw.length > 0 ? raw : null;
|
|
250
|
+
} catch {
|
|
251
|
+
return null;
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
const explicitToken = resolveExplicitToken(options.token);
|
|
255
|
+
const tokenProvided = explicitToken !== void 0;
|
|
256
|
+
const serverToken = tokenProvided ? explicitToken : readInitialToken();
|
|
257
|
+
const hasServerToken = serverToken !== null;
|
|
258
|
+
const handshakeTimeoutMs = typeof options.handshakeTimeoutMs === "number" && options.handshakeTimeoutMs > 0 ? options.handshakeTimeoutMs : DEFAULT_AUTH_HANDSHAKE_TIMEOUT_MS;
|
|
259
|
+
let token = serverToken;
|
|
260
|
+
let isLoading = !hasServerToken && !tokenProvided;
|
|
261
|
+
let authConfirmed = hasServerToken;
|
|
262
|
+
let handshakePending = false;
|
|
263
|
+
let authEpoch = 0;
|
|
264
|
+
let lastForcedRefreshTime = 0;
|
|
265
|
+
let forcedRefreshPromise = null;
|
|
266
|
+
let destroyed = false;
|
|
267
|
+
let deauthGraceTimer = null;
|
|
268
|
+
let activeSignIn = null;
|
|
269
|
+
let initializePromise = null;
|
|
270
|
+
const handshakeWaiters = /* @__PURE__ */ new Set();
|
|
271
|
+
let snapshot = {
|
|
272
|
+
phase: hasServerToken ? "authenticated" : isLoading ? "loading" : "unauthenticated",
|
|
273
|
+
isLoading,
|
|
274
|
+
isAuthenticated: hasServerToken,
|
|
275
|
+
token
|
|
276
|
+
};
|
|
277
|
+
const computePublic = () => {
|
|
278
|
+
if (snapshot.token !== null && snapshot.phase === "authenticated") return {
|
|
279
|
+
status: "signedIn",
|
|
280
|
+
token: snapshot.token
|
|
281
|
+
};
|
|
282
|
+
if (snapshot.phase === "loading" || snapshot.phase === "handshake") return {
|
|
283
|
+
status: "loading",
|
|
284
|
+
token: null
|
|
285
|
+
};
|
|
286
|
+
return {
|
|
287
|
+
status: "signedOut",
|
|
288
|
+
token: null
|
|
289
|
+
};
|
|
290
|
+
};
|
|
291
|
+
let publicSnapshot = computePublic();
|
|
292
|
+
const authStatesEqual = (left, right) => left.status === right.status && left.token === right.token;
|
|
293
|
+
const refreshPublic = () => {
|
|
294
|
+
const next = computePublic();
|
|
295
|
+
if (authStatesEqual(publicSnapshot, next)) return false;
|
|
296
|
+
publicSnapshot = next;
|
|
297
|
+
return true;
|
|
298
|
+
};
|
|
299
|
+
const settleHandshakeWaiters = (epoch, outcome) => {
|
|
300
|
+
for (const waiter of Array.from(handshakeWaiters)) {
|
|
301
|
+
if (waiter.epoch !== epoch) continue;
|
|
302
|
+
clearTimeout(waiter.timeoutId);
|
|
303
|
+
handshakeWaiters.delete(waiter);
|
|
304
|
+
if (outcome.type === "resolve") waiter.deferred.resolve(void 0);
|
|
305
|
+
else waiter.deferred.reject(outcome.error);
|
|
306
|
+
}
|
|
307
|
+
};
|
|
308
|
+
const rejectObsoleteHandshakeWaiters = (activeEpoch) => {
|
|
309
|
+
for (const waiter of Array.from(handshakeWaiters)) {
|
|
310
|
+
if (waiter.epoch >= activeEpoch) continue;
|
|
311
|
+
clearTimeout(waiter.timeoutId);
|
|
312
|
+
handshakeWaiters.delete(waiter);
|
|
313
|
+
waiter.deferred.reject(createHandshakeError("AUTH_HANDSHAKE_REJECTED", {
|
|
314
|
+
...waiter.context,
|
|
315
|
+
reason: "token_changed"
|
|
316
|
+
}));
|
|
317
|
+
}
|
|
318
|
+
};
|
|
319
|
+
const rejectAllHandshakeWaiters = (error) => {
|
|
320
|
+
for (const waiter of Array.from(handshakeWaiters)) {
|
|
321
|
+
clearTimeout(waiter.timeoutId);
|
|
322
|
+
handshakeWaiters.delete(waiter);
|
|
323
|
+
waiter.deferred.reject(error);
|
|
324
|
+
}
|
|
325
|
+
};
|
|
326
|
+
const clearDeauthGrace = () => {
|
|
327
|
+
if (deauthGraceTimer !== null) {
|
|
328
|
+
clearTimeout(deauthGraceTimer);
|
|
329
|
+
deauthGraceTimer = null;
|
|
330
|
+
}
|
|
331
|
+
};
|
|
332
|
+
/**
|
|
333
|
+
* Arm the bounded re-handshake window after Convex reports a confirmed
|
|
334
|
+
* session as unauthenticated. The public snapshot is intentionally left on
|
|
335
|
+
* the confirmed state so a transient mid-rotation `false` does not flicker the
|
|
336
|
+
* UI; only if no confirming `true` arrives before the window elapses (and the
|
|
337
|
+
* token identity is unchanged) do we sign out.
|
|
338
|
+
*/
|
|
339
|
+
const startDeauthGrace = () => {
|
|
340
|
+
if (deauthGraceTimer !== null) return;
|
|
341
|
+
const epoch = authEpoch;
|
|
342
|
+
deauthGraceTimer = setTimeout(() => {
|
|
343
|
+
deauthGraceTimer = null;
|
|
344
|
+
if (destroyed || authEpoch !== epoch || !authConfirmed || token === null) return;
|
|
345
|
+
setToken({
|
|
346
|
+
shouldStore: true,
|
|
347
|
+
tokens: null
|
|
348
|
+
}).catch((error) => {
|
|
349
|
+
logMessage("convex-auth/client", LOG_LEVELS.ERROR, ["[convex-auth] Sign-out after server-side deauthentication failed:", error]);
|
|
350
|
+
});
|
|
351
|
+
}, handshakeTimeoutMs);
|
|
352
|
+
};
|
|
353
|
+
const waitForAuthHandshake = async (context) => {
|
|
354
|
+
if (token === null) return;
|
|
355
|
+
if (authConfirmed && !handshakePending) return;
|
|
356
|
+
if (!handshakePending) throw createHandshakeError("AUTH_HANDSHAKE_REJECTED", {
|
|
357
|
+
...context,
|
|
358
|
+
reason: "auth_rejected"
|
|
359
|
+
});
|
|
360
|
+
const epoch = authEpoch;
|
|
361
|
+
const deferred = createDeferred();
|
|
362
|
+
const waiter = {
|
|
363
|
+
epoch,
|
|
364
|
+
context,
|
|
365
|
+
deferred,
|
|
366
|
+
timeoutId: setTimeout(() => {
|
|
367
|
+
handshakeWaiters.delete(waiter);
|
|
368
|
+
deferred.reject(createHandshakeError("AUTH_HANDSHAKE_TIMEOUT", {
|
|
369
|
+
...context,
|
|
370
|
+
timeoutMs: handshakeTimeoutMs
|
|
371
|
+
}));
|
|
372
|
+
if (!destroyed && authEpoch === epoch && token !== null && handshakePending) {
|
|
373
|
+
const timedOutToken = token;
|
|
374
|
+
withAuthStorageMutex(async () => {
|
|
375
|
+
if (destroyed || authEpoch !== epoch || token !== timedOutToken || !handshakePending) return;
|
|
376
|
+
await storageRemove(JWT_STORAGE_KEY);
|
|
377
|
+
if (destroyed || authEpoch !== epoch || token !== timedOutToken || !handshakePending) return;
|
|
378
|
+
await setToken({
|
|
379
|
+
shouldStore: false,
|
|
380
|
+
tokens: null
|
|
381
|
+
});
|
|
382
|
+
}).catch((error) => {
|
|
383
|
+
logMessage("convex-auth/client", LOG_LEVELS.ERROR, ["[convex-auth] Sign-out after handshake timeout failed:", error]);
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
}, handshakeTimeoutMs)
|
|
387
|
+
};
|
|
388
|
+
handshakeWaiters.add(waiter);
|
|
389
|
+
try {
|
|
390
|
+
await deferred.promise;
|
|
391
|
+
} finally {
|
|
392
|
+
clearTimeout(waiter.timeoutId);
|
|
393
|
+
handshakeWaiters.delete(waiter);
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
const handleConvexAuthChange = (isAuthenticated) => {
|
|
397
|
+
if (destroyed) return;
|
|
398
|
+
if (isAuthenticated) {
|
|
399
|
+
authConfirmed = true;
|
|
400
|
+
handshakePending = false;
|
|
401
|
+
clearDeauthGrace();
|
|
402
|
+
settleHandshakeWaiters(authEpoch, { type: "resolve" });
|
|
403
|
+
} else if (token === null || !authConfirmed) {
|
|
404
|
+
authConfirmed = false;
|
|
405
|
+
if (token !== null) handshakePending = true;
|
|
406
|
+
} else startDeauthGrace();
|
|
407
|
+
if (updateSnapshot()) notify();
|
|
408
|
+
};
|
|
409
|
+
const notify = () => {
|
|
410
|
+
refreshPublic();
|
|
411
|
+
for (const cb of subscribers) cb();
|
|
412
|
+
};
|
|
413
|
+
const updateSnapshot = () => {
|
|
414
|
+
const phase = token !== null && handshakePending ? "handshake" : isLoading ? "loading" : token !== null && authConfirmed ? "authenticated" : "unauthenticated";
|
|
415
|
+
const next = {
|
|
416
|
+
phase,
|
|
417
|
+
isLoading: phase === "loading" || phase === "handshake",
|
|
418
|
+
isAuthenticated: phase === "authenticated",
|
|
419
|
+
token
|
|
420
|
+
};
|
|
421
|
+
if (snapshot.phase === next.phase && snapshot.isLoading === next.isLoading && snapshot.isAuthenticated === next.isAuthenticated && snapshot.token === next.token) return false;
|
|
422
|
+
snapshot = next;
|
|
423
|
+
return true;
|
|
424
|
+
};
|
|
425
|
+
const finalizeLoadingState = () => {
|
|
426
|
+
if (!isLoading) return;
|
|
427
|
+
isLoading = false;
|
|
428
|
+
if (updateSnapshot()) notify();
|
|
429
|
+
};
|
|
430
|
+
const inviteManager = createInviteManager({
|
|
431
|
+
param,
|
|
432
|
+
storageGet,
|
|
433
|
+
storageSet,
|
|
434
|
+
storageRemove,
|
|
435
|
+
cleanUrlParams,
|
|
436
|
+
tokenKey: INVITE_TOKEN_KEY,
|
|
437
|
+
emailKey: INVITE_EMAIL_KEY
|
|
438
|
+
});
|
|
439
|
+
const getPendingInvite = () => inviteManager.getPendingInvite();
|
|
440
|
+
const persistInvite = () => inviteManager.persistInvite();
|
|
441
|
+
const acceptInvite = () => inviteManager.acceptInvite();
|
|
442
|
+
const bindConvexAuth = () => {
|
|
443
|
+
convex.setAuth(fetchAccessToken, handleConvexAuthChange);
|
|
444
|
+
};
|
|
445
|
+
const setToken = async (args) => {
|
|
446
|
+
const previousToken = token;
|
|
447
|
+
token = args.tokens === null ? null : args.tokens.token;
|
|
448
|
+
const tokenChanged = token !== previousToken;
|
|
449
|
+
if (tokenChanged) {
|
|
450
|
+
authEpoch += 1;
|
|
451
|
+
rejectObsoleteHandshakeWaiters(authEpoch);
|
|
452
|
+
clearDeauthGrace();
|
|
453
|
+
}
|
|
454
|
+
if (args.tokens === null) lastForcedRefreshTime = 0;
|
|
455
|
+
if (args.shouldStore) await withAuthStorageMutex(async () => {
|
|
456
|
+
if (args.tokens === null) {
|
|
457
|
+
await storageRemove(JWT_STORAGE_KEY);
|
|
458
|
+
await storageRemove(REFRESH_TOKEN_STORAGE_KEY);
|
|
459
|
+
} else if ("refreshToken" in args.tokens) {
|
|
460
|
+
await storageSet(JWT_STORAGE_KEY, args.tokens.token);
|
|
461
|
+
await storageSet(REFRESH_TOKEN_STORAGE_KEY, args.tokens.refreshToken);
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
if (token === null) {
|
|
465
|
+
authConfirmed = false;
|
|
466
|
+
handshakePending = false;
|
|
467
|
+
settleHandshakeWaiters(authEpoch, {
|
|
468
|
+
type: "reject",
|
|
469
|
+
error: createHandshakeError("AUTH_HANDSHAKE_REJECTED", { reason: "token_cleared" })
|
|
470
|
+
});
|
|
471
|
+
} else if (!(authConfirmed && args.resyncConvexAuth === false && args.requireHandshake !== true) && (args.requireHandshake === true || tokenChanged || !authConfirmed)) {
|
|
472
|
+
authConfirmed = false;
|
|
473
|
+
handshakePending = true;
|
|
474
|
+
} else handshakePending = false;
|
|
475
|
+
const hadPendingLoad = isLoading;
|
|
476
|
+
isLoading = false;
|
|
477
|
+
const changed = updateSnapshot();
|
|
478
|
+
if (args.resyncConvexAuth !== false) bindConvexAuth();
|
|
479
|
+
if (hadPendingLoad || changed) notify();
|
|
480
|
+
};
|
|
481
|
+
const setTokenAndMaybeWait = async (args) => {
|
|
482
|
+
const { waitForHandshake, context, ...tokenArgs } = args;
|
|
483
|
+
await setToken({
|
|
484
|
+
...tokenArgs,
|
|
485
|
+
requireHandshake: waitForHandshake
|
|
486
|
+
});
|
|
487
|
+
if (tokenArgs.tokens === null) return false;
|
|
488
|
+
if (waitForHandshake) await waitForAuthHandshake(context);
|
|
489
|
+
return true;
|
|
490
|
+
};
|
|
491
|
+
const adapterDeps = {
|
|
492
|
+
proxy,
|
|
493
|
+
convex,
|
|
494
|
+
requireApiRefs,
|
|
495
|
+
proxyFetch,
|
|
496
|
+
setTokenAndMaybeWait
|
|
497
|
+
};
|
|
498
|
+
const webauthnAdapter = adapters.webauthn ?? adapterFactories.webauthn?.(adapterDeps);
|
|
499
|
+
const verifyCode = async (args) => {
|
|
500
|
+
return retryWithJitteredBackoff(() => requireHttpClient().action(requireApiRefs().signIn, "code" in args ? {
|
|
501
|
+
params: { code: args.code },
|
|
502
|
+
verifier: args.verifier
|
|
503
|
+
} : args), isTransientNetworkError);
|
|
504
|
+
};
|
|
505
|
+
const normalizeDeviceCodeResult = (device_code) => {
|
|
506
|
+
const input = device_code;
|
|
507
|
+
return {
|
|
508
|
+
deviceCode: input.deviceCode,
|
|
509
|
+
userCode: input.userCode,
|
|
510
|
+
verificationUri: input.verification_uri ?? input.verificationUri ?? "",
|
|
511
|
+
verificationUriComplete: input.verification_uri_complete ?? input.verificationUriComplete ?? "",
|
|
512
|
+
expiresIn: input.expiresIn,
|
|
513
|
+
interval: input.interval
|
|
514
|
+
};
|
|
515
|
+
};
|
|
516
|
+
const isSignedInResult = (result) => result.kind === "signedIn";
|
|
517
|
+
/**
|
|
518
|
+
* Hand an OAuth authorization URL to the platform launcher.
|
|
519
|
+
*
|
|
520
|
+
* Browser-style runtimes navigate away and return nothing, so the caller
|
|
521
|
+
* receives the `redirect` result. Session-style runtimes (Expo) return the
|
|
522
|
+
* callback URL, which is completed inline and resolves to `signedIn`.
|
|
523
|
+
*/
|
|
524
|
+
const launchOAuth = async (redirect, verifier) => {
|
|
525
|
+
const redirectResult = {
|
|
526
|
+
kind: "redirect",
|
|
527
|
+
redirect,
|
|
528
|
+
verifier
|
|
529
|
+
};
|
|
530
|
+
if (!runtime.oauth) return redirectResult;
|
|
531
|
+
const callback = await runtime.oauth.open(redirect);
|
|
532
|
+
if (callback === void 0) return redirectResult;
|
|
533
|
+
return (await completeOAuth(callback)).handled ? { kind: "signedIn" } : redirectResult;
|
|
534
|
+
};
|
|
535
|
+
/**
|
|
536
|
+
* Sign in with a provider.
|
|
537
|
+
*
|
|
538
|
+
* @param provider - Provider ID (e.g. `"email"`, `"password"`, `"google"`).
|
|
539
|
+
* Omit when exchanging an OAuth code (the code carries the provider info).
|
|
540
|
+
* @param args - Provider-specific arguments. Pass a `Record<string, Value>`
|
|
541
|
+
* or `FormData`. Common fields: `email`, `password`, `code`, `redirectTo`.
|
|
542
|
+
* @returns A {@link SignInResult} indicating the outcome.
|
|
543
|
+
* @throws {ConvexError} When the server action rejects the sign-in attempt (e.g. invalid credentials, provider error, or rate limiting).
|
|
544
|
+
*
|
|
545
|
+
* @example Email magic link
|
|
546
|
+
* ```ts
|
|
547
|
+
* await auth.signIn('email', { email: 'user@example.com' });
|
|
548
|
+
* ```
|
|
549
|
+
*
|
|
550
|
+
* @example Password
|
|
551
|
+
* ```ts
|
|
552
|
+
* const result = await auth.signIn('password', { email, password, flow: 'signIn' });
|
|
553
|
+
* if (result.kind === 'totpRequired') {
|
|
554
|
+
* await auth.totp.verify({ code: totpCode, verifier: result.verifier });
|
|
555
|
+
* }
|
|
556
|
+
* ```
|
|
557
|
+
*
|
|
558
|
+
* @example OAuth (returns a redirect URL)
|
|
559
|
+
* ```ts
|
|
560
|
+
* const result = await auth.signIn('google');
|
|
561
|
+
* if (result.kind === 'redirect') {
|
|
562
|
+
* window.location.href = result.redirect.toString();
|
|
563
|
+
* }
|
|
564
|
+
* ```
|
|
565
|
+
*/
|
|
566
|
+
const signIn = async (provider, args) => {
|
|
567
|
+
if (destroyed) throw new Error("Convex auth client has been destroyed.");
|
|
568
|
+
await persistInvite();
|
|
569
|
+
const rawParams = args instanceof FormData ? (() => {
|
|
570
|
+
const formParams = {};
|
|
571
|
+
for (const [key$1, value] of formDataEntries(args)) if (typeof value === "string") formParams[key$1] = value;
|
|
572
|
+
return formParams;
|
|
573
|
+
})() : args ?? {};
|
|
574
|
+
const params = options.oauthRedirectTo !== void 0 && rawParams.redirectTo === void 0 ? {
|
|
575
|
+
...rawParams,
|
|
576
|
+
redirectTo: options.oauthRedirectTo
|
|
577
|
+
} : rawParams;
|
|
578
|
+
const flow = typeof params.flow === "string" && params.flow.length > 0 ? params.flow : "signIn";
|
|
579
|
+
const signInKey = buildSignInRequestKey(provider, params);
|
|
580
|
+
const handleSignInActionResult = async (result, resultOptions) => {
|
|
581
|
+
if (result.kind === "redirect") {
|
|
582
|
+
const redirectUrl = new URL(result.redirect);
|
|
583
|
+
if (resultOptions.persistVerifier) await storageSet(VERIFIER_STORAGE_KEY, result.verifier);
|
|
584
|
+
return {
|
|
585
|
+
kind: "redirect",
|
|
586
|
+
redirect: redirectUrl,
|
|
587
|
+
verifier: result.verifier
|
|
588
|
+
};
|
|
589
|
+
}
|
|
590
|
+
if (result.kind === "totpRequired") return {
|
|
591
|
+
kind: "totpRequired",
|
|
592
|
+
verifier: result.verifier
|
|
593
|
+
};
|
|
594
|
+
if (result.kind === "deviceCode") return {
|
|
595
|
+
kind: "deviceCode",
|
|
596
|
+
deviceCode: normalizeDeviceCodeResult(result.deviceCode)
|
|
597
|
+
};
|
|
598
|
+
if (result.kind === "signedIn") return await setTokenAndMaybeWait(resultOptions.shouldStore ? {
|
|
599
|
+
shouldStore: true,
|
|
600
|
+
tokens: result.session,
|
|
601
|
+
waitForHandshake: true,
|
|
602
|
+
context: {
|
|
603
|
+
provider,
|
|
604
|
+
flow
|
|
605
|
+
}
|
|
606
|
+
} : {
|
|
607
|
+
shouldStore: false,
|
|
608
|
+
tokens: result.session === null ? null : { token: result.session.token },
|
|
609
|
+
waitForHandshake: true,
|
|
610
|
+
context: {
|
|
611
|
+
provider,
|
|
612
|
+
flow
|
|
613
|
+
}
|
|
614
|
+
}) ? { kind: "signedIn" } : { kind: "started" };
|
|
615
|
+
return { kind: "started" };
|
|
616
|
+
};
|
|
617
|
+
if (activeSignIn !== null) {
|
|
618
|
+
if (activeSignIn.key === signInKey) return await activeSignIn.promise;
|
|
619
|
+
throw new Error("Another sign-in flow is already in progress.");
|
|
620
|
+
}
|
|
621
|
+
const runSignInAction = async () => {
|
|
622
|
+
if (proxy) return await handleSignInActionResult(await proxyFetch({
|
|
623
|
+
action: "auth:signIn",
|
|
624
|
+
args: {
|
|
625
|
+
provider,
|
|
626
|
+
params
|
|
627
|
+
}
|
|
628
|
+
}), {
|
|
629
|
+
shouldStore: false,
|
|
630
|
+
persistVerifier: false
|
|
631
|
+
});
|
|
632
|
+
const verifier = await storageGet(VERIFIER_STORAGE_KEY) ?? void 0;
|
|
633
|
+
try {
|
|
634
|
+
const result = await convex.action(requireApiRefs().signIn, {
|
|
635
|
+
provider,
|
|
636
|
+
params,
|
|
637
|
+
verifier
|
|
638
|
+
});
|
|
639
|
+
if (params.code !== void 0) await storageRemove(VERIFIER_STORAGE_KEY);
|
|
640
|
+
return await handleSignInActionResult(result, {
|
|
641
|
+
shouldStore: true,
|
|
642
|
+
persistVerifier: true
|
|
643
|
+
});
|
|
644
|
+
} catch (error) {
|
|
645
|
+
if (params.code !== void 0) {
|
|
646
|
+
const convexCode = error instanceof ConvexError && typeof error.data?.code === "string" ? error.data.code : null;
|
|
647
|
+
if (convexCode !== null && ["INVALID_VERIFICATION_CODE", "INVALID_VERIFIER"].includes(convexCode)) await storageRemove(VERIFIER_STORAGE_KEY);
|
|
648
|
+
}
|
|
649
|
+
throw error;
|
|
650
|
+
}
|
|
651
|
+
};
|
|
652
|
+
const signInPromise = (async () => {
|
|
653
|
+
const result = await runSignInAction();
|
|
654
|
+
return result.kind === "redirect" ? await launchOAuth(result.redirect, result.verifier) : result;
|
|
655
|
+
})();
|
|
656
|
+
activeSignIn = {
|
|
657
|
+
key: signInKey,
|
|
658
|
+
promise: signInPromise
|
|
659
|
+
};
|
|
660
|
+
try {
|
|
661
|
+
return await signInPromise;
|
|
662
|
+
} finally {
|
|
663
|
+
if (activeSignIn?.promise === signInPromise) activeSignIn = null;
|
|
664
|
+
}
|
|
665
|
+
};
|
|
666
|
+
/**
|
|
667
|
+
* Sign out the current user.
|
|
668
|
+
*
|
|
669
|
+
* Invalidates the server session and clears local token state.
|
|
670
|
+
* Errors are silently caught — calling `signOut` on an already
|
|
671
|
+
* signed-out user is a no-op.
|
|
672
|
+
*/
|
|
673
|
+
const signOut = async () => {
|
|
674
|
+
if (destroyed) return;
|
|
675
|
+
if (proxy) {
|
|
676
|
+
try {
|
|
677
|
+
await proxyFetch({
|
|
678
|
+
action: "auth:signOut",
|
|
679
|
+
args: {}
|
|
680
|
+
});
|
|
681
|
+
} catch {}
|
|
682
|
+
await setToken({
|
|
683
|
+
shouldStore: false,
|
|
684
|
+
tokens: null
|
|
685
|
+
});
|
|
686
|
+
if (convex.clearAuth) convex.clearAuth();
|
|
687
|
+
return;
|
|
688
|
+
}
|
|
689
|
+
try {
|
|
690
|
+
await convex.action(requireApiRefs().signOut, {});
|
|
691
|
+
} catch {}
|
|
692
|
+
await setToken({
|
|
693
|
+
shouldStore: true,
|
|
694
|
+
tokens: null
|
|
695
|
+
});
|
|
696
|
+
if (convex.clearAuth) convex.clearAuth();
|
|
697
|
+
};
|
|
698
|
+
const fetchAccessToken = async ({ forceRefreshToken }) => {
|
|
699
|
+
if (destroyed) return null;
|
|
700
|
+
if (!forceRefreshToken) return token;
|
|
701
|
+
if (forcedRefreshPromise !== null) return await forcedRefreshPromise;
|
|
702
|
+
if (token !== null && Date.now() - lastForcedRefreshTime < FORCED_REFRESH_REUSE_MS) return token;
|
|
703
|
+
forcedRefreshPromise = (async () => {
|
|
704
|
+
try {
|
|
705
|
+
return await refreshAccessToken();
|
|
706
|
+
} finally {
|
|
707
|
+
forcedRefreshPromise = null;
|
|
708
|
+
}
|
|
709
|
+
})();
|
|
710
|
+
return await forcedRefreshPromise;
|
|
711
|
+
};
|
|
712
|
+
async function refreshAccessToken() {
|
|
713
|
+
const mutex = runtime.mutex;
|
|
714
|
+
const withMutex = mutex ? (key$1, callback) => mutex.withKey(key$1, callback) : localMutex;
|
|
715
|
+
if (proxy) {
|
|
716
|
+
const tokenBeforeRefresh = token;
|
|
717
|
+
return await withMutex(`__convexAuthProxyRefresh_${escapedNamespace}`, async () => {
|
|
718
|
+
if (token !== tokenBeforeRefresh) return token;
|
|
719
|
+
const epochAtRefreshStart = authEpoch;
|
|
720
|
+
try {
|
|
721
|
+
const result = await retryWithJitteredBackoff(() => proxyFetch({
|
|
722
|
+
action: "auth:signIn",
|
|
723
|
+
args: { refreshToken: true }
|
|
724
|
+
}), isRetriableProxyRefreshError);
|
|
725
|
+
if (destroyed || authEpoch !== epochAtRefreshStart) return token;
|
|
726
|
+
if (isSignedInResult(result) && result.session) {
|
|
727
|
+
await setToken({
|
|
728
|
+
shouldStore: false,
|
|
729
|
+
tokens: { token: result.session.token },
|
|
730
|
+
resyncConvexAuth: false
|
|
731
|
+
});
|
|
732
|
+
lastForcedRefreshTime = Date.now();
|
|
733
|
+
} else await setToken({
|
|
734
|
+
shouldStore: false,
|
|
735
|
+
tokens: null,
|
|
736
|
+
resyncConvexAuth: false
|
|
737
|
+
});
|
|
738
|
+
} catch (error) {
|
|
739
|
+
logMessage("convex-auth/client", LOG_LEVELS.ERROR, ["[convex-auth] Proxy refresh failed:", error]);
|
|
740
|
+
if (destroyed || authEpoch !== epochAtRefreshStart) return token;
|
|
741
|
+
if (isAuthRefreshRejection(error)) await setToken({
|
|
742
|
+
shouldStore: false,
|
|
743
|
+
tokens: null,
|
|
744
|
+
resyncConvexAuth: false
|
|
745
|
+
});
|
|
746
|
+
else if (token === null) finalizeLoadingState();
|
|
747
|
+
}
|
|
748
|
+
return token;
|
|
749
|
+
});
|
|
750
|
+
}
|
|
751
|
+
const tokenBeforeLockAcquisition = token;
|
|
752
|
+
return await withMutex(key(REFRESH_TOKEN_STORAGE_KEY), async () => {
|
|
753
|
+
const tokenAfterLockAcquisition = token;
|
|
754
|
+
if (tokenAfterLockAcquisition !== tokenBeforeLockAcquisition) return tokenAfterLockAcquisition;
|
|
755
|
+
const refreshToken = await storageGet(REFRESH_TOKEN_STORAGE_KEY) ?? null;
|
|
756
|
+
if (!refreshToken) {
|
|
757
|
+
await setToken({
|
|
758
|
+
shouldStore: true,
|
|
759
|
+
tokens: null,
|
|
760
|
+
resyncConvexAuth: false
|
|
761
|
+
});
|
|
762
|
+
return null;
|
|
763
|
+
}
|
|
764
|
+
const epochAtRefreshStart = authEpoch;
|
|
765
|
+
try {
|
|
766
|
+
const result = await verifyCode({ refreshToken });
|
|
767
|
+
if (destroyed || authEpoch !== epochAtRefreshStart) return token;
|
|
768
|
+
if (result.kind !== "signedIn") throw new Error("Code exchange did not return tokens.");
|
|
769
|
+
await setToken({
|
|
770
|
+
shouldStore: true,
|
|
771
|
+
tokens: result.session,
|
|
772
|
+
resyncConvexAuth: false
|
|
773
|
+
});
|
|
774
|
+
lastForcedRefreshTime = Date.now();
|
|
775
|
+
} catch (error) {
|
|
776
|
+
if (destroyed || authEpoch !== epochAtRefreshStart) return token;
|
|
777
|
+
if (isAuthRefreshRejection(error)) {
|
|
778
|
+
await setToken({
|
|
779
|
+
shouldStore: true,
|
|
780
|
+
tokens: null,
|
|
781
|
+
resyncConvexAuth: false
|
|
782
|
+
});
|
|
783
|
+
return null;
|
|
784
|
+
}
|
|
785
|
+
logMessage("convex-auth/client", LOG_LEVELS.ERROR, ["[convex-auth] Token refresh failed transiently, keeping session:", error]);
|
|
786
|
+
}
|
|
787
|
+
return token;
|
|
788
|
+
});
|
|
789
|
+
}
|
|
790
|
+
const resolveOAuthInput = (input) => {
|
|
791
|
+
if (input instanceof URL) return {
|
|
792
|
+
code: input.searchParams.get("code"),
|
|
793
|
+
cleanupUrl: input.searchParams.has("code") ? (() => {
|
|
794
|
+
const next = new URL(input.toString());
|
|
795
|
+
next.searchParams.delete("code");
|
|
796
|
+
next.searchParams.delete("state");
|
|
797
|
+
return next;
|
|
798
|
+
})() : null
|
|
799
|
+
};
|
|
800
|
+
if (typeof input === "object") return {
|
|
801
|
+
code: input.code,
|
|
802
|
+
cleanupUrl: null
|
|
803
|
+
};
|
|
804
|
+
try {
|
|
805
|
+
const url$1 = new URL(input);
|
|
806
|
+
return {
|
|
807
|
+
code: url$1.searchParams.get("code"),
|
|
808
|
+
cleanupUrl: url$1.searchParams.has("code") ? (() => {
|
|
809
|
+
const next = new URL(url$1.toString());
|
|
810
|
+
next.searchParams.delete("code");
|
|
811
|
+
next.searchParams.delete("state");
|
|
812
|
+
return next;
|
|
813
|
+
})() : null
|
|
814
|
+
};
|
|
815
|
+
} catch {
|
|
816
|
+
return {
|
|
817
|
+
code: input,
|
|
818
|
+
cleanupUrl: null
|
|
819
|
+
};
|
|
820
|
+
}
|
|
821
|
+
};
|
|
822
|
+
const replaceWithCleanupUrl = async (cleanupUrl) => {
|
|
823
|
+
if (!runtime.location) return;
|
|
824
|
+
const current = runtime.location.get();
|
|
825
|
+
const relativeUrl = current !== null && cleanupUrl.origin === current.origin ? `${cleanupUrl.pathname}${cleanupUrl.search}${cleanupUrl.hash}` : cleanupUrl.toString();
|
|
826
|
+
await runtime.location.replace(relativeUrl);
|
|
827
|
+
};
|
|
828
|
+
const completeOAuth = async (input) => {
|
|
829
|
+
const { code, cleanupUrl } = resolveOAuthInput(input);
|
|
830
|
+
if (!code) return { handled: false };
|
|
831
|
+
if ((await signIn(void 0, { code })).kind !== "signedIn") throw new Error("OAuth code exchange did not complete sign-in.");
|
|
832
|
+
if (cleanupUrl) await replaceWithCleanupUrl(cleanupUrl);
|
|
833
|
+
return {
|
|
834
|
+
handled: true,
|
|
835
|
+
cleanupUrl
|
|
836
|
+
};
|
|
837
|
+
};
|
|
838
|
+
const hydrateFromStorage = async () => {
|
|
839
|
+
const storedToken = await storageGet(JWT_STORAGE_KEY) ?? null;
|
|
840
|
+
await setToken({
|
|
841
|
+
shouldStore: false,
|
|
842
|
+
tokens: storedToken === null ? null : { token: storedToken },
|
|
843
|
+
resyncConvexAuth: storedToken !== null && storedToken !== token
|
|
844
|
+
});
|
|
845
|
+
};
|
|
846
|
+
const initialize = async () => {
|
|
847
|
+
if (destroyed) return;
|
|
848
|
+
if (initializePromise !== null) return await initializePromise;
|
|
849
|
+
initializePromise = (async () => {
|
|
850
|
+
if (proxy) {
|
|
851
|
+
if (!tokenProvided && !hasServerToken && runtime.environment !== "server") try {
|
|
852
|
+
await fetchAccessToken({ forceRefreshToken: true });
|
|
853
|
+
} catch (error) {
|
|
854
|
+
logMessage("convex-auth/client", LOG_LEVELS.ERROR, ["[convex-auth] Proxy token refresh failed:", error]);
|
|
855
|
+
}
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
if (!tokenProvided && !hasServerToken) try {
|
|
859
|
+
await hydrateFromStorage();
|
|
860
|
+
} catch {
|
|
861
|
+
try {
|
|
862
|
+
await setToken({
|
|
863
|
+
shouldStore: false,
|
|
864
|
+
tokens: null,
|
|
865
|
+
resyncConvexAuth: false
|
|
866
|
+
});
|
|
867
|
+
} catch {}
|
|
868
|
+
}
|
|
869
|
+
try {
|
|
870
|
+
const loc = runtime.location?.get() ?? null;
|
|
871
|
+
if (loc && loc.searchParams.has("code") && loc.searchParams.has("state")) await completeOAuth(loc);
|
|
872
|
+
} catch (error) {
|
|
873
|
+
logMessage("convex-auth/client", LOG_LEVELS.ERROR, ["[convex-auth] OAuth completion failed:", error]);
|
|
874
|
+
}
|
|
875
|
+
})();
|
|
876
|
+
try {
|
|
877
|
+
await initializePromise;
|
|
878
|
+
} finally {
|
|
879
|
+
initializePromise = Promise.resolve();
|
|
880
|
+
}
|
|
881
|
+
};
|
|
882
|
+
const subscribe = (handler) => {
|
|
883
|
+
let last = null;
|
|
884
|
+
const emit = () => {
|
|
885
|
+
const state = publicSnapshot;
|
|
886
|
+
if (last !== null && authStatesEqual(last, state)) return;
|
|
887
|
+
last = state;
|
|
888
|
+
handler(state);
|
|
889
|
+
};
|
|
890
|
+
emit();
|
|
891
|
+
subscribers.add(emit);
|
|
892
|
+
return () => {
|
|
893
|
+
subscribers.delete(emit);
|
|
894
|
+
};
|
|
895
|
+
};
|
|
896
|
+
if (!proxy && runtime.sync) {
|
|
897
|
+
const logStorageSyncError = (error) => {
|
|
898
|
+
logMessage("convex-auth/client", LOG_LEVELS.ERROR, ["[convex-auth] Storage event handler failed:", error]);
|
|
899
|
+
};
|
|
900
|
+
disposeStorageListener = runtime.sync.subscribe(key(JWT_STORAGE_KEY), (value) => {
|
|
901
|
+
if (destroyed) return;
|
|
902
|
+
if (value === token) return;
|
|
903
|
+
if (value === null) {
|
|
904
|
+
setToken({
|
|
905
|
+
shouldStore: false,
|
|
906
|
+
tokens: null
|
|
907
|
+
}).catch(logStorageSyncError);
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
const incoming = value;
|
|
911
|
+
if (authConfirmed && token !== null) {
|
|
912
|
+
const currentSubject = decodeJwtSubject(token);
|
|
913
|
+
const incomingSubject = decodeJwtSubject(incoming);
|
|
914
|
+
if (currentSubject !== null && incomingSubject === currentSubject) setToken({
|
|
915
|
+
shouldStore: false,
|
|
916
|
+
tokens: { token: incoming },
|
|
917
|
+
resyncConvexAuth: false
|
|
918
|
+
}).catch(logStorageSyncError);
|
|
919
|
+
return;
|
|
920
|
+
}
|
|
921
|
+
setToken({
|
|
922
|
+
shouldStore: false,
|
|
923
|
+
tokens: { token: incoming }
|
|
924
|
+
}).catch(logStorageSyncError);
|
|
925
|
+
}) ?? null;
|
|
926
|
+
}
|
|
927
|
+
bindConvexAuth();
|
|
928
|
+
initialize().catch((error) => {
|
|
929
|
+
logMessage("convex-auth/client", LOG_LEVELS.ERROR, ["[convex-auth] Client initialization failed:", error]);
|
|
930
|
+
finalizeLoadingState();
|
|
931
|
+
});
|
|
932
|
+
return {
|
|
933
|
+
initialize,
|
|
934
|
+
param,
|
|
935
|
+
get invite() {
|
|
936
|
+
const pendingInvite = getPendingInvite();
|
|
937
|
+
if (!pendingInvite) return null;
|
|
938
|
+
return {
|
|
939
|
+
token: pendingInvite.token,
|
|
940
|
+
email: pendingInvite.email,
|
|
941
|
+
accept: acceptInvite
|
|
942
|
+
};
|
|
943
|
+
},
|
|
944
|
+
completeOAuth,
|
|
945
|
+
signIn,
|
|
946
|
+
signOut,
|
|
947
|
+
subscribe,
|
|
948
|
+
getSnapshot: () => publicSnapshot,
|
|
949
|
+
totp: adapters.totp ?? createTotpClient({
|
|
950
|
+
proxy,
|
|
951
|
+
convex,
|
|
952
|
+
requireApiRefs,
|
|
953
|
+
proxyFetch,
|
|
954
|
+
setTokenAndMaybeWait
|
|
955
|
+
}),
|
|
956
|
+
device: adapters.device ?? createDeviceClient({
|
|
957
|
+
proxy,
|
|
958
|
+
convex,
|
|
959
|
+
requireApiRefs,
|
|
960
|
+
proxyFetch,
|
|
961
|
+
setTokenAndMaybeWait
|
|
962
|
+
}),
|
|
963
|
+
destroy: () => {
|
|
964
|
+
destroyed = true;
|
|
965
|
+
clearDeauthGrace();
|
|
966
|
+
rejectAllHandshakeWaiters(createHandshakeError("AUTH_HANDSHAKE_REJECTED", { reason: "destroyed" }));
|
|
967
|
+
disposeStorageListener?.();
|
|
968
|
+
subscribers.clear();
|
|
969
|
+
},
|
|
970
|
+
...webauthnAdapter ? { webauthn: webauthnAdapter } : {}
|
|
971
|
+
};
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
//#endregion
|
|
975
|
+
export { client, resolveUrl };
|
|
976
|
+
//# sourceMappingURL=index.js.map
|