@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,431 @@
|
|
|
1
|
+
import { ErrorCode } from "../shared/codes.js";
|
|
2
|
+
import { vGroupConnectionPolicy, vGroupDoc, vPaginated } from "./model.js";
|
|
3
|
+
import schema_default from "./schema.js";
|
|
4
|
+
import { internal } from "./_generated/api.js";
|
|
5
|
+
import { internalMutation, mutation, query } from "./_generated/server.js";
|
|
6
|
+
import { ConvexError, v } from "convex/values";
|
|
7
|
+
import { paginationOptsValidator } from "convex/server";
|
|
8
|
+
import { stream } from "convex-helpers/server/stream";
|
|
9
|
+
import { paginator } from "convex-helpers/server/pagination";
|
|
10
|
+
|
|
11
|
+
//#region src/component/group.ts
|
|
12
|
+
/**
|
|
13
|
+
* `component.group.*` — hierarchical groups (the group entity root;
|
|
14
|
+
* members/invites are sub-resources under `group.member` / `group.invite`).
|
|
15
|
+
*
|
|
16
|
+
* `ancestors` is a kept domain read (hierarchy walk).
|
|
17
|
+
*
|
|
18
|
+
* @module
|
|
19
|
+
*/
|
|
20
|
+
/**
|
|
21
|
+
* Read a group by `id`, or batch-read by `ids` (result aligned to input
|
|
22
|
+
* order, with `null` for missing ids and duplicates preserved).
|
|
23
|
+
*/
|
|
24
|
+
const get = query({
|
|
25
|
+
args: {
|
|
26
|
+
id: v.optional(v.id("Group")),
|
|
27
|
+
ids: v.optional(v.array(v.id("Group")))
|
|
28
|
+
},
|
|
29
|
+
returns: v.union(vGroupDoc, v.null(), v.array(v.union(vGroupDoc, v.null()))),
|
|
30
|
+
handler: async (ctx, args) => {
|
|
31
|
+
if (args.ids !== void 0) {
|
|
32
|
+
if (args.ids.length === 0) return [];
|
|
33
|
+
const unique = Array.from(new Set(args.ids));
|
|
34
|
+
const docs = await Promise.all(unique.map((id) => ctx.db.get("Group", id)));
|
|
35
|
+
const byId = new Map(unique.map((id, i) => [id, docs[i] ?? null]));
|
|
36
|
+
return args.ids.map((id) => byId.get(id) ?? null);
|
|
37
|
+
}
|
|
38
|
+
if (args.id === void 0) return null;
|
|
39
|
+
return await ctx.db.get("Group", args.id);
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
/**
|
|
43
|
+
* Walk the parent chain from a group up to the root, returning the ordered
|
|
44
|
+
* ancestor docs. Flags `cycleDetected` and `maxDepthReached` so callers can
|
|
45
|
+
* tell a truncated walk from a complete one; `includeSelf` prepends the
|
|
46
|
+
* starting group.
|
|
47
|
+
*/
|
|
48
|
+
const ancestors = query({
|
|
49
|
+
args: {
|
|
50
|
+
id: v.id("Group"),
|
|
51
|
+
maxDepth: v.optional(v.number()),
|
|
52
|
+
includeSelf: v.optional(v.boolean())
|
|
53
|
+
},
|
|
54
|
+
returns: v.object({
|
|
55
|
+
ancestors: v.array(vGroupDoc),
|
|
56
|
+
cycleDetected: v.boolean(),
|
|
57
|
+
maxDepthReached: v.boolean()
|
|
58
|
+
}),
|
|
59
|
+
handler: async (ctx, { id: groupId, maxDepth, includeSelf }) => {
|
|
60
|
+
const limit = Math.max(0, Math.floor(maxDepth ?? 32));
|
|
61
|
+
const visited = /* @__PURE__ */ new Set();
|
|
62
|
+
const ancestors = [];
|
|
63
|
+
let cycleDetected = false;
|
|
64
|
+
let maxDepthReached = false;
|
|
65
|
+
let current = groupId;
|
|
66
|
+
let depth = 0;
|
|
67
|
+
let first = true;
|
|
68
|
+
while (current !== void 0) {
|
|
69
|
+
if (depth > limit) {
|
|
70
|
+
maxDepthReached = true;
|
|
71
|
+
break;
|
|
72
|
+
}
|
|
73
|
+
if (visited.has(current)) {
|
|
74
|
+
cycleDetected = true;
|
|
75
|
+
break;
|
|
76
|
+
}
|
|
77
|
+
visited.add(current);
|
|
78
|
+
const doc = await ctx.db.get("Group", current);
|
|
79
|
+
if (doc === null) break;
|
|
80
|
+
if (first) {
|
|
81
|
+
first = false;
|
|
82
|
+
if (includeSelf === true) ancestors.push(doc);
|
|
83
|
+
} else ancestors.push(doc);
|
|
84
|
+
current = doc.parentGroupId;
|
|
85
|
+
depth += 1;
|
|
86
|
+
}
|
|
87
|
+
return {
|
|
88
|
+
ancestors,
|
|
89
|
+
cycleDetected,
|
|
90
|
+
maxDepthReached
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
});
|
|
94
|
+
/** List groups, paginated, optionally filtered by `where` and sorted via `orderBy`/`order`. */
|
|
95
|
+
const list = query({
|
|
96
|
+
args: {
|
|
97
|
+
where: v.optional(v.object({
|
|
98
|
+
slug: v.optional(v.string()),
|
|
99
|
+
type: v.optional(v.string()),
|
|
100
|
+
parentGroupId: v.optional(v.id("Group")),
|
|
101
|
+
name: v.optional(v.string()),
|
|
102
|
+
isRoot: v.optional(v.boolean())
|
|
103
|
+
})),
|
|
104
|
+
paginationOpts: paginationOptsValidator,
|
|
105
|
+
orderBy: v.optional(v.union(v.literal("_creationTime"), v.literal("name"), v.literal("slug"), v.literal("type"))),
|
|
106
|
+
order: v.optional(v.union(v.literal("asc"), v.literal("desc")))
|
|
107
|
+
},
|
|
108
|
+
returns: vPaginated(vGroupDoc),
|
|
109
|
+
handler: async (ctx, args) => {
|
|
110
|
+
const where = args.where ?? {};
|
|
111
|
+
const order = args.order ?? "desc";
|
|
112
|
+
const orderBy = args.orderBy ?? "_creationTime";
|
|
113
|
+
const base = stream(ctx.db, schema_default).query("Group");
|
|
114
|
+
let q;
|
|
115
|
+
if (orderBy === "name") q = where.parentGroupId !== void 0 ? where.name !== void 0 ? base.withIndex("parent_group_id_name", (idx) => idx.eq("parentGroupId", where.parentGroupId).eq("name", where.name)) : base.withIndex("parent_group_id_name", (idx) => idx.eq("parentGroupId", where.parentGroupId)) : base.withIndex("name");
|
|
116
|
+
else if (orderBy === "slug") q = where.parentGroupId !== void 0 ? where.slug !== void 0 ? base.withIndex("parent_group_id_slug", (idx) => idx.eq("parentGroupId", where.parentGroupId).eq("slug", where.slug)) : base.withIndex("parent_group_id_slug", (idx) => idx.eq("parentGroupId", where.parentGroupId)) : where.slug !== void 0 ? base.withIndex("slug", (idx) => idx.eq("slug", where.slug)) : base.withIndex("slug");
|
|
117
|
+
else if (orderBy === "type") q = where.parentGroupId !== void 0 ? where.type !== void 0 ? base.withIndex("parent_group_id_type", (idx) => idx.eq("parentGroupId", where.parentGroupId).eq("type", where.type)) : base.withIndex("parent_group_id_type", (idx) => idx.eq("parentGroupId", where.parentGroupId)) : where.type !== void 0 ? base.withIndex("type", (idx) => idx.eq("type", where.type)) : base.withIndex("type");
|
|
118
|
+
else if (where.type !== void 0 && where.parentGroupId !== void 0) q = base.withIndex("type_parent_group_id", (idx) => idx.eq("type", where.type).eq("parentGroupId", where.parentGroupId));
|
|
119
|
+
else if (where.slug !== void 0) q = base.withIndex("slug", (idx) => idx.eq("slug", where.slug));
|
|
120
|
+
else if (where.type !== void 0) q = base.withIndex("type", (idx) => idx.eq("type", where.type));
|
|
121
|
+
else if (where.parentGroupId !== void 0) q = base.withIndex("parent_group_id", (idx) => idx.eq("parentGroupId", where.parentGroupId));
|
|
122
|
+
else if (where.isRoot !== void 0) q = base.withIndex("is_root", (idx) => idx.eq("isRoot", where.isRoot));
|
|
123
|
+
else q = base;
|
|
124
|
+
return await q.order(order).filterWith(async (d) => (where.slug === void 0 || d.slug === where.slug) && (where.type === void 0 || d.type === where.type) && (where.parentGroupId === void 0 || d.parentGroupId === where.parentGroupId) && (where.name === void 0 || d.name === where.name) && (where.isRoot === void 0 || d.isRoot === where.isRoot)).paginate(args.paginationOpts);
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
/**
|
|
128
|
+
* Insert a new group. A group with no `parentGroupId` is a root and is
|
|
129
|
+
* back-patched to point `rootGroupId` at itself; otherwise it inherits the
|
|
130
|
+
* parent's `rootGroupId`.
|
|
131
|
+
*/
|
|
132
|
+
const create = mutation({
|
|
133
|
+
args: {
|
|
134
|
+
name: v.string(),
|
|
135
|
+
slug: v.optional(v.string()),
|
|
136
|
+
type: v.optional(v.string()),
|
|
137
|
+
parentGroupId: v.optional(v.id("Group")),
|
|
138
|
+
extend: v.optional(v.any())
|
|
139
|
+
},
|
|
140
|
+
returns: v.id("Group"),
|
|
141
|
+
handler: async (ctx, args) => {
|
|
142
|
+
const isRoot = !args.parentGroupId;
|
|
143
|
+
let rootGroupId;
|
|
144
|
+
if (!isRoot && args.parentGroupId) {
|
|
145
|
+
await assertGroupCanAcceptChild(ctx, args.parentGroupId);
|
|
146
|
+
rootGroupId = (await ctx.db.get("Group", args.parentGroupId))?.rootGroupId ?? args.parentGroupId;
|
|
147
|
+
}
|
|
148
|
+
const groupId = await ctx.db.insert("Group", {
|
|
149
|
+
...args,
|
|
150
|
+
isRoot,
|
|
151
|
+
rootGroupId: isRoot ? void 0 : rootGroupId
|
|
152
|
+
});
|
|
153
|
+
if (isRoot) await ctx.db.patch("Group", groupId, { rootGroupId: groupId });
|
|
154
|
+
return groupId;
|
|
155
|
+
}
|
|
156
|
+
});
|
|
157
|
+
/** Small subtrees keep the original synchronous, all-or-nothing behavior. */
|
|
158
|
+
const INLINE_GROUP_LIMIT = 48;
|
|
159
|
+
const INLINE_RELATION_LIMIT = 384;
|
|
160
|
+
/** Durable jobs deliberately use small pages to leave transaction headroom. */
|
|
161
|
+
const PLAN_ITEMS_PER_RUN = 4;
|
|
162
|
+
const CHILDREN_PER_PAGE = 32;
|
|
163
|
+
const APPLY_ITEMS_PER_RUN = 16;
|
|
164
|
+
const RELATIONS_PER_RUN = 64;
|
|
165
|
+
const CLEANUP_ITEMS_PER_RUN = 128;
|
|
166
|
+
/**
|
|
167
|
+
* Collect a subtree only while it is known to fit comfortably in one
|
|
168
|
+
* transaction. Returning `null` is not an error: it selects the durable path,
|
|
169
|
+
* and no hierarchy row has been changed yet.
|
|
170
|
+
*/
|
|
171
|
+
async function collectInlineSubtree(ctx, groupId, includeRelations) {
|
|
172
|
+
const queue = [groupId];
|
|
173
|
+
const seen = /* @__PURE__ */ new Set();
|
|
174
|
+
const groups = [];
|
|
175
|
+
const members = [];
|
|
176
|
+
const invites = [];
|
|
177
|
+
for (let head = 0; head < queue.length; head += 1) {
|
|
178
|
+
const id = queue[head];
|
|
179
|
+
if (seen.has(id)) continue;
|
|
180
|
+
seen.add(id);
|
|
181
|
+
if (seen.size > INLINE_GROUP_LIMIT) return null;
|
|
182
|
+
const group = await ctx.db.get("Group", id);
|
|
183
|
+
if (group === null) continue;
|
|
184
|
+
groups.push(group);
|
|
185
|
+
const children = await ctx.db.query("Group").withIndex("parent_group_id", (q) => q.eq("parentGroupId", id)).take(INLINE_GROUP_LIMIT + 1);
|
|
186
|
+
if (children.length > INLINE_GROUP_LIMIT) return null;
|
|
187
|
+
queue.push(...children.map((child) => child._id));
|
|
188
|
+
if (queue.length > INLINE_GROUP_LIMIT * 2) return null;
|
|
189
|
+
if (!includeRelations) continue;
|
|
190
|
+
const groupMembers = await ctx.db.query("GroupMember").withIndex("group_id", (q) => q.eq("groupId", id)).take(INLINE_RELATION_LIMIT + 1);
|
|
191
|
+
const groupInvites = await ctx.db.query("GroupInvite").withIndex("group_id", (q) => q.eq("groupId", id)).take(INLINE_RELATION_LIMIT + 1);
|
|
192
|
+
members.push(...groupMembers);
|
|
193
|
+
invites.push(...groupInvites);
|
|
194
|
+
if (members.length + invites.length > INLINE_RELATION_LIMIT) return null;
|
|
195
|
+
}
|
|
196
|
+
return {
|
|
197
|
+
groups,
|
|
198
|
+
members,
|
|
199
|
+
invites
|
|
200
|
+
};
|
|
201
|
+
}
|
|
202
|
+
async function scheduleHierarchyOperation(ctx, operationId) {
|
|
203
|
+
await ctx.scheduler.runAfter(0, internal.group.processGroupHierarchy, { operationId });
|
|
204
|
+
}
|
|
205
|
+
async function createHierarchyOperation(ctx, args) {
|
|
206
|
+
const operationId = await ctx.db.insert("GroupHierarchyOperation", {
|
|
207
|
+
...args,
|
|
208
|
+
phase: "planning"
|
|
209
|
+
});
|
|
210
|
+
await ctx.db.insert("GroupHierarchyWork", {
|
|
211
|
+
operationId,
|
|
212
|
+
kind: args.kind,
|
|
213
|
+
groupId: args.groupId,
|
|
214
|
+
depth: 0,
|
|
215
|
+
planned: false,
|
|
216
|
+
applied: false
|
|
217
|
+
});
|
|
218
|
+
await scheduleHierarchyOperation(ctx, operationId);
|
|
219
|
+
return operationId;
|
|
220
|
+
}
|
|
221
|
+
async function activeRemovalForGroup(ctx, groupId) {
|
|
222
|
+
const work = await ctx.db.query("GroupHierarchyWork").withIndex("group_id_kind", (q) => q.eq("groupId", groupId).eq("kind", "remove")).take(1);
|
|
223
|
+
for (const item of work) {
|
|
224
|
+
const operation = await ctx.db.get("GroupHierarchyOperation", item.operationId);
|
|
225
|
+
if (operation?.kind === "remove" && operation.phase !== "cleaning") return operation;
|
|
226
|
+
}
|
|
227
|
+
return null;
|
|
228
|
+
}
|
|
229
|
+
async function activeHierarchyOperationForGroup(ctx, groupId) {
|
|
230
|
+
const work = await ctx.db.query("GroupHierarchyWork").withIndex("group_id", (q) => q.eq("groupId", groupId)).first();
|
|
231
|
+
return work === null ? null : await ctx.db.get("GroupHierarchyOperation", work.operationId);
|
|
232
|
+
}
|
|
233
|
+
async function assertGroupNotBeingRemoved(ctx, groupId) {
|
|
234
|
+
if (await activeRemovalForGroup(ctx, groupId) !== null) throw new ConvexError({
|
|
235
|
+
code: ErrorCode.INVALID_PARAMETERS,
|
|
236
|
+
message: `Group ${groupId} is being removed and cannot be changed.`
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
async function assertGroupCanAcceptChild(ctx, groupId) {
|
|
240
|
+
if (await activeHierarchyOperationForGroup(ctx, groupId) !== null) throw new ConvexError({
|
|
241
|
+
code: ErrorCode.INVALID_PARAMETERS,
|
|
242
|
+
message: `Group ${groupId} has a hierarchy operation in progress and cannot accept a child.`
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
async function planHierarchyOperation(ctx, operation) {
|
|
246
|
+
const items = await ctx.db.query("GroupHierarchyWork").withIndex("operation_id_planned", (q) => q.eq("operationId", operation._id).eq("planned", false)).take(PLAN_ITEMS_PER_RUN);
|
|
247
|
+
for (const item of items) {
|
|
248
|
+
const page = await paginator(ctx.db, schema_default).query("Group").withIndex("parent_group_id", (q) => q.eq("parentGroupId", item.groupId)).paginate({
|
|
249
|
+
numItems: CHILDREN_PER_PAGE,
|
|
250
|
+
cursor: item.scanCursor ?? null
|
|
251
|
+
});
|
|
252
|
+
for (const child of page.page) if (await ctx.db.query("GroupHierarchyWork").withIndex("operation_id_group_id", (q) => q.eq("operationId", operation._id).eq("groupId", child._id)).unique() === null) await ctx.db.insert("GroupHierarchyWork", {
|
|
253
|
+
operationId: operation._id,
|
|
254
|
+
kind: operation.kind,
|
|
255
|
+
groupId: child._id,
|
|
256
|
+
parentWorkId: item._id,
|
|
257
|
+
expectedParentGroupId: item.groupId,
|
|
258
|
+
depth: item.depth + 1,
|
|
259
|
+
planned: false,
|
|
260
|
+
applied: false
|
|
261
|
+
});
|
|
262
|
+
await ctx.db.patch("GroupHierarchyWork", item._id, {
|
|
263
|
+
planned: page.isDone,
|
|
264
|
+
scanCursor: page.isDone ? void 0 : page.continueCursor
|
|
265
|
+
});
|
|
266
|
+
}
|
|
267
|
+
if (await ctx.db.query("GroupHierarchyWork").withIndex("operation_id_planned", (q) => q.eq("operationId", operation._id).eq("planned", false)).first() === null) await ctx.db.patch("GroupHierarchyOperation", operation._id, { phase: "applying" });
|
|
268
|
+
await scheduleHierarchyOperation(ctx, operation._id);
|
|
269
|
+
}
|
|
270
|
+
async function applyRemoval(ctx, operation) {
|
|
271
|
+
const items = await ctx.db.query("GroupHierarchyWork").withIndex("operation_id_applied_depth", (q) => q.eq("operationId", operation._id).eq("applied", false)).order("desc").take(APPLY_ITEMS_PER_RUN);
|
|
272
|
+
for (const item of items) {
|
|
273
|
+
if (await ctx.db.get("Group", item.groupId) === null) {
|
|
274
|
+
await ctx.db.patch("GroupHierarchyWork", item._id, { applied: true });
|
|
275
|
+
continue;
|
|
276
|
+
}
|
|
277
|
+
const children = await ctx.db.query("Group").withIndex("parent_group_id", (q) => q.eq("parentGroupId", item.groupId)).take(2);
|
|
278
|
+
let hasBlockingChild = false;
|
|
279
|
+
for (const child of children) {
|
|
280
|
+
const childWork = await ctx.db.query("GroupHierarchyWork").withIndex("operation_id_group_id", (q) => q.eq("operationId", operation._id).eq("groupId", child._id)).unique();
|
|
281
|
+
if (childWork === null || childWork.depth > item.depth) {
|
|
282
|
+
hasBlockingChild = true;
|
|
283
|
+
break;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
if (hasBlockingChild) continue;
|
|
287
|
+
const members = await ctx.db.query("GroupMember").withIndex("group_id", (q) => q.eq("groupId", item.groupId)).take(RELATIONS_PER_RUN);
|
|
288
|
+
const invites = await ctx.db.query("GroupInvite").withIndex("group_id", (q) => q.eq("groupId", item.groupId)).take(RELATIONS_PER_RUN);
|
|
289
|
+
for (const member of members) await ctx.db.delete("GroupMember", member._id);
|
|
290
|
+
for (const invite of invites) await ctx.db.delete("GroupInvite", invite._id);
|
|
291
|
+
if (members.length === RELATIONS_PER_RUN || invites.length === RELATIONS_PER_RUN) continue;
|
|
292
|
+
await ctx.db.delete("Group", item.groupId);
|
|
293
|
+
await ctx.db.patch("GroupHierarchyWork", item._id, { applied: true });
|
|
294
|
+
}
|
|
295
|
+
if (await ctx.db.query("GroupHierarchyWork").withIndex("operation_id_applied_depth", (q) => q.eq("operationId", operation._id).eq("applied", false)).first() === null) await ctx.db.patch("GroupHierarchyOperation", operation._id, { phase: "cleaning" });
|
|
296
|
+
await scheduleHierarchyOperation(ctx, operation._id);
|
|
297
|
+
}
|
|
298
|
+
async function applyRestamp(ctx, operation) {
|
|
299
|
+
const newRootGroupId = operation.newRootGroupId;
|
|
300
|
+
if (newRootGroupId === void 0) {
|
|
301
|
+
await ctx.db.patch("GroupHierarchyOperation", operation._id, { phase: "cleaning" });
|
|
302
|
+
await scheduleHierarchyOperation(ctx, operation._id);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
const items = await ctx.db.query("GroupHierarchyWork").withIndex("operation_id_applied_depth", (q) => q.eq("operationId", operation._id).eq("applied", false)).order("asc").take(APPLY_ITEMS_PER_RUN);
|
|
306
|
+
for (const item of items) {
|
|
307
|
+
const group = await ctx.db.get("Group", item.groupId);
|
|
308
|
+
let eligible = false;
|
|
309
|
+
if (group !== null) {
|
|
310
|
+
if (item.parentWorkId === void 0) eligible = group.parentGroupId === operation.expectedParentGroupId && group.rootGroupId === newRootGroupId;
|
|
311
|
+
else eligible = (await ctx.db.get("GroupHierarchyWork", item.parentWorkId))?.eligible === true && group.parentGroupId === item.expectedParentGroupId;
|
|
312
|
+
if (eligible && group.rootGroupId !== newRootGroupId) await ctx.db.patch("Group", group._id, { rootGroupId: newRootGroupId });
|
|
313
|
+
}
|
|
314
|
+
await ctx.db.patch("GroupHierarchyWork", item._id, {
|
|
315
|
+
eligible,
|
|
316
|
+
applied: true
|
|
317
|
+
});
|
|
318
|
+
}
|
|
319
|
+
if (await ctx.db.query("GroupHierarchyWork").withIndex("operation_id_applied_depth", (q) => q.eq("operationId", operation._id).eq("applied", false)).first() === null) await ctx.db.patch("GroupHierarchyOperation", operation._id, { phase: "cleaning" });
|
|
320
|
+
await scheduleHierarchyOperation(ctx, operation._id);
|
|
321
|
+
}
|
|
322
|
+
async function cleanupHierarchyOperation(ctx, operation) {
|
|
323
|
+
const work = await ctx.db.query("GroupHierarchyWork").withIndex("operation_id_group_id", (q) => q.eq("operationId", operation._id)).take(CLEANUP_ITEMS_PER_RUN);
|
|
324
|
+
for (const item of work) await ctx.db.delete("GroupHierarchyWork", item._id);
|
|
325
|
+
if (work.length === 0) await ctx.db.delete("GroupHierarchyOperation", operation._id);
|
|
326
|
+
else await scheduleHierarchyOperation(ctx, operation._id);
|
|
327
|
+
}
|
|
328
|
+
/** Durable, idempotent continuation for large hierarchy operations. */
|
|
329
|
+
const processGroupHierarchy = internalMutation({
|
|
330
|
+
args: { operationId: v.id("GroupHierarchyOperation") },
|
|
331
|
+
returns: v.null(),
|
|
332
|
+
handler: async (ctx, { operationId }) => {
|
|
333
|
+
const operation = await ctx.db.get("GroupHierarchyOperation", operationId);
|
|
334
|
+
if (operation === null) return null;
|
|
335
|
+
if (operation.phase === "planning") await planHierarchyOperation(ctx, operation);
|
|
336
|
+
else if (operation.phase === "applying" && operation.kind === "remove") await applyRemoval(ctx, operation);
|
|
337
|
+
else if (operation.phase === "applying") await applyRestamp(ctx, operation);
|
|
338
|
+
else await cleanupHierarchyOperation(ctx, operation);
|
|
339
|
+
return null;
|
|
340
|
+
}
|
|
341
|
+
});
|
|
342
|
+
/**
|
|
343
|
+
* Patch fields on a group. Re-parenting (a `patch.parentGroupId`) recomputes
|
|
344
|
+
* `isRoot`/`rootGroupId` and cascades the new `rootGroupId` to every
|
|
345
|
+
* descendant in the moved subtree. Small subtrees update atomically. Large
|
|
346
|
+
* subtrees use a durable planned work queue; stale continuations verify their
|
|
347
|
+
* target and parent lineage before writing, so a newer move always wins.
|
|
348
|
+
*/
|
|
349
|
+
const update = mutation({
|
|
350
|
+
args: {
|
|
351
|
+
id: v.id("Group"),
|
|
352
|
+
patch: v.object({
|
|
353
|
+
name: v.optional(v.string()),
|
|
354
|
+
slug: v.optional(v.string()),
|
|
355
|
+
type: v.optional(v.string()),
|
|
356
|
+
parentGroupId: v.optional(v.id("Group")),
|
|
357
|
+
rootGroupId: v.optional(v.id("Group")),
|
|
358
|
+
isRoot: v.optional(v.boolean()),
|
|
359
|
+
policy: v.optional(vGroupConnectionPolicy),
|
|
360
|
+
extend: v.optional(v.any())
|
|
361
|
+
})
|
|
362
|
+
},
|
|
363
|
+
returns: v.null(),
|
|
364
|
+
handler: async (ctx, { id: groupId, patch }) => {
|
|
365
|
+
await assertGroupNotBeingRemoved(ctx, groupId);
|
|
366
|
+
if (patch.parentGroupId !== void 0) {
|
|
367
|
+
await assertGroupCanAcceptChild(ctx, patch.parentGroupId);
|
|
368
|
+
const oldRootGroupId = (await ctx.db.get("Group", groupId))?.rootGroupId;
|
|
369
|
+
const newParentGroupId = patch.parentGroupId;
|
|
370
|
+
const newIsRoot = !newParentGroupId;
|
|
371
|
+
let newRootGroupId;
|
|
372
|
+
if (newIsRoot) newRootGroupId = groupId;
|
|
373
|
+
else newRootGroupId = (await ctx.db.get("Group", newParentGroupId))?.rootGroupId ?? newParentGroupId;
|
|
374
|
+
patch.isRoot = newIsRoot;
|
|
375
|
+
patch.rootGroupId = newRootGroupId;
|
|
376
|
+
const existingRestamp = await ctx.db.query("GroupHierarchyOperation").withIndex("group_id_kind_parent_root", (q) => q.eq("groupId", groupId).eq("kind", "restamp").eq("expectedParentGroupId", newParentGroupId).eq("newRootGroupId", newRootGroupId)).first();
|
|
377
|
+
if (existingRestamp !== null) await scheduleHierarchyOperation(ctx, existingRestamp._id);
|
|
378
|
+
else if (oldRootGroupId && oldRootGroupId !== newRootGroupId) {
|
|
379
|
+
const inline = await collectInlineSubtree(ctx, groupId, false);
|
|
380
|
+
if (inline === null) await createHierarchyOperation(ctx, {
|
|
381
|
+
groupId,
|
|
382
|
+
kind: "restamp",
|
|
383
|
+
newRootGroupId,
|
|
384
|
+
expectedParentGroupId: newParentGroupId
|
|
385
|
+
});
|
|
386
|
+
else for (const group of inline.groups) if (group._id !== groupId && group.rootGroupId !== newRootGroupId) await ctx.db.patch("Group", group._id, { rootGroupId: newRootGroupId });
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
await ctx.db.patch("Group", groupId, patch);
|
|
390
|
+
return null;
|
|
391
|
+
}
|
|
392
|
+
});
|
|
393
|
+
/**
|
|
394
|
+
* Delete a group and cascade-delete its descendant groups, memberships, and
|
|
395
|
+
* invites. Small subtrees delete atomically. Large subtrees are fully planned
|
|
396
|
+
* before application begins, then drained bottom-up through durable,
|
|
397
|
+
* idempotent continuations. Retrying `remove` resumes the same operation.
|
|
398
|
+
*/
|
|
399
|
+
const remove = mutation({
|
|
400
|
+
args: { id: v.id("Group") },
|
|
401
|
+
returns: v.null(),
|
|
402
|
+
handler: async (ctx, { id: groupId }) => {
|
|
403
|
+
const exactOperation = await ctx.db.query("GroupHierarchyOperation").withIndex("group_id_kind", (q) => q.eq("groupId", groupId).eq("kind", "remove")).first();
|
|
404
|
+
if (exactOperation !== null) {
|
|
405
|
+
await scheduleHierarchyOperation(ctx, exactOperation._id);
|
|
406
|
+
return null;
|
|
407
|
+
}
|
|
408
|
+
const ancestorOperation = await activeRemovalForGroup(ctx, groupId);
|
|
409
|
+
if (ancestorOperation !== null) {
|
|
410
|
+
await scheduleHierarchyOperation(ctx, ancestorOperation._id);
|
|
411
|
+
return null;
|
|
412
|
+
}
|
|
413
|
+
if (await ctx.db.get("Group", groupId) === null) return null;
|
|
414
|
+
const inline = await collectInlineSubtree(ctx, groupId, true);
|
|
415
|
+
if (inline === null) {
|
|
416
|
+
await createHierarchyOperation(ctx, {
|
|
417
|
+
groupId,
|
|
418
|
+
kind: "remove"
|
|
419
|
+
});
|
|
420
|
+
return null;
|
|
421
|
+
}
|
|
422
|
+
for (const member of inline.members) await ctx.db.delete("GroupMember", member._id);
|
|
423
|
+
for (const invite of inline.invites) await ctx.db.delete("GroupInvite", invite._id);
|
|
424
|
+
for (const group of [...inline.groups].reverse()) await ctx.db.delete("Group", group._id);
|
|
425
|
+
return null;
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
429
|
+
//#endregion
|
|
430
|
+
export { ancestors, create, get, list, processGroupHierarchy, remove, update };
|
|
431
|
+
//# sourceMappingURL=group.js.map
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { AuthProviderConfig, ConvexAuthConfig, ConvexCredentialsConfig, CorsConfig, DeviceProviderConfig, EmailConfig, EmailUserConfig, GenericDoc, GroupConnectionPolicy, GroupConnectionPolicyPatch, HttpKeyContext, KeyRecord, KeyScope, PhoneConfig, PhoneUserConfig, ScopeChecker } from "../server/types.js";
|
|
2
|
+
import { AuthContext, AuthContextConfig, OptionalAuthContext, UserDoc } from "../server/context.js";
|
|
3
|
+
import { AuthConfig, InferAuth } from "../server/facade.js";
|
|
4
|
+
import { HttpAuthContext, HttpAuthContextConfig, OptionalHttpAuthContext } from "../server/http.js";
|
|
5
|
+
import { AuthApi, defineAuth } from "../server/auth.js";
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import { mutation, query } from "./_generated/server.js";
|
|
2
|
+
import { v } from "convex/values";
|
|
3
|
+
|
|
4
|
+
//#region src/component/limits.ts
|
|
5
|
+
/**
|
|
6
|
+
* `component.limits.*` — sign-in token buckets stored with auth state.
|
|
7
|
+
*
|
|
8
|
+
* @module
|
|
9
|
+
*/
|
|
10
|
+
const HOUR_MS = 3600 * 1e3;
|
|
11
|
+
const args = {
|
|
12
|
+
identifier: v.string(),
|
|
13
|
+
maxAttemptsPerHour: v.number()
|
|
14
|
+
};
|
|
15
|
+
const returns = v.object({
|
|
16
|
+
ok: v.boolean(),
|
|
17
|
+
retryAfter: v.optional(v.number())
|
|
18
|
+
});
|
|
19
|
+
async function readBucket(ctx, identifier) {
|
|
20
|
+
return await ctx.db.query("SignInLimit").withIndex("identifier", (q) => q.eq("identifier", identifier)).unique();
|
|
21
|
+
}
|
|
22
|
+
function bucketStatus(bucket, maxAttemptsPerHour, now) {
|
|
23
|
+
const capacity = Math.max(0, maxAttemptsPerHour);
|
|
24
|
+
if (capacity === 0) return {
|
|
25
|
+
tokens: 0,
|
|
26
|
+
retryAfter: HOUR_MS
|
|
27
|
+
};
|
|
28
|
+
const elapsed = bucket === null ? 0 : Math.max(0, now - bucket.updatedAt);
|
|
29
|
+
const previous = bucket?.tokens ?? capacity;
|
|
30
|
+
const tokens = Math.min(capacity, previous + elapsed * capacity / HOUR_MS);
|
|
31
|
+
return {
|
|
32
|
+
tokens,
|
|
33
|
+
retryAfter: tokens >= 1 ? void 0 : Math.ceil((1 - tokens) * HOUR_MS / capacity)
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
/** Read token-bucket headroom without another component call. @internal */
|
|
37
|
+
async function checkSignInLimit(ctx, input) {
|
|
38
|
+
const status = bucketStatus(await readBucket(ctx, input.identifier), input.maxAttemptsPerHour, Date.now());
|
|
39
|
+
return {
|
|
40
|
+
ok: status.tokens >= 1,
|
|
41
|
+
retryAfter: status.retryAfter
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
/** Consume one guessable-secret attempt in the caller's mutation. @internal */
|
|
45
|
+
async function recordSignInLimit(ctx, input) {
|
|
46
|
+
const now = Date.now();
|
|
47
|
+
const bucket = await readBucket(ctx, input.identifier);
|
|
48
|
+
const status = bucketStatus(bucket, input.maxAttemptsPerHour, now);
|
|
49
|
+
if (status.tokens < 1) {
|
|
50
|
+
if (bucket !== null) await ctx.db.patch("SignInLimit", bucket._id, {
|
|
51
|
+
tokens: status.tokens,
|
|
52
|
+
updatedAt: now
|
|
53
|
+
});
|
|
54
|
+
return {
|
|
55
|
+
ok: false,
|
|
56
|
+
retryAfter: status.retryAfter
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const tokens = status.tokens - 1;
|
|
60
|
+
if (bucket === null) await ctx.db.insert("SignInLimit", {
|
|
61
|
+
identifier: input.identifier,
|
|
62
|
+
tokens,
|
|
63
|
+
updatedAt: now
|
|
64
|
+
});
|
|
65
|
+
else await ctx.db.patch("SignInLimit", bucket._id, {
|
|
66
|
+
tokens,
|
|
67
|
+
updatedAt: now
|
|
68
|
+
});
|
|
69
|
+
return {
|
|
70
|
+
ok: true,
|
|
71
|
+
retryAfter: void 0
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Clear a token bucket in the caller's mutation. @internal */
|
|
75
|
+
async function resetSignInLimit(ctx, identifier) {
|
|
76
|
+
const bucket = await readBucket(ctx, identifier);
|
|
77
|
+
if (bucket !== null) await ctx.db.delete("SignInLimit", bucket._id);
|
|
78
|
+
}
|
|
79
|
+
/** Peek at sign-in rate-limit headroom for `identifier` without consuming a token. */
|
|
80
|
+
const signInCheck = query({
|
|
81
|
+
args,
|
|
82
|
+
returns,
|
|
83
|
+
handler: checkSignInLimit
|
|
84
|
+
});
|
|
85
|
+
/** Consume one sign-in token for `identifier`; `ok: false` when throttled. */
|
|
86
|
+
const signInRecord = mutation({
|
|
87
|
+
args,
|
|
88
|
+
returns,
|
|
89
|
+
handler: recordSignInLimit
|
|
90
|
+
});
|
|
91
|
+
/** Clear the sign-in rate-limit counter for `identifier` after success. */
|
|
92
|
+
const signInReset = mutation({
|
|
93
|
+
args: { identifier: v.string() },
|
|
94
|
+
returns: v.null(),
|
|
95
|
+
handler: async (ctx, { identifier }) => {
|
|
96
|
+
await resetSignInLimit(ctx, identifier);
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
//#endregion
|
|
102
|
+
export { checkSignInLimit, recordSignInLimit, resetSignInLimit, signInCheck, signInRecord, signInReset };
|
|
103
|
+
//# sourceMappingURL=limits.js.map
|