convex 1.44.0 → 1.45.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/CHANGELOG.md +13 -0
- package/dist/browser.bundle.js +1 -1
- package/dist/browser.bundle.js.map +1 -1
- package/dist/cjs/cli/convexExport.js +1 -1
- package/dist/cjs/cli/convexExport.js.map +1 -1
- package/dist/cjs/cli/index.js +2 -32
- package/dist/cjs/cli/index.js.map +2 -2
- package/dist/cjs/cli/lib/api.js +11 -5
- package/dist/cjs/cli/lib/api.js.map +2 -2
- package/dist/cjs/cli/lib/convexExport.js +12 -1
- package/dist/cjs/cli/lib/convexExport.js.map +2 -2
- package/dist/cjs/cli/lib/dashboard.js.map +2 -2
- package/dist/cjs/cli/lib/generatedFunctionLogsApi.js.map +1 -1
- package/dist/cjs/cli/lib/indexes.js +1 -1
- package/dist/cjs/cli/lib/indexes.js.map +1 -1
- package/dist/cjs/cli/lib/localDeployment/upgrade.js +23 -188
- package/dist/cjs/cli/lib/localDeployment/upgrade.js.map +3 -3
- package/dist/cjs/cli/lib/mcp/tools/index.js.map +1 -1
- package/dist/cjs/cli/mcp.js +76 -69
- package/dist/cjs/cli/mcp.js.map +2 -2
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/server/impl/actions_impl.js.map +2 -2
- package/dist/cjs/server/index.js.map +2 -2
- package/dist/cjs-types/cli/lib/api.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/convexExport.d.ts +1 -0
- package/dist/cjs-types/cli/lib/convexExport.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/dashboard.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts +2 -0
- package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/localDeployment/upgrade.d.ts +2 -0
- package/dist/cjs-types/cli/lib/localDeployment/upgrade.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/mcp/tools/index.d.ts +1 -1
- package/dist/cjs-types/cli/lib/mcp/tools/index.d.ts.map +1 -1
- package/dist/cjs-types/cli/mcp.d.ts +3 -0
- package/dist/cjs-types/cli/mcp.d.ts.map +1 -1
- package/dist/cjs-types/index.d.ts +1 -1
- package/dist/cjs-types/server/impl/actions_impl.d.ts +14 -0
- package/dist/cjs-types/server/impl/actions_impl.d.ts.map +1 -1
- package/dist/cjs-types/server/index.d.ts +1 -0
- package/dist/cjs-types/server/index.d.ts.map +1 -1
- package/dist/cli.bundle.cjs +31210 -25495
- package/dist/cli.bundle.cjs.map +4 -4
- package/dist/esm/cli/convexExport.js +1 -1
- package/dist/esm/cli/convexExport.js.map +1 -1
- package/dist/esm/cli/index.js +2 -32
- package/dist/esm/cli/index.js.map +2 -2
- package/dist/esm/cli/lib/api.js +11 -5
- package/dist/esm/cli/lib/api.js.map +2 -2
- package/dist/esm/cli/lib/convexExport.js +16 -3
- package/dist/esm/cli/lib/convexExport.js.map +2 -2
- package/dist/esm/cli/lib/dashboard.js.map +2 -2
- package/dist/esm/cli/lib/indexes.js +1 -1
- package/dist/esm/cli/lib/indexes.js.map +1 -1
- package/dist/esm/cli/lib/localDeployment/upgrade.js +22 -190
- package/dist/esm/cli/lib/localDeployment/upgrade.js.map +2 -2
- package/dist/esm/cli/lib/mcp/tools/index.js.map +1 -1
- package/dist/esm/cli/mcp.js +75 -72
- package/dist/esm/cli/mcp.js.map +2 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/server/impl/actions_impl.js.map +2 -2
- package/dist/esm/server/index.js.map +2 -2
- package/dist/esm-types/cli/lib/api.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/convexExport.d.ts +1 -0
- package/dist/esm-types/cli/lib/convexExport.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/dashboard.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts +2 -0
- package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/localDeployment/upgrade.d.ts +2 -0
- package/dist/esm-types/cli/lib/localDeployment/upgrade.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/mcp/tools/index.d.ts +1 -1
- package/dist/esm-types/cli/lib/mcp/tools/index.d.ts.map +1 -1
- package/dist/esm-types/cli/mcp.d.ts +3 -0
- package/dist/esm-types/cli/mcp.d.ts.map +1 -1
- package/dist/esm-types/index.d.ts +1 -1
- package/dist/esm-types/server/impl/actions_impl.d.ts +14 -0
- package/dist/esm-types/server/impl/actions_impl.d.ts.map +1 -1
- package/dist/esm-types/server/index.d.ts +1 -0
- package/dist/esm-types/server/index.d.ts.map +1 -1
- package/dist/react.bundle.js +1 -1
- package/dist/react.bundle.js.map +1 -1
- package/package.json +3 -3
- package/src/cli/convexExport.ts +1 -1
- package/src/cli/index.ts +2 -35
- package/src/cli/lib/api.ts +11 -5
- package/src/cli/lib/convexExport.ts +21 -0
- package/src/cli/lib/dashboard.ts +2 -0
- package/src/cli/lib/generatedFunctionLogsApi.ts +2 -0
- package/src/cli/lib/indexes.ts +1 -1
- package/src/cli/lib/localDeployment/upgrade.ts +34 -207
- package/src/cli/lib/mcp/tools/index.ts +1 -1
- package/src/cli/mcp.ts +91 -77
- package/src/index.ts +1 -1
- package/src/server/impl/actions_impl.ts +3 -1
- package/src/server/index.ts +0 -3
- package/dist/cjs-types/browser/http_client.test.d.ts +0 -2
- package/dist/cjs-types/browser/http_client.test.d.ts.map +0 -1
- package/dist/cjs-types/browser/query_options.test.d.ts +0 -2
- package/dist/cjs-types/browser/query_options.test.d.ts.map +0 -1
- package/dist/cjs-types/browser/simple_client.test.d.ts +0 -2
- package/dist/cjs-types/browser/simple_client.test.d.ts.map +0 -1
- package/dist/cjs-types/browser/sync/client.test.d.ts +0 -5
- package/dist/cjs-types/browser/sync/client.test.d.ts.map +0 -1
- package/dist/cjs-types/browser/sync/client_node.test.d.ts +0 -2
- package/dist/cjs-types/browser/sync/client_node.test.d.ts.map +0 -1
- package/dist/cjs-types/browser/sync/client_node_test_helpers.d.ts +0 -44
- package/dist/cjs-types/browser/sync/client_node_test_helpers.d.ts.map +0 -1
- package/dist/cjs-types/browser/sync/local_state.test.d.ts +0 -2
- package/dist/cjs-types/browser/sync/local_state.test.d.ts.map +0 -1
- package/dist/cjs-types/browser/sync/optimistic_query_set.test.d.ts +0 -2
- package/dist/cjs-types/browser/sync/optimistic_query_set.test.d.ts.map +0 -1
- package/dist/cjs-types/browser/sync/paginated_query_client.test.d.ts +0 -2
- package/dist/cjs-types/browser/sync/paginated_query_client.test.d.ts.map +0 -1
- package/dist/cjs-types/browser/sync/protocol.test.d.ts +0 -5
- package/dist/cjs-types/browser/sync/protocol.test.d.ts.map +0 -1
- package/dist/cjs-types/browser/sync/request_manager.test.d.ts +0 -2
- package/dist/cjs-types/browser/sync/request_manager.test.d.ts.map +0 -1
- package/dist/cjs-types/bundler/fs.test.d.ts +0 -2
- package/dist/cjs-types/bundler/fs.test.d.ts.map +0 -1
- package/dist/cjs-types/bundler/index.test.d.ts +0 -2
- package/dist/cjs-types/bundler/index.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/codegen_templates/api.test.d.ts +0 -2
- package/dist/cjs-types/cli/codegen_templates/api.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/codegen_templates/common.test.d.ts +0 -2
- package/dist/cjs-types/cli/codegen_templates/common.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/codegen_templates/templates.test.d.ts +0 -2
- package/dist/cjs-types/cli/codegen_templates/templates.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/codegen_templates/validator_helpers.test.d.ts +0 -2
- package/dist/cjs-types/cli/codegen_templates/validator_helpers.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/configure.test.d.ts +0 -2
- package/dist/cjs-types/cli/configure.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/deploymentCreate.test.d.ts +0 -2
- package/dist/cjs-types/cli/deploymentCreate.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/deploymentSelect.test.d.ts +0 -2
- package/dist/cjs-types/cli/deploymentSelect.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/deploymentSelection.test.d.ts +0 -2
- package/dist/cjs-types/cli/deploymentSelection.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/deploymentToken.test.d.ts +0 -2
- package/dist/cjs-types/cli/deploymentToken.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/dev.test.d.ts +0 -2
- package/dist/cjs-types/cli/dev.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/envDefault.test.d.ts +0 -2
- package/dist/cjs-types/cli/envDefault.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/aiFiles/agentsmd.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/aiFiles/agentsmd.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/aiFiles/claudemd.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/aiFiles/claudemd.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/aiFiles/guidelinesmd.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/aiFiles/index.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/aiFiles/index.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/aiFiles/integration.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/aiFiles/integration.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/aiFiles/prompt.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/aiFiles/prompt.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/aiFiles/state.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/aiFiles/state.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/aiFiles/utils.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/aiFiles/utils.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/codegen.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/codegen.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/components.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/components.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/config.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/config.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/deployment.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/deployment.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/deploymentSelector.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/deploymentSelector.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/env.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/env.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/expiration.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/expiration.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/extractDeploymentNameForWorkOS.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/extractDeploymentNameForWorkOS.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/formatEnvValueForDotfile.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/formatEnvValueForDotfile.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/formatTargetedDeployment.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/formatTargetedDeployment.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/fsUtils.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/fsUtils.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/generateDocs.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/generateDocs.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/indexes.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/indexes.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/localDeployment/run.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/localDeployment/run.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/localDeployment/secrets.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/localDeployment/secrets.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/run.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/run.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/runTestFunction.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/runTestFunction.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/typecheck.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/typecheck.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/updates.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/updates.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/utils/hash.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/utils/hash.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/utils/utils.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/utils/utils.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/versionApi.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/versionApi.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/workos/environmentApi.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/workos/environmentApi.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/lib/workos/workos.test.d.ts +0 -2
- package/dist/cjs-types/cli/lib/workos/workos.test.d.ts.map +0 -1
- package/dist/cjs-types/cli/login.test.d.ts +0 -2
- package/dist/cjs-types/cli/login.test.d.ts.map +0 -1
- package/dist/cjs-types/common/index.test.d.ts +0 -2
- package/dist/cjs-types/common/index.test.d.ts.map +0 -1
- package/dist/cjs-types/nextjs/nextjs.test.d.ts +0 -2
- package/dist/cjs-types/nextjs/nextjs.test.d.ts.map +0 -1
- package/dist/cjs-types/react/ConvexAuthState.test.d.ts +0 -2
- package/dist/cjs-types/react/ConvexAuthState.test.d.ts.map +0 -1
- package/dist/cjs-types/react/auth_helpers.test.d.ts +0 -2
- package/dist/cjs-types/react/auth_helpers.test.d.ts.map +0 -1
- package/dist/cjs-types/react/auth_websocket.test.d.ts +0 -2
- package/dist/cjs-types/react/auth_websocket.test.d.ts.map +0 -1
- package/dist/cjs-types/react/client.test.d.ts +0 -2
- package/dist/cjs-types/react/client.test.d.ts.map +0 -1
- package/dist/cjs-types/react/client_provided_base_client.test.d.ts +0 -2
- package/dist/cjs-types/react/client_provided_base_client.test.d.ts.map +0 -1
- package/dist/cjs-types/react/queries_observer.test.d.ts +0 -2
- package/dist/cjs-types/react/queries_observer.test.d.ts.map +0 -1
- package/dist/cjs-types/react/react_node.test.d.ts +0 -2
- package/dist/cjs-types/react/react_node.test.d.ts.map +0 -1
- package/dist/cjs-types/react/use_paginated_query.test.d.ts +0 -2
- package/dist/cjs-types/react/use_paginated_query.test.d.ts.map +0 -1
- package/dist/cjs-types/react/use_queries.test.d.ts +0 -5
- package/dist/cjs-types/react/use_queries.test.d.ts.map +0 -1
- package/dist/cjs-types/react/use_query.test.d.ts +0 -5
- package/dist/cjs-types/react/use_query.test.d.ts.map +0 -1
- package/dist/cjs-types/react/use_query_object_options.test.d.ts +0 -5
- package/dist/cjs-types/react/use_query_object_options.test.d.ts.map +0 -1
- package/dist/cjs-types/react/use_query_result.test.d.ts +0 -5
- package/dist/cjs-types/react/use_query_result.test.d.ts.map +0 -1
- package/dist/cjs-types/react-auth0/ConvexProviderWithAuth0.test.d.ts +0 -2
- package/dist/cjs-types/react-auth0/ConvexProviderWithAuth0.test.d.ts.map +0 -1
- package/dist/cjs-types/react-clerk/ConvexProviderWithClerk.test.d.ts +0 -2
- package/dist/cjs-types/react-clerk/ConvexProviderWithClerk.test.d.ts.map +0 -1
- package/dist/cjs-types/server/api.intersect.test.d.ts +0 -2
- package/dist/cjs-types/server/api.intersect.test.d.ts.map +0 -1
- package/dist/cjs-types/server/api.test.d.ts +0 -2
- package/dist/cjs-types/server/api.test.d.ts.map +0 -1
- package/dist/cjs-types/server/audit_logging.test.d.ts +0 -2
- package/dist/cjs-types/server/audit_logging.test.d.ts.map +0 -1
- package/dist/cjs-types/server/components/index.test.d.ts +0 -2
- package/dist/cjs-types/server/components/index.test.d.ts.map +0 -1
- package/dist/cjs-types/server/cron.test.d.ts +0 -2
- package/dist/cjs-types/server/cron.test.d.ts.map +0 -1
- package/dist/cjs-types/server/data_model.test.d.ts +0 -2
- package/dist/cjs-types/server/data_model.test.d.ts.map +0 -1
- package/dist/cjs-types/server/database.test.d.ts +0 -2
- package/dist/cjs-types/server/database.test.d.ts.map +0 -1
- package/dist/cjs-types/server/database_api.test.d.ts +0 -2
- package/dist/cjs-types/server/database_api.test.d.ts.map +0 -1
- package/dist/cjs-types/server/filter_builder.test.d.ts +0 -2
- package/dist/cjs-types/server/filter_builder.test.d.ts.map +0 -1
- package/dist/cjs-types/server/impl/actions_impl.test.d.ts +0 -2
- package/dist/cjs-types/server/impl/actions_impl.test.d.ts.map +0 -1
- package/dist/cjs-types/server/impl/filter_builder_impl.test.d.ts +0 -2
- package/dist/cjs-types/server/impl/filter_builder_impl.test.d.ts.map +0 -1
- package/dist/cjs-types/server/impl/query_impl.test.d.ts +0 -2
- package/dist/cjs-types/server/impl/query_impl.test.d.ts.map +0 -1
- package/dist/cjs-types/server/pagination.test.d.ts +0 -2
- package/dist/cjs-types/server/pagination.test.d.ts.map +0 -1
- package/dist/cjs-types/server/query.test.d.ts +0 -2
- package/dist/cjs-types/server/query.test.d.ts.map +0 -1
- package/dist/cjs-types/server/registration.test.d.ts +0 -2
- package/dist/cjs-types/server/registration.test.d.ts.map +0 -1
- package/dist/cjs-types/server/router.test.d.ts +0 -2
- package/dist/cjs-types/server/router.test.d.ts.map +0 -1
- package/dist/cjs-types/server/scheduler.test.d.ts +0 -2
- package/dist/cjs-types/server/scheduler.test.d.ts.map +0 -1
- package/dist/cjs-types/server/schema.test.d.ts +0 -2
- package/dist/cjs-types/server/schema.test.d.ts.map +0 -1
- package/dist/cjs-types/test/fake_watch.d.ts +0 -16
- package/dist/cjs-types/test/fake_watch.d.ts.map +0 -1
- package/dist/cjs-types/test/type_testing.d.ts +0 -9
- package/dist/cjs-types/test/type_testing.d.ts.map +0 -1
- package/dist/cjs-types/type_utils.test.d.ts +0 -2
- package/dist/cjs-types/type_utils.test.d.ts.map +0 -1
- package/dist/cjs-types/values/size.test.d.ts +0 -2
- package/dist/cjs-types/values/size.test.d.ts.map +0 -1
- package/dist/cjs-types/values/validator.test.d.ts +0 -2
- package/dist/cjs-types/values/validator.test.d.ts.map +0 -1
- package/dist/cjs-types/values/value.test.d.ts +0 -2
- package/dist/cjs-types/values/value.test.d.ts.map +0 -1
- package/dist/esm-types/browser/http_client.test.d.ts +0 -2
- package/dist/esm-types/browser/http_client.test.d.ts.map +0 -1
- package/dist/esm-types/browser/query_options.test.d.ts +0 -2
- package/dist/esm-types/browser/query_options.test.d.ts.map +0 -1
- package/dist/esm-types/browser/simple_client.test.d.ts +0 -2
- package/dist/esm-types/browser/simple_client.test.d.ts.map +0 -1
- package/dist/esm-types/browser/sync/client.test.d.ts +0 -5
- package/dist/esm-types/browser/sync/client.test.d.ts.map +0 -1
- package/dist/esm-types/browser/sync/client_node.test.d.ts +0 -2
- package/dist/esm-types/browser/sync/client_node.test.d.ts.map +0 -1
- package/dist/esm-types/browser/sync/client_node_test_helpers.d.ts +0 -44
- package/dist/esm-types/browser/sync/client_node_test_helpers.d.ts.map +0 -1
- package/dist/esm-types/browser/sync/local_state.test.d.ts +0 -2
- package/dist/esm-types/browser/sync/local_state.test.d.ts.map +0 -1
- package/dist/esm-types/browser/sync/optimistic_query_set.test.d.ts +0 -2
- package/dist/esm-types/browser/sync/optimistic_query_set.test.d.ts.map +0 -1
- package/dist/esm-types/browser/sync/paginated_query_client.test.d.ts +0 -2
- package/dist/esm-types/browser/sync/paginated_query_client.test.d.ts.map +0 -1
- package/dist/esm-types/browser/sync/protocol.test.d.ts +0 -5
- package/dist/esm-types/browser/sync/protocol.test.d.ts.map +0 -1
- package/dist/esm-types/browser/sync/request_manager.test.d.ts +0 -2
- package/dist/esm-types/browser/sync/request_manager.test.d.ts.map +0 -1
- package/dist/esm-types/bundler/fs.test.d.ts +0 -2
- package/dist/esm-types/bundler/fs.test.d.ts.map +0 -1
- package/dist/esm-types/bundler/index.test.d.ts +0 -2
- package/dist/esm-types/bundler/index.test.d.ts.map +0 -1
- package/dist/esm-types/cli/codegen_templates/api.test.d.ts +0 -2
- package/dist/esm-types/cli/codegen_templates/api.test.d.ts.map +0 -1
- package/dist/esm-types/cli/codegen_templates/common.test.d.ts +0 -2
- package/dist/esm-types/cli/codegen_templates/common.test.d.ts.map +0 -1
- package/dist/esm-types/cli/codegen_templates/templates.test.d.ts +0 -2
- package/dist/esm-types/cli/codegen_templates/templates.test.d.ts.map +0 -1
- package/dist/esm-types/cli/codegen_templates/validator_helpers.test.d.ts +0 -2
- package/dist/esm-types/cli/codegen_templates/validator_helpers.test.d.ts.map +0 -1
- package/dist/esm-types/cli/configure.test.d.ts +0 -2
- package/dist/esm-types/cli/configure.test.d.ts.map +0 -1
- package/dist/esm-types/cli/deploymentCreate.test.d.ts +0 -2
- package/dist/esm-types/cli/deploymentCreate.test.d.ts.map +0 -1
- package/dist/esm-types/cli/deploymentSelect.test.d.ts +0 -2
- package/dist/esm-types/cli/deploymentSelect.test.d.ts.map +0 -1
- package/dist/esm-types/cli/deploymentSelection.test.d.ts +0 -2
- package/dist/esm-types/cli/deploymentSelection.test.d.ts.map +0 -1
- package/dist/esm-types/cli/deploymentToken.test.d.ts +0 -2
- package/dist/esm-types/cli/deploymentToken.test.d.ts.map +0 -1
- package/dist/esm-types/cli/dev.test.d.ts +0 -2
- package/dist/esm-types/cli/dev.test.d.ts.map +0 -1
- package/dist/esm-types/cli/envDefault.test.d.ts +0 -2
- package/dist/esm-types/cli/envDefault.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/aiFiles/agentsmd.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/aiFiles/agentsmd.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/aiFiles/claudemd.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/aiFiles/claudemd.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/aiFiles/guidelinesmd.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/aiFiles/index.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/aiFiles/index.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/aiFiles/integration.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/aiFiles/integration.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/aiFiles/prompt.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/aiFiles/prompt.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/aiFiles/state.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/aiFiles/state.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/aiFiles/utils.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/aiFiles/utils.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/codegen.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/codegen.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/components.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/components.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/config.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/config.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/deployment.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/deployment.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/deploymentSelector.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/deploymentSelector.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/env.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/env.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/expiration.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/expiration.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/extractDeploymentNameForWorkOS.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/extractDeploymentNameForWorkOS.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/formatEnvValueForDotfile.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/formatEnvValueForDotfile.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/formatTargetedDeployment.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/formatTargetedDeployment.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/fsUtils.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/fsUtils.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/generateDocs.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/generateDocs.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/indexes.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/indexes.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/localDeployment/run.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/localDeployment/run.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/localDeployment/secrets.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/localDeployment/secrets.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/run.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/run.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/runTestFunction.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/runTestFunction.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/typecheck.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/typecheck.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/updates.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/updates.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/utils/hash.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/utils/hash.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/utils/utils.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/utils/utils.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/versionApi.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/versionApi.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/workos/environmentApi.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/workos/environmentApi.test.d.ts.map +0 -1
- package/dist/esm-types/cli/lib/workos/workos.test.d.ts +0 -2
- package/dist/esm-types/cli/lib/workos/workos.test.d.ts.map +0 -1
- package/dist/esm-types/cli/login.test.d.ts +0 -2
- package/dist/esm-types/cli/login.test.d.ts.map +0 -1
- package/dist/esm-types/common/index.test.d.ts +0 -2
- package/dist/esm-types/common/index.test.d.ts.map +0 -1
- package/dist/esm-types/nextjs/nextjs.test.d.ts +0 -2
- package/dist/esm-types/nextjs/nextjs.test.d.ts.map +0 -1
- package/dist/esm-types/react/ConvexAuthState.test.d.ts +0 -2
- package/dist/esm-types/react/ConvexAuthState.test.d.ts.map +0 -1
- package/dist/esm-types/react/auth_helpers.test.d.ts +0 -2
- package/dist/esm-types/react/auth_helpers.test.d.ts.map +0 -1
- package/dist/esm-types/react/auth_websocket.test.d.ts +0 -2
- package/dist/esm-types/react/auth_websocket.test.d.ts.map +0 -1
- package/dist/esm-types/react/client.test.d.ts +0 -2
- package/dist/esm-types/react/client.test.d.ts.map +0 -1
- package/dist/esm-types/react/client_provided_base_client.test.d.ts +0 -2
- package/dist/esm-types/react/client_provided_base_client.test.d.ts.map +0 -1
- package/dist/esm-types/react/queries_observer.test.d.ts +0 -2
- package/dist/esm-types/react/queries_observer.test.d.ts.map +0 -1
- package/dist/esm-types/react/react_node.test.d.ts +0 -2
- package/dist/esm-types/react/react_node.test.d.ts.map +0 -1
- package/dist/esm-types/react/use_paginated_query.test.d.ts +0 -2
- package/dist/esm-types/react/use_paginated_query.test.d.ts.map +0 -1
- package/dist/esm-types/react/use_queries.test.d.ts +0 -5
- package/dist/esm-types/react/use_queries.test.d.ts.map +0 -1
- package/dist/esm-types/react/use_query.test.d.ts +0 -5
- package/dist/esm-types/react/use_query.test.d.ts.map +0 -1
- package/dist/esm-types/react/use_query_object_options.test.d.ts +0 -5
- package/dist/esm-types/react/use_query_object_options.test.d.ts.map +0 -1
- package/dist/esm-types/react/use_query_result.test.d.ts +0 -5
- package/dist/esm-types/react/use_query_result.test.d.ts.map +0 -1
- package/dist/esm-types/react-auth0/ConvexProviderWithAuth0.test.d.ts +0 -2
- package/dist/esm-types/react-auth0/ConvexProviderWithAuth0.test.d.ts.map +0 -1
- package/dist/esm-types/react-clerk/ConvexProviderWithClerk.test.d.ts +0 -2
- package/dist/esm-types/react-clerk/ConvexProviderWithClerk.test.d.ts.map +0 -1
- package/dist/esm-types/server/api.intersect.test.d.ts +0 -2
- package/dist/esm-types/server/api.intersect.test.d.ts.map +0 -1
- package/dist/esm-types/server/api.test.d.ts +0 -2
- package/dist/esm-types/server/api.test.d.ts.map +0 -1
- package/dist/esm-types/server/audit_logging.test.d.ts +0 -2
- package/dist/esm-types/server/audit_logging.test.d.ts.map +0 -1
- package/dist/esm-types/server/components/index.test.d.ts +0 -2
- package/dist/esm-types/server/components/index.test.d.ts.map +0 -1
- package/dist/esm-types/server/cron.test.d.ts +0 -2
- package/dist/esm-types/server/cron.test.d.ts.map +0 -1
- package/dist/esm-types/server/data_model.test.d.ts +0 -2
- package/dist/esm-types/server/data_model.test.d.ts.map +0 -1
- package/dist/esm-types/server/database.test.d.ts +0 -2
- package/dist/esm-types/server/database.test.d.ts.map +0 -1
- package/dist/esm-types/server/database_api.test.d.ts +0 -2
- package/dist/esm-types/server/database_api.test.d.ts.map +0 -1
- package/dist/esm-types/server/filter_builder.test.d.ts +0 -2
- package/dist/esm-types/server/filter_builder.test.d.ts.map +0 -1
- package/dist/esm-types/server/impl/actions_impl.test.d.ts +0 -2
- package/dist/esm-types/server/impl/actions_impl.test.d.ts.map +0 -1
- package/dist/esm-types/server/impl/filter_builder_impl.test.d.ts +0 -2
- package/dist/esm-types/server/impl/filter_builder_impl.test.d.ts.map +0 -1
- package/dist/esm-types/server/impl/query_impl.test.d.ts +0 -2
- package/dist/esm-types/server/impl/query_impl.test.d.ts.map +0 -1
- package/dist/esm-types/server/pagination.test.d.ts +0 -2
- package/dist/esm-types/server/pagination.test.d.ts.map +0 -1
- package/dist/esm-types/server/query.test.d.ts +0 -2
- package/dist/esm-types/server/query.test.d.ts.map +0 -1
- package/dist/esm-types/server/registration.test.d.ts +0 -2
- package/dist/esm-types/server/registration.test.d.ts.map +0 -1
- package/dist/esm-types/server/router.test.d.ts +0 -2
- package/dist/esm-types/server/router.test.d.ts.map +0 -1
- package/dist/esm-types/server/scheduler.test.d.ts +0 -2
- package/dist/esm-types/server/scheduler.test.d.ts.map +0 -1
- package/dist/esm-types/server/schema.test.d.ts +0 -2
- package/dist/esm-types/server/schema.test.d.ts.map +0 -1
- package/dist/esm-types/test/fake_watch.d.ts +0 -16
- package/dist/esm-types/test/fake_watch.d.ts.map +0 -1
- package/dist/esm-types/test/type_testing.d.ts +0 -9
- package/dist/esm-types/test/type_testing.d.ts.map +0 -1
- package/dist/esm-types/type_utils.test.d.ts +0 -2
- package/dist/esm-types/type_utils.test.d.ts.map +0 -1
- package/dist/esm-types/values/size.test.d.ts +0 -2
- package/dist/esm-types/values/size.test.d.ts.map +0 -1
- package/dist/esm-types/values/validator.test.d.ts +0 -2
- package/dist/esm-types/values/validator.test.d.ts.map +0 -1
- package/dist/esm-types/values/value.test.d.ts +0 -2
- package/dist/esm-types/values/value.test.d.ts.map +0 -1
- package/src/browser/http_client.test.ts +0 -202
- package/src/browser/query_options.test.ts +0 -43
- package/src/browser/simple_client.test.ts +0 -104
- package/src/browser/sync/client.test.ts +0 -44
- package/src/browser/sync/client_node.test.ts +0 -1207
- package/src/browser/sync/client_node_test_helpers.ts +0 -200
- package/src/browser/sync/local_state.test.ts +0 -128
- package/src/browser/sync/optimistic_query_set.test.ts +0 -253
- package/src/browser/sync/paginated_query_client.test.ts +0 -597
- package/src/browser/sync/protocol.test.ts +0 -14
- package/src/browser/sync/request_manager.test.ts +0 -273
- package/src/bundler/fs.test.ts +0 -86
- package/src/bundler/index.test.ts +0 -210
- package/src/bundler/test_fixtures/js/project01/bar.js +0 -4
- package/src/bundler/test_fixtures/js/project01/file with spaces.js +0 -1
- package/src/bundler/test_fixtures/js/project01/foo.js +0 -9
- package/src/bundler/test_fixtures/js/project_with_https/https.js +0 -9
- package/src/bundler/test_fixtures/js/project_with_https_not_at_top_level/default.js +0 -3
- package/src/bundler/test_fixtures/js/project_with_https_not_at_top_level/more_code/https.js +0 -5
- package/src/bundler/test_fixtures/js/project_with_https_without_router/https.js +0 -1
- package/src/bundler/test_fixtures/js/project_with_node_shims/uses_node_shims.js +0 -4
- package/src/cli/codegen_templates/api.test.ts +0 -18
- package/src/cli/codegen_templates/common.test.ts +0 -52
- package/src/cli/codegen_templates/templates.test.ts +0 -16
- package/src/cli/codegen_templates/validator_helpers.test.ts +0 -31
- package/src/cli/configure.test.ts +0 -138
- package/src/cli/deploymentCreate.test.ts +0 -1376
- package/src/cli/deploymentSelect.test.ts +0 -1291
- package/src/cli/deploymentSelection.test.ts +0 -2546
- package/src/cli/deploymentToken.test.ts +0 -397
- package/src/cli/dev.test.ts +0 -157
- package/src/cli/envDefault.test.ts +0 -495
- package/src/cli/lib/__snapshots__/formatTargetedDeployment.test.ts.snap +0 -94
- package/src/cli/lib/aiFiles/agentsmd.test.ts +0 -133
- package/src/cli/lib/aiFiles/claudemd.test.ts +0 -92
- package/src/cli/lib/aiFiles/guidelinesmd.test.ts +0 -50
- package/src/cli/lib/aiFiles/index.test.ts +0 -986
- package/src/cli/lib/aiFiles/integration.test.ts +0 -692
- package/src/cli/lib/aiFiles/prompt.test.ts +0 -202
- package/src/cli/lib/aiFiles/state.test.ts +0 -305
- package/src/cli/lib/aiFiles/utils.test.ts +0 -50
- package/src/cli/lib/codegen.test.ts +0 -49
- package/src/cli/lib/components.test.ts +0 -227
- package/src/cli/lib/config.test.ts +0 -1026
- package/src/cli/lib/deployment.test.ts +0 -85
- package/src/cli/lib/deploymentSelector.test.ts +0 -107
- package/src/cli/lib/env.test.ts +0 -60
- package/src/cli/lib/expiration.test.ts +0 -159
- package/src/cli/lib/extractDeploymentNameForWorkOS.test.ts +0 -30
- package/src/cli/lib/formatEnvValueForDotfile.test.ts +0 -294
- package/src/cli/lib/formatTargetedDeployment.test.ts +0 -281
- package/src/cli/lib/fsUtils.test.ts +0 -67
- package/src/cli/lib/generateDocs.test.ts +0 -326
- package/src/cli/lib/indexes.test.ts +0 -77
- package/src/cli/lib/localDeployment/run.test.ts +0 -104
- package/src/cli/lib/localDeployment/secrets.test.ts +0 -53
- package/src/cli/lib/run.test.ts +0 -54
- package/src/cli/lib/runTestFunction.test.ts +0 -84
- package/src/cli/lib/typecheck.test.ts +0 -71
- package/src/cli/lib/updates.test.ts +0 -157
- package/src/cli/lib/utils/hash.test.ts +0 -25
- package/src/cli/lib/utils/utils.test.ts +0 -340
- package/src/cli/lib/versionApi.test.ts +0 -471
- package/src/cli/lib/workos/environmentApi.test.ts +0 -107
- package/src/cli/lib/workos/workos.test.ts +0 -242
- package/src/cli/login.test.ts +0 -261
- package/src/common/README.md +0 -2
- package/src/common/index.test.ts +0 -35
- package/src/nextjs/nextjs.test.tsx +0 -94
- package/src/react/ConvexAuthState.test.tsx +0 -702
- package/src/react/auth_helpers.test.tsx +0 -45
- package/src/react/auth_websocket.test.tsx +0 -1177
- package/src/react/client.test.tsx +0 -261
- package/src/react/client_provided_base_client.test.tsx +0 -174
- package/src/react/queries_observer.test.ts +0 -176
- package/src/react/react_node.test.ts +0 -78
- package/src/react/use_paginated_query.test.tsx +0 -1420
- package/src/react/use_queries.test.ts +0 -140
- package/src/react/use_query.test.ts +0 -71
- package/src/react/use_query_object_options.test.ts +0 -51
- package/src/react/use_query_result.test.ts +0 -75
- package/src/react-auth0/ConvexProviderWithAuth0.test.tsx +0 -17
- package/src/react-clerk/ConvexProviderWithClerk.test.tsx +0 -18
- package/src/server/README.md +0 -15
- package/src/server/api.intersect.test.ts +0 -109
- package/src/server/api.test.ts +0 -447
- package/src/server/audit_logging.test.ts +0 -131
- package/src/server/components/index.test.ts +0 -48
- package/src/server/cron.test.ts +0 -58
- package/src/server/data_model.test.ts +0 -221
- package/src/server/database.test.ts +0 -184
- package/src/server/database_api.test.ts +0 -439
- package/src/server/filter_builder.test.ts +0 -102
- package/src/server/impl/actions_impl.test.ts +0 -59
- package/src/server/impl/filter_builder_impl.test.ts +0 -13
- package/src/server/impl/query_impl.test.ts +0 -46
- package/src/server/pagination.test.ts +0 -49
- package/src/server/query.test.ts +0 -112
- package/src/server/registration.test.ts +0 -589
- package/src/server/router.test.ts +0 -148
- package/src/server/scheduler.test.ts +0 -31
- package/src/server/schema.test.ts +0 -1081
- package/src/test/fake_watch.ts +0 -54
- package/src/test/type_testing.ts +0 -21
- package/src/type_utils.test.ts +0 -62
- package/src/values/size.test.ts +0 -95
- package/src/values/validator.test.ts +0 -619
- package/src/values/value.test.ts +0 -232
- package/src/vendor/README.md +0 -18
- package/src/vendor/jwt-decode/README.md +0 -1
|
@@ -1,1177 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @vitest-environment custom-vitest-environment.ts
|
|
3
|
-
*/
|
|
4
|
-
import { expect, vi, test, describe } from "vitest";
|
|
5
|
-
import { jwtEncode } from "../vendor/jwt-encode/index.js";
|
|
6
|
-
import {
|
|
7
|
-
nodeWebSocket,
|
|
8
|
-
withInMemoryWebSocket,
|
|
9
|
-
} from "../browser/sync/client_node_test_helpers.js";
|
|
10
|
-
import { ConvexReactClient, ConvexReactClientOptions } from "./index.js";
|
|
11
|
-
import { BaseConvexClient } from "../browser/index.js";
|
|
12
|
-
import waitForExpect from "wait-for-expect";
|
|
13
|
-
import { anyApi } from "../server/index.js";
|
|
14
|
-
import { Long } from "../vendor/long.js";
|
|
15
|
-
import {
|
|
16
|
-
AuthError,
|
|
17
|
-
ClientMessage,
|
|
18
|
-
WireServerMessage,
|
|
19
|
-
} from "../browser/sync/protocol.js";
|
|
20
|
-
|
|
21
|
-
const testReactClient = (
|
|
22
|
-
address: string,
|
|
23
|
-
options?: ConvexReactClientOptions,
|
|
24
|
-
) => {
|
|
25
|
-
const client = new ConvexReactClient(address, {
|
|
26
|
-
webSocketConstructor: nodeWebSocket,
|
|
27
|
-
unsavedChangesWarning: false,
|
|
28
|
-
...options,
|
|
29
|
-
});
|
|
30
|
-
const baseClient = client.sync;
|
|
31
|
-
if (!(baseClient instanceof BaseConvexClient)) {
|
|
32
|
-
throw new Error("Expected `sync` to be a `BaseConvexClient`");
|
|
33
|
-
}
|
|
34
|
-
return { client, baseClient };
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
// Disabled due to flakes in CI
|
|
38
|
-
// https://linear.app/convex/issue/ENG-7052/re-enable-auth-websocket-client-tests
|
|
39
|
-
|
|
40
|
-
// On Linux these can retry forever due to EADDRINUSE so run then sequentially.
|
|
41
|
-
describe.sequential.skip("auth websocket tests", () => {
|
|
42
|
-
// This is the path usually taken on page load after a user logged in,
|
|
43
|
-
// with a constant token provider.
|
|
44
|
-
test("Authenticate via valid static token", async () => {
|
|
45
|
-
await withInMemoryWebSocket(async ({ address, receive, send }) => {
|
|
46
|
-
const { client, baseClient } = testReactClient(address);
|
|
47
|
-
|
|
48
|
-
const tokenFetcher = vi.fn(async () =>
|
|
49
|
-
jwtEncode({ iat: 1234500, exp: 1244500 }, "secret"),
|
|
50
|
-
);
|
|
51
|
-
const onAuthChange = vi.fn();
|
|
52
|
-
client.setAuth(tokenFetcher, onAuthChange);
|
|
53
|
-
|
|
54
|
-
expect((await receive()).type).toEqual("Connect");
|
|
55
|
-
expect((await receive()).type).toEqual("Authenticate");
|
|
56
|
-
expect((await receive()).type).toEqual("ModifyQuerySet");
|
|
57
|
-
|
|
58
|
-
const querySetVersion = baseClient["remoteQuerySet"]["version"];
|
|
59
|
-
|
|
60
|
-
send({
|
|
61
|
-
type: "Transition",
|
|
62
|
-
startVersion: querySetVersion,
|
|
63
|
-
endVersion: {
|
|
64
|
-
...querySetVersion,
|
|
65
|
-
// Client started at 0
|
|
66
|
-
// Good token advanced to 1
|
|
67
|
-
identity: 1,
|
|
68
|
-
},
|
|
69
|
-
modifications: [],
|
|
70
|
-
});
|
|
71
|
-
|
|
72
|
-
await waitForExpect(() => {
|
|
73
|
-
expect(onAuthChange).toHaveBeenCalledTimes(1);
|
|
74
|
-
});
|
|
75
|
-
await client.close();
|
|
76
|
-
|
|
77
|
-
expect(tokenFetcher).toHaveBeenCalledWith({ forceRefreshToken: false });
|
|
78
|
-
expect(onAuthChange).toHaveBeenCalledTimes(1);
|
|
79
|
-
expect(onAuthChange).toHaveBeenCalledWith(true);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
|
|
83
|
-
// This happens when a user opens a page after their cached token expired
|
|
84
|
-
test("Reauthenticate after token expiration with versioning", async () => {
|
|
85
|
-
await withInMemoryWebSocket(async ({ address, receive, send, close }) => {
|
|
86
|
-
const { client, baseClient } = testReactClient(address);
|
|
87
|
-
|
|
88
|
-
let token = jwtEncode({ iat: 1234500, exp: 1244500 }, "wobabloobla");
|
|
89
|
-
const fetchToken = async () => token;
|
|
90
|
-
const tokenFetcher = vi.fn(fetchToken);
|
|
91
|
-
const onAuthChange = vi.fn();
|
|
92
|
-
client.setAuth(tokenFetcher, onAuthChange);
|
|
93
|
-
|
|
94
|
-
await assertReconnectWithAuth(receive, {
|
|
95
|
-
baseVersion: 0,
|
|
96
|
-
token: token,
|
|
97
|
-
});
|
|
98
|
-
|
|
99
|
-
// Token must change, otherwise client will not try to reauthenticate
|
|
100
|
-
token = jwtEncode({ iat: 1234500, exp: 1244500 }, "secret");
|
|
101
|
-
|
|
102
|
-
await simulateAuthError({
|
|
103
|
-
send,
|
|
104
|
-
close,
|
|
105
|
-
authError: {
|
|
106
|
-
type: "AuthError",
|
|
107
|
-
error: "bla",
|
|
108
|
-
baseVersion: 0,
|
|
109
|
-
authUpdateAttempted: true,
|
|
110
|
-
},
|
|
111
|
-
});
|
|
112
|
-
|
|
113
|
-
// The client reconnects automatically
|
|
114
|
-
await assertReconnectWithAuth(receive, {
|
|
115
|
-
baseVersion: 0,
|
|
116
|
-
token: token,
|
|
117
|
-
});
|
|
118
|
-
|
|
119
|
-
const querySetVersion = baseClient["remoteQuerySet"]["version"];
|
|
120
|
-
|
|
121
|
-
// Server accepts new token
|
|
122
|
-
send({
|
|
123
|
-
type: "Transition",
|
|
124
|
-
startVersion: querySetVersion,
|
|
125
|
-
endVersion: {
|
|
126
|
-
...querySetVersion,
|
|
127
|
-
identity: 1,
|
|
128
|
-
},
|
|
129
|
-
modifications: [],
|
|
130
|
-
});
|
|
131
|
-
|
|
132
|
-
await waitForExpect(() => {
|
|
133
|
-
expect(onAuthChange).toHaveBeenCalledTimes(1);
|
|
134
|
-
});
|
|
135
|
-
await client.close();
|
|
136
|
-
|
|
137
|
-
expect(tokenFetcher).toHaveBeenNthCalledWith(1, {
|
|
138
|
-
forceRefreshToken: false,
|
|
139
|
-
});
|
|
140
|
-
expect(tokenFetcher).toHaveBeenNthCalledWith(2, {
|
|
141
|
-
forceRefreshToken: true,
|
|
142
|
-
});
|
|
143
|
-
expect(onAuthChange).toHaveBeenCalledWith(true);
|
|
144
|
-
});
|
|
145
|
-
});
|
|
146
|
-
|
|
147
|
-
// This happens when a user opens a page and they cannot
|
|
148
|
-
// fetch from a cache (say due to Prevent Cross Site tracking)
|
|
149
|
-
test("Reauthenticate after token cache failure", async () => {
|
|
150
|
-
await withInMemoryWebSocket(async ({ address, receive, send }) => {
|
|
151
|
-
const { client, baseClient } = testReactClient(address);
|
|
152
|
-
|
|
153
|
-
const freshToken = jwtEncode({ iat: 1234500, exp: 1244500 }, "secret");
|
|
154
|
-
const tokenFetcher = vi.fn(
|
|
155
|
-
async (args: { forceRefreshToken: boolean }) => {
|
|
156
|
-
if (args.forceRefreshToken) {
|
|
157
|
-
return freshToken;
|
|
158
|
-
}
|
|
159
|
-
return null;
|
|
160
|
-
},
|
|
161
|
-
);
|
|
162
|
-
const onAuthChange = vi.fn();
|
|
163
|
-
void client.setAuth(tokenFetcher, onAuthChange);
|
|
164
|
-
|
|
165
|
-
// The client authenticates after the token refetch
|
|
166
|
-
await assertReconnectWithAuth(receive, {
|
|
167
|
-
baseVersion: 0,
|
|
168
|
-
token: freshToken,
|
|
169
|
-
});
|
|
170
|
-
|
|
171
|
-
const querySetVersion = baseClient["remoteQuerySet"]["version"];
|
|
172
|
-
|
|
173
|
-
// Server accepts new token
|
|
174
|
-
send({
|
|
175
|
-
type: "Transition",
|
|
176
|
-
startVersion: querySetVersion,
|
|
177
|
-
endVersion: {
|
|
178
|
-
...querySetVersion,
|
|
179
|
-
identity: 1,
|
|
180
|
-
},
|
|
181
|
-
modifications: [],
|
|
182
|
-
});
|
|
183
|
-
|
|
184
|
-
await waitForExpect(() => {
|
|
185
|
-
expect(onAuthChange).toHaveBeenCalledTimes(1);
|
|
186
|
-
});
|
|
187
|
-
await client.close();
|
|
188
|
-
|
|
189
|
-
expect(tokenFetcher).toHaveBeenNthCalledWith(1, {
|
|
190
|
-
forceRefreshToken: false,
|
|
191
|
-
});
|
|
192
|
-
expect(tokenFetcher).toHaveBeenNthCalledWith(2, {
|
|
193
|
-
forceRefreshToken: true,
|
|
194
|
-
});
|
|
195
|
-
expect(onAuthChange).toHaveBeenCalledWith(true);
|
|
196
|
-
});
|
|
197
|
-
});
|
|
198
|
-
|
|
199
|
-
// This is usually a misconfigured server rejecting any token
|
|
200
|
-
test("Fail when tokens are always rejected", async () => {
|
|
201
|
-
await withInMemoryWebSocket(async ({ address, receive, send, close }) => {
|
|
202
|
-
const { client } = testReactClient(address);
|
|
203
|
-
|
|
204
|
-
const consoleSpy = vi
|
|
205
|
-
.spyOn(global.console, "error")
|
|
206
|
-
.mockImplementation(() => {
|
|
207
|
-
// Do nothing
|
|
208
|
-
});
|
|
209
|
-
|
|
210
|
-
const token1 = jwtEncode({ iat: 1234500, exp: 1244500 }, "secret1");
|
|
211
|
-
const token2 = jwtEncode({ iat: 1234500, exp: 1244500 }, "secret2");
|
|
212
|
-
const token3 = jwtEncode({ iat: 1234500, exp: 1244500 }, "secret3");
|
|
213
|
-
const token4 = jwtEncode({ iat: 1234500, exp: 1244500 }, "secret4");
|
|
214
|
-
|
|
215
|
-
const tokens = [token1, token2, token3, token4];
|
|
216
|
-
|
|
217
|
-
const tokenFetcher = vi.fn(async () => tokens.shift());
|
|
218
|
-
const onAuthChange = vi.fn();
|
|
219
|
-
client.setAuth(tokenFetcher, onAuthChange);
|
|
220
|
-
|
|
221
|
-
expect((await receive()).type).toEqual("Connect");
|
|
222
|
-
assertAuthenticateMessage(await receive(), {
|
|
223
|
-
baseVersion: 0,
|
|
224
|
-
token: token1,
|
|
225
|
-
});
|
|
226
|
-
expect((await receive()).type).toEqual("ModifyQuerySet");
|
|
227
|
-
|
|
228
|
-
send({
|
|
229
|
-
type: "AuthError",
|
|
230
|
-
error: "bla",
|
|
231
|
-
baseVersion: 0,
|
|
232
|
-
authUpdateAttempted: true,
|
|
233
|
-
});
|
|
234
|
-
close();
|
|
235
|
-
|
|
236
|
-
// The client reconnects automatically and retries twice
|
|
237
|
-
expect((await receive()).type).toEqual("Connect");
|
|
238
|
-
assertAuthenticateMessage(await receive(), {
|
|
239
|
-
baseVersion: 0,
|
|
240
|
-
token: token2,
|
|
241
|
-
});
|
|
242
|
-
expect((await receive()).type).toEqual("ModifyQuerySet");
|
|
243
|
-
|
|
244
|
-
const AUTH_ERROR_MESSAGE = "bada boom";
|
|
245
|
-
send({
|
|
246
|
-
type: "AuthError",
|
|
247
|
-
error: AUTH_ERROR_MESSAGE,
|
|
248
|
-
baseVersion: 0,
|
|
249
|
-
authUpdateAttempted: true,
|
|
250
|
-
});
|
|
251
|
-
close();
|
|
252
|
-
|
|
253
|
-
expect((await receive()).type).toEqual("Connect");
|
|
254
|
-
assertAuthenticateMessage(await receive(), {
|
|
255
|
-
baseVersion: 0,
|
|
256
|
-
token: token3,
|
|
257
|
-
});
|
|
258
|
-
expect((await receive()).type).toEqual("ModifyQuerySet");
|
|
259
|
-
|
|
260
|
-
send({
|
|
261
|
-
type: "AuthError",
|
|
262
|
-
error: AUTH_ERROR_MESSAGE,
|
|
263
|
-
baseVersion: 0,
|
|
264
|
-
authUpdateAttempted: true,
|
|
265
|
-
});
|
|
266
|
-
close();
|
|
267
|
-
|
|
268
|
-
expect((await receive()).type).toEqual("Connect");
|
|
269
|
-
assertAuthenticateMessage(await receive(), {
|
|
270
|
-
baseVersion: 0,
|
|
271
|
-
token: token4,
|
|
272
|
-
});
|
|
273
|
-
expect((await receive()).type).toEqual("ModifyQuerySet");
|
|
274
|
-
|
|
275
|
-
send({
|
|
276
|
-
type: "AuthError",
|
|
277
|
-
error: AUTH_ERROR_MESSAGE,
|
|
278
|
-
baseVersion: 0,
|
|
279
|
-
authUpdateAttempted: true,
|
|
280
|
-
});
|
|
281
|
-
close();
|
|
282
|
-
|
|
283
|
-
// The client reconnects automatically (but without auth)
|
|
284
|
-
expect((await receive()).type).toEqual("Connect");
|
|
285
|
-
expect((await receive()).type).toEqual("ModifyQuerySet");
|
|
286
|
-
await client.close();
|
|
287
|
-
|
|
288
|
-
expect(onAuthChange).toHaveBeenCalledTimes(1);
|
|
289
|
-
expect(onAuthChange).toHaveBeenCalledWith(false);
|
|
290
|
-
expect(consoleSpy).toHaveBeenCalledWith(
|
|
291
|
-
`Failed to authenticate: "${AUTH_ERROR_MESSAGE}", check your server auth config`,
|
|
292
|
-
);
|
|
293
|
-
});
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
// This happens when "refresh token"s expired - auth provider client thinks
|
|
297
|
-
// it's authed but it cannot fetch a token at all.
|
|
298
|
-
test("Fail when tokens cannot be fetched", async () => {
|
|
299
|
-
await withInMemoryWebSocket(async ({ address, receive }) => {
|
|
300
|
-
const { client } = testReactClient(address);
|
|
301
|
-
const tokenFetcher = vi.fn(async () => null);
|
|
302
|
-
const onAuthChange = vi.fn();
|
|
303
|
-
void client.setAuth(tokenFetcher, onAuthChange);
|
|
304
|
-
|
|
305
|
-
expect((await receive()).type).toEqual("Connect");
|
|
306
|
-
expect((await receive()).type).toEqual("ModifyQuerySet");
|
|
307
|
-
|
|
308
|
-
await waitForExpect(() => {
|
|
309
|
-
expect(onAuthChange).toHaveBeenCalledTimes(1);
|
|
310
|
-
});
|
|
311
|
-
await client.close();
|
|
312
|
-
|
|
313
|
-
expect(onAuthChange).toHaveBeenCalledTimes(1);
|
|
314
|
-
expect(onAuthChange).toHaveBeenCalledWith(false);
|
|
315
|
-
});
|
|
316
|
-
});
|
|
317
|
-
|
|
318
|
-
test("Client is protected against token rejection race", async () => {
|
|
319
|
-
await withInMemoryWebSocket(async ({ address, receive, send, close }) => {
|
|
320
|
-
const { client, baseClient } = testReactClient(address);
|
|
321
|
-
|
|
322
|
-
const badToken = jwtEncode({ iat: 1234500, exp: 1244500 }, "wobalooba");
|
|
323
|
-
const badTokenFetcher = vi.fn(async () => badToken);
|
|
324
|
-
const firstOnChange = vi.fn();
|
|
325
|
-
client.setAuth(badTokenFetcher, firstOnChange);
|
|
326
|
-
|
|
327
|
-
await assertReconnectWithAuth(receive, {
|
|
328
|
-
baseVersion: 0,
|
|
329
|
-
token: badToken,
|
|
330
|
-
});
|
|
331
|
-
|
|
332
|
-
const querySetVersion = baseClient["remoteQuerySet"]["version"];
|
|
333
|
-
|
|
334
|
-
const goodToken = jwtEncode({ iat: 1234500, exp: 1244500 }, "secret");
|
|
335
|
-
const goodTokenFetcher = vi.fn(async () => goodToken);
|
|
336
|
-
|
|
337
|
-
const secondOnChange = vi.fn();
|
|
338
|
-
client.setAuth(goodTokenFetcher, secondOnChange);
|
|
339
|
-
|
|
340
|
-
assertAuthenticateMessage(await receive(), {
|
|
341
|
-
baseVersion: 1,
|
|
342
|
-
token: goodToken,
|
|
343
|
-
});
|
|
344
|
-
|
|
345
|
-
// This is the current server AuthError sequence:
|
|
346
|
-
// send a message and close the connection.
|
|
347
|
-
await simulateAuthError({
|
|
348
|
-
send,
|
|
349
|
-
close,
|
|
350
|
-
authError: {
|
|
351
|
-
type: "AuthError",
|
|
352
|
-
error: "bla",
|
|
353
|
-
baseVersion: 0,
|
|
354
|
-
authUpdateAttempted: true,
|
|
355
|
-
},
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
await assertReconnectWithAuth(receive, {
|
|
359
|
-
baseVersion: 0,
|
|
360
|
-
token: goodToken,
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
send({
|
|
364
|
-
type: "Transition",
|
|
365
|
-
startVersion: {
|
|
366
|
-
...querySetVersion,
|
|
367
|
-
// Client started at 0 after reconnect
|
|
368
|
-
identity: 0,
|
|
369
|
-
},
|
|
370
|
-
endVersion: {
|
|
371
|
-
...querySetVersion,
|
|
372
|
-
// Good token advanced to 1
|
|
373
|
-
identity: 1,
|
|
374
|
-
},
|
|
375
|
-
modifications: [],
|
|
376
|
-
});
|
|
377
|
-
|
|
378
|
-
await waitForExpect(() => {
|
|
379
|
-
expect(secondOnChange).toHaveBeenCalledTimes(1);
|
|
380
|
-
});
|
|
381
|
-
await client.close();
|
|
382
|
-
|
|
383
|
-
expect(firstOnChange).toHaveBeenCalledTimes(0);
|
|
384
|
-
expect(secondOnChange).toHaveBeenCalledWith(true);
|
|
385
|
-
});
|
|
386
|
-
});
|
|
387
|
-
|
|
388
|
-
// This is a race condition where a delayed auth error from a non-auth message
|
|
389
|
-
// comes back while the client is waiting for server validation of the new token.
|
|
390
|
-
test("Client ignores non-auth responses for token validation", async () => {
|
|
391
|
-
await withInMemoryWebSocket(async ({ address, receive, send, close }) => {
|
|
392
|
-
const { client, baseClient } = testReactClient(address);
|
|
393
|
-
const ts = Math.ceil(Date.now() / 1000);
|
|
394
|
-
const initialToken = jwtEncode({ iat: ts, exp: ts + 1000 }, "token1");
|
|
395
|
-
const freshToken = jwtEncode({ iat: ts, exp: ts + 1000 }, "token2");
|
|
396
|
-
const tokens = [initialToken, freshToken];
|
|
397
|
-
const tokenFetcher = vi.fn(async (_opts) => tokens.shift()!);
|
|
398
|
-
const onChange = vi.fn();
|
|
399
|
-
// This will immediately send the `initialToken` to the server (treating it as
|
|
400
|
-
// a token cached in local storage / other memory), and then asynchronously
|
|
401
|
-
// fetch `freshToken`, as a "fresh" token, and send that in a future `Authenticate`
|
|
402
|
-
// message.
|
|
403
|
-
client.setAuth(tokenFetcher, onChange);
|
|
404
|
-
|
|
405
|
-
// Messages for initial connection + handling `initialToken`
|
|
406
|
-
await assertReconnectWithAuth(receive, {
|
|
407
|
-
baseVersion: 0,
|
|
408
|
-
token: initialToken,
|
|
409
|
-
});
|
|
410
|
-
|
|
411
|
-
const querySetVersion = baseClient["remoteQuerySet"]["version"];
|
|
412
|
-
|
|
413
|
-
send({
|
|
414
|
-
type: "Transition",
|
|
415
|
-
startVersion: {
|
|
416
|
-
...querySetVersion,
|
|
417
|
-
identity: 0,
|
|
418
|
-
},
|
|
419
|
-
endVersion: {
|
|
420
|
-
...querySetVersion,
|
|
421
|
-
identity: 1,
|
|
422
|
-
},
|
|
423
|
-
modifications: [],
|
|
424
|
-
});
|
|
425
|
-
|
|
426
|
-
// Message from the client containing `freshToken`
|
|
427
|
-
assertAuthenticateMessage(await receive(), {
|
|
428
|
-
baseVersion: 1,
|
|
429
|
-
token: freshToken,
|
|
430
|
-
});
|
|
431
|
-
|
|
432
|
-
// The client's sync state should still be on version 1, because we haven't transitioned
|
|
433
|
-
// to the new token yet. But the AuthenticationManager should be in the state `waitingForServerConfirmationOfFreshToken`
|
|
434
|
-
|
|
435
|
-
// The server may send an auth error for version 1 before it has processed the
|
|
436
|
-
// `Authenticate` message for version 2.
|
|
437
|
-
|
|
438
|
-
// One way this can happen is a query re-executing (i.e. because the data changed) and noticing
|
|
439
|
-
// that the current auth has expired. This should have `authUpdateAttempted: false` because
|
|
440
|
-
// the server has not yet processed the `Authenticate` message for version 2.
|
|
441
|
-
await simulateAuthError({
|
|
442
|
-
send,
|
|
443
|
-
close,
|
|
444
|
-
authError: {
|
|
445
|
-
type: "AuthError",
|
|
446
|
-
error: "bla",
|
|
447
|
-
baseVersion: 1,
|
|
448
|
-
authUpdateAttempted: false,
|
|
449
|
-
},
|
|
450
|
-
});
|
|
451
|
-
|
|
452
|
-
// However, on the next reconnect, it should send `freshToken` to complete the token exchange.
|
|
453
|
-
await assertReconnectWithAuth(receive, {
|
|
454
|
-
baseVersion: 0,
|
|
455
|
-
token: freshToken,
|
|
456
|
-
});
|
|
457
|
-
|
|
458
|
-
const querySetVersion2 = baseClient["remoteQuerySet"]["version"];
|
|
459
|
-
|
|
460
|
-
send({
|
|
461
|
-
type: "Transition",
|
|
462
|
-
startVersion: {
|
|
463
|
-
...querySetVersion2,
|
|
464
|
-
identity: 0,
|
|
465
|
-
},
|
|
466
|
-
endVersion: {
|
|
467
|
-
...querySetVersion2,
|
|
468
|
-
identity: 1,
|
|
469
|
-
},
|
|
470
|
-
modifications: [],
|
|
471
|
-
});
|
|
472
|
-
|
|
473
|
-
// Flush
|
|
474
|
-
await new Promise((resolve) => setTimeout(resolve));
|
|
475
|
-
await client.close();
|
|
476
|
-
|
|
477
|
-
expect(onChange).toHaveBeenCalledTimes(2);
|
|
478
|
-
expect(onChange).toHaveBeenNthCalledWith(1, true);
|
|
479
|
-
// Without proper handling, this second call will be false
|
|
480
|
-
expect(onChange).toHaveBeenNthCalledWith(2, true);
|
|
481
|
-
}, true);
|
|
482
|
-
});
|
|
483
|
-
|
|
484
|
-
// This is a race condition where a connection stopped by reauthentication
|
|
485
|
-
// never restarts due to reauthentication exiting early. This happens when
|
|
486
|
-
// an additional refetch begins while reauthentication is still running,
|
|
487
|
-
// such as with a scheduled refetch.
|
|
488
|
-
test("Client maintains connection when refetch occurs during reauth attempt", async () => {
|
|
489
|
-
await withInMemoryWebSocket(async ({ address, receive, send, close }) => {
|
|
490
|
-
vi.useFakeTimers();
|
|
491
|
-
const { client, baseClient } = testReactClient(address);
|
|
492
|
-
// In this test we're going to simulate `fetchToken` taking a long time (1s)
|
|
493
|
-
// so we can test race conditions, so the issued time will be 1s after the
|
|
494
|
-
// fetched time.
|
|
495
|
-
|
|
496
|
-
// Tokens in this test will expire 3s after they are issued, and we're relying
|
|
497
|
-
// on the default 2s refresh leeway which means the scheduled refetch will
|
|
498
|
-
// start 1s after the token is issued.
|
|
499
|
-
|
|
500
|
-
const nowInSeconds = Math.ceil(Date.now() / 1000);
|
|
501
|
-
// existing token, the times shouldn't matter since we immediately fetch a fresh token
|
|
502
|
-
const initialToken = jwtEncode(
|
|
503
|
-
{ iat: nowInSeconds - 10, exp: nowInSeconds + 10 },
|
|
504
|
-
"initialToken",
|
|
505
|
-
);
|
|
506
|
-
// fresh token, fetched at ts=1
|
|
507
|
-
const freshToken = jwtEncode(
|
|
508
|
-
{ iat: nowInSeconds + 1, exp: nowInSeconds + 4 },
|
|
509
|
-
"freshToken",
|
|
510
|
-
);
|
|
511
|
-
// scheduled refetch at ts=2 (2s before freshToken expires), but with a 1s delay
|
|
512
|
-
const scheduledRefetchToken = jwtEncode(
|
|
513
|
-
{ iat: nowInSeconds + 3, exp: nowInSeconds + 6 },
|
|
514
|
-
"scheduledRefetchToken",
|
|
515
|
-
);
|
|
516
|
-
// fetched at ts 1.5 in response to an auth error, issued at ts=2.5
|
|
517
|
-
const reauthToken = jwtEncode(
|
|
518
|
-
{ iat: nowInSeconds + 2.5, exp: nowInSeconds + 5.5 },
|
|
519
|
-
"reauthToken",
|
|
520
|
-
);
|
|
521
|
-
const tokens = [
|
|
522
|
-
initialToken,
|
|
523
|
-
freshToken,
|
|
524
|
-
reauthToken,
|
|
525
|
-
scheduledRefetchToken,
|
|
526
|
-
];
|
|
527
|
-
const tokenFetcher = vi.fn(
|
|
528
|
-
async ({ forceRefreshToken }: { forceRefreshToken: boolean }) => {
|
|
529
|
-
const token = tokens.shift();
|
|
530
|
-
if (forceRefreshToken === false) {
|
|
531
|
-
if (token !== initialToken) {
|
|
532
|
-
throw new Error(
|
|
533
|
-
"scheduledRefetchToken should be fetched with forceRefreshToken=true",
|
|
534
|
-
);
|
|
535
|
-
}
|
|
536
|
-
return token;
|
|
537
|
-
}
|
|
538
|
-
|
|
539
|
-
vi.advanceTimersByTime(1000);
|
|
540
|
-
return token;
|
|
541
|
-
},
|
|
542
|
-
);
|
|
543
|
-
const onChange = vi.fn((isAuthenticated: boolean) => {
|
|
544
|
-
if (!isAuthenticated) {
|
|
545
|
-
throw new Error("Client is unexpectedly unauthenticated");
|
|
546
|
-
}
|
|
547
|
-
});
|
|
548
|
-
client.setAuth(tokenFetcher, onChange);
|
|
549
|
-
|
|
550
|
-
// Initial connection, sending `initialToken`
|
|
551
|
-
// ts=0
|
|
552
|
-
await assertReconnectWithAuth(receive, {
|
|
553
|
-
baseVersion: 0,
|
|
554
|
-
token: initialToken,
|
|
555
|
-
});
|
|
556
|
-
const querySetVersion = baseClient["remoteQuerySet"]["version"];
|
|
557
|
-
|
|
558
|
-
send({
|
|
559
|
-
type: "Transition",
|
|
560
|
-
startVersion: {
|
|
561
|
-
...querySetVersion,
|
|
562
|
-
identity: 0,
|
|
563
|
-
},
|
|
564
|
-
endVersion: {
|
|
565
|
-
...querySetVersion,
|
|
566
|
-
identity: 1,
|
|
567
|
-
},
|
|
568
|
-
modifications: [],
|
|
569
|
-
});
|
|
570
|
-
|
|
571
|
-
// Immediately fetch a a fresh token (`freshToken`).
|
|
572
|
-
// `freshToken` expires at ts=4
|
|
573
|
-
// We will also schedule a refetch at ts=2 (2s before `freshToken` expires)
|
|
574
|
-
assertAuthenticateMessage(await receive(), {
|
|
575
|
-
baseVersion: 1,
|
|
576
|
-
token: freshToken,
|
|
577
|
-
});
|
|
578
|
-
|
|
579
|
-
// Server confirms `freshToken` and transitions to version 2
|
|
580
|
-
send({
|
|
581
|
-
type: "Transition",
|
|
582
|
-
startVersion: {
|
|
583
|
-
...querySetVersion,
|
|
584
|
-
identity: 1,
|
|
585
|
-
},
|
|
586
|
-
endVersion: {
|
|
587
|
-
...querySetVersion,
|
|
588
|
-
identity: 2,
|
|
589
|
-
},
|
|
590
|
-
modifications: [],
|
|
591
|
-
});
|
|
592
|
-
|
|
593
|
-
vi.advanceTimersByTime(500);
|
|
594
|
-
|
|
595
|
-
// ts=1.5
|
|
596
|
-
// `freshToken` becomes stale before the client has a chance to fetch and send
|
|
597
|
-
// `scheduledRefetchToken` (e.g. because the page is backgrounded or because `fetchToken` is slow
|
|
598
|
-
// for some reason), so the server hits an AuthError.
|
|
599
|
-
await simulateAuthError({
|
|
600
|
-
send,
|
|
601
|
-
close,
|
|
602
|
-
authError: {
|
|
603
|
-
type: "AuthError",
|
|
604
|
-
error: "bla",
|
|
605
|
-
baseVersion: 2,
|
|
606
|
-
authUpdateAttempted: false,
|
|
607
|
-
},
|
|
608
|
-
});
|
|
609
|
-
|
|
610
|
-
// In response to this error, we call `tryToReauthenticate`.
|
|
611
|
-
// Let's say `this.configVersion` is X
|
|
612
|
-
// This will first stop the websocket, which bumps the configVersion to X+1
|
|
613
|
-
// This'll call `fetchAndGuardAgainstRace`, which bumps `this.configVersion` to X+2
|
|
614
|
-
// and sets `originalConfigVersion=X+2` locally
|
|
615
|
-
// Then it starts fetching `reauthToken` at ts=1.5 and it will finish at ts=2.5.
|
|
616
|
-
|
|
617
|
-
// At ts=2, we expect the scheduled token fetch to start.
|
|
618
|
-
// This calls `fetchAndGuardAgainstRace`, which bumps `this.configVersion` to X+3
|
|
619
|
-
// and sets `originalConfigVersion=X+3` locally
|
|
620
|
-
|
|
621
|
-
// At ts=2.5, we get a result from `fetchToken` from the `fetchAndGuardAgainstRace` call
|
|
622
|
-
// in tryToReauthenticate.
|
|
623
|
-
// However, the config version no longer matches, so we return { isFromOutdatedConfig: true }
|
|
624
|
-
// and exit from tryToReauthenticate early. Notably, before `tryRestartSocket` is called,
|
|
625
|
-
// so the connection is still stopped.
|
|
626
|
-
|
|
627
|
-
// At ts=3, we get a result from `fetchToken` from the scheduled refetch.
|
|
628
|
-
// This time we return the token since the config version matches.
|
|
629
|
-
|
|
630
|
-
// Previously, `refetchToken` would not call `tryRestartSocket`, so the WS would
|
|
631
|
-
// stay stopped.
|
|
632
|
-
|
|
633
|
-
// Now that `tryRestartSocket` is called, we should expect to see an Authenticate
|
|
634
|
-
// message with `scheduledRefetchToken`
|
|
635
|
-
await assertReconnectWithAuth(receive, {
|
|
636
|
-
baseVersion: 0,
|
|
637
|
-
token: scheduledRefetchToken,
|
|
638
|
-
});
|
|
639
|
-
|
|
640
|
-
send({
|
|
641
|
-
type: "Transition",
|
|
642
|
-
startVersion: {
|
|
643
|
-
...querySetVersion,
|
|
644
|
-
identity: 0,
|
|
645
|
-
},
|
|
646
|
-
endVersion: {
|
|
647
|
-
...querySetVersion,
|
|
648
|
-
identity: 1,
|
|
649
|
-
},
|
|
650
|
-
modifications: [],
|
|
651
|
-
});
|
|
652
|
-
|
|
653
|
-
await client.close();
|
|
654
|
-
vi.useRealTimers();
|
|
655
|
-
|
|
656
|
-
expect(onChange).toHaveBeenCalledTimes(2);
|
|
657
|
-
expect(onChange).toHaveBeenNthCalledWith(1, true);
|
|
658
|
-
expect(onChange).toHaveBeenNthCalledWith(2, true);
|
|
659
|
-
});
|
|
660
|
-
});
|
|
661
|
-
|
|
662
|
-
// When awaiting server confirmation of a fresh token, a subsequent
|
|
663
|
-
// auth error (from an Authenticate request) will cause the client to go to
|
|
664
|
-
// an unauthenticated state. This test covers a race condition where an
|
|
665
|
-
// Authenticate request for a fresh token is sent, and then the client app
|
|
666
|
-
// goes to background and misses the Transition response. If the client
|
|
667
|
-
// becomes active after the new token has expired, a new Authenticate request
|
|
668
|
-
// will be sent with the expired token, leading to an error response and
|
|
669
|
-
// unauthenticated state.
|
|
670
|
-
test("Client retries token validation on error", async () => {
|
|
671
|
-
await withInMemoryWebSocket(async ({ address, receive, send, close }) => {
|
|
672
|
-
const { client, baseClient } = testReactClient(address);
|
|
673
|
-
const ts = Math.ceil(Date.now() / 1000);
|
|
674
|
-
const token1 = jwtEncode({ iat: ts, exp: ts + 60 }, "token1");
|
|
675
|
-
const token2 = jwtEncode({ iat: ts, exp: ts + 60 }, "token2");
|
|
676
|
-
const token3 = jwtEncode({ iat: ts, exp: ts + 60 }, "token3");
|
|
677
|
-
const tokens = [token1, token2, token3];
|
|
678
|
-
const tokenFetcher = vi.fn(async (_opts) => tokens.shift()!);
|
|
679
|
-
const onChange = vi.fn();
|
|
680
|
-
client.setAuth(tokenFetcher, onChange);
|
|
681
|
-
|
|
682
|
-
await assertReconnectWithAuth(receive, {
|
|
683
|
-
baseVersion: 0,
|
|
684
|
-
token: token1,
|
|
685
|
-
});
|
|
686
|
-
|
|
687
|
-
const querySetVersion = baseClient["remoteQuerySet"]["version"];
|
|
688
|
-
|
|
689
|
-
send({
|
|
690
|
-
type: "Transition",
|
|
691
|
-
startVersion: {
|
|
692
|
-
...querySetVersion,
|
|
693
|
-
identity: 0,
|
|
694
|
-
},
|
|
695
|
-
endVersion: {
|
|
696
|
-
...querySetVersion,
|
|
697
|
-
identity: 1,
|
|
698
|
-
},
|
|
699
|
-
modifications: [],
|
|
700
|
-
});
|
|
701
|
-
|
|
702
|
-
assertAuthenticateMessage(await receive(), {
|
|
703
|
-
baseVersion: 1,
|
|
704
|
-
token: token2,
|
|
705
|
-
});
|
|
706
|
-
|
|
707
|
-
// Simulating an auth error while waiting for server confirmation of a
|
|
708
|
-
// fresh token.
|
|
709
|
-
await simulateAuthError({
|
|
710
|
-
send,
|
|
711
|
-
close,
|
|
712
|
-
authError: {
|
|
713
|
-
type: "AuthError",
|
|
714
|
-
error: "bla",
|
|
715
|
-
baseVersion: 1,
|
|
716
|
-
authUpdateAttempted: true,
|
|
717
|
-
},
|
|
718
|
-
});
|
|
719
|
-
// The client should reattempt reauthentication.
|
|
720
|
-
await assertReconnectWithAuth(receive, {
|
|
721
|
-
baseVersion: 0,
|
|
722
|
-
token: token3,
|
|
723
|
-
});
|
|
724
|
-
send({
|
|
725
|
-
type: "Transition",
|
|
726
|
-
startVersion: {
|
|
727
|
-
...querySetVersion,
|
|
728
|
-
identity: 0,
|
|
729
|
-
},
|
|
730
|
-
endVersion: {
|
|
731
|
-
...querySetVersion,
|
|
732
|
-
identity: 1,
|
|
733
|
-
},
|
|
734
|
-
modifications: [],
|
|
735
|
-
});
|
|
736
|
-
|
|
737
|
-
// Flush
|
|
738
|
-
await new Promise((resolve) => setTimeout(resolve));
|
|
739
|
-
await client.close();
|
|
740
|
-
|
|
741
|
-
expect(tokenFetcher).toHaveBeenCalledTimes(3);
|
|
742
|
-
// Initial setConfig
|
|
743
|
-
expect(tokenFetcher).toHaveBeenNthCalledWith(1, {
|
|
744
|
-
forceRefreshToken: false,
|
|
745
|
-
});
|
|
746
|
-
// Initial fresh token fetch
|
|
747
|
-
expect(tokenFetcher).toHaveBeenNthCalledWith(2, {
|
|
748
|
-
forceRefreshToken: true,
|
|
749
|
-
});
|
|
750
|
-
// Reauth second attempt
|
|
751
|
-
expect(tokenFetcher).toHaveBeenNthCalledWith(3, {
|
|
752
|
-
forceRefreshToken: true,
|
|
753
|
-
});
|
|
754
|
-
expect(onChange).toHaveBeenCalledTimes(2);
|
|
755
|
-
// Initial setConfig
|
|
756
|
-
expect(onChange).toHaveBeenNthCalledWith(1, true);
|
|
757
|
-
// Reauth second attempt
|
|
758
|
-
expect(onChange).toHaveBeenNthCalledWith(2, true);
|
|
759
|
-
});
|
|
760
|
-
});
|
|
761
|
-
|
|
762
|
-
test("Authentication runs first", async () => {
|
|
763
|
-
await withInMemoryWebSocket(async ({ address, receive, send }) => {
|
|
764
|
-
const { client, baseClient } = testReactClient(address);
|
|
765
|
-
|
|
766
|
-
const token1 = jwtEncode({ iat: 1234500, exp: 1244500 }, "secret");
|
|
767
|
-
const tokenFetcher = vi.fn(async () => token1);
|
|
768
|
-
client.setAuth(tokenFetcher);
|
|
769
|
-
|
|
770
|
-
await assertReconnectWithAuth(receive, {
|
|
771
|
-
baseVersion: 0,
|
|
772
|
-
token: token1,
|
|
773
|
-
});
|
|
774
|
-
|
|
775
|
-
const querySetVersion = baseClient["remoteQuerySet"]["version"];
|
|
776
|
-
|
|
777
|
-
send({
|
|
778
|
-
type: "Transition",
|
|
779
|
-
startVersion: querySetVersion,
|
|
780
|
-
endVersion: {
|
|
781
|
-
...querySetVersion,
|
|
782
|
-
// Client started at 0
|
|
783
|
-
// Good token advanced to 1
|
|
784
|
-
identity: 1,
|
|
785
|
-
},
|
|
786
|
-
modifications: [],
|
|
787
|
-
});
|
|
788
|
-
|
|
789
|
-
const token2 = jwtEncode({ iat: 1234550, exp: 1244550 }, "secret");
|
|
790
|
-
const tokenFetcher2 = vi.fn(async () => token2);
|
|
791
|
-
client.setAuth(tokenFetcher2);
|
|
792
|
-
client.watchQuery(anyApi.myQuery.default).onUpdate(() => {});
|
|
793
|
-
|
|
794
|
-
// Crucially Authenticate comes first!
|
|
795
|
-
assertAuthenticateMessage(await receive(), {
|
|
796
|
-
baseVersion: 1,
|
|
797
|
-
token: token2,
|
|
798
|
-
});
|
|
799
|
-
expect((await receive()).type).toEqual("ModifyQuerySet");
|
|
800
|
-
});
|
|
801
|
-
});
|
|
802
|
-
|
|
803
|
-
test("Auth pause doesn't prevent unsubscribing from queries", async () => {
|
|
804
|
-
await withInMemoryWebSocket(async ({ address, receive, send }) => {
|
|
805
|
-
const { client, baseClient } = testReactClient(address);
|
|
806
|
-
|
|
807
|
-
const token1 = jwtEncode({ iat: 1234500, exp: 1244500 }, "secret");
|
|
808
|
-
const tokenFetcher = vi.fn(async () => token1);
|
|
809
|
-
client.setAuth(tokenFetcher);
|
|
810
|
-
|
|
811
|
-
const unsubscribe = client
|
|
812
|
-
.watchQuery(anyApi.myQuery.default)
|
|
813
|
-
.onUpdate(() => {});
|
|
814
|
-
|
|
815
|
-
await assertReconnectWithAuth(receive, {
|
|
816
|
-
baseVersion: 0,
|
|
817
|
-
token: token1,
|
|
818
|
-
});
|
|
819
|
-
|
|
820
|
-
const querySetVersion = baseClient["remoteQuerySet"]["version"];
|
|
821
|
-
|
|
822
|
-
send({
|
|
823
|
-
type: "Transition",
|
|
824
|
-
startVersion: querySetVersion,
|
|
825
|
-
endVersion: {
|
|
826
|
-
querySet: 1,
|
|
827
|
-
identity: 1,
|
|
828
|
-
ts: Long.fromNumber(1),
|
|
829
|
-
},
|
|
830
|
-
modifications: [
|
|
831
|
-
{
|
|
832
|
-
type: "QueryUpdated",
|
|
833
|
-
queryId: 0,
|
|
834
|
-
value: 42,
|
|
835
|
-
logLines: [],
|
|
836
|
-
journal: null,
|
|
837
|
-
},
|
|
838
|
-
],
|
|
839
|
-
});
|
|
840
|
-
|
|
841
|
-
await waitForExpect(() => {
|
|
842
|
-
expect(baseClient["remoteQuerySet"]["version"].identity).toEqual(1);
|
|
843
|
-
});
|
|
844
|
-
|
|
845
|
-
let resolve: (value: string) => void;
|
|
846
|
-
const tokenFetcher2 = vi.fn(
|
|
847
|
-
() =>
|
|
848
|
-
new Promise<string>((r) => {
|
|
849
|
-
resolve = r;
|
|
850
|
-
}),
|
|
851
|
-
);
|
|
852
|
-
// Set new auth
|
|
853
|
-
client.setAuth(tokenFetcher2);
|
|
854
|
-
|
|
855
|
-
// Unsubscribe
|
|
856
|
-
unsubscribe();
|
|
857
|
-
|
|
858
|
-
// Finish fetching the token
|
|
859
|
-
const token2 = jwtEncode({ iat: 1234550, exp: 1244550 }, "secret");
|
|
860
|
-
resolve!(token2);
|
|
861
|
-
|
|
862
|
-
// Crucially Authenticate comes first!
|
|
863
|
-
assertAuthenticateMessage(await receive(), {
|
|
864
|
-
baseVersion: 1,
|
|
865
|
-
token: token2,
|
|
866
|
-
});
|
|
867
|
-
expect(await receive()).toMatchObject({
|
|
868
|
-
type: "ModifyQuerySet",
|
|
869
|
-
modifications: [{ type: "Remove", queryId: 0 }],
|
|
870
|
-
baseVersion: 1,
|
|
871
|
-
});
|
|
872
|
-
|
|
873
|
-
// Make sure we are now unpaused
|
|
874
|
-
|
|
875
|
-
client.watchQuery(anyApi.myQuery.default).onUpdate(() => {});
|
|
876
|
-
|
|
877
|
-
expect(await receive()).toMatchObject({
|
|
878
|
-
type: "ModifyQuerySet",
|
|
879
|
-
modifications: [{ type: "Add", queryId: 1 }],
|
|
880
|
-
baseVersion: 2,
|
|
881
|
-
});
|
|
882
|
-
|
|
883
|
-
client.watchQuery(anyApi.myQuery.foo).onUpdate(() => {});
|
|
884
|
-
|
|
885
|
-
expect(await receive()).toMatchObject({
|
|
886
|
-
type: "ModifyQuerySet",
|
|
887
|
-
modifications: [{ type: "Add", queryId: 2 }],
|
|
888
|
-
baseVersion: 3,
|
|
889
|
-
});
|
|
890
|
-
});
|
|
891
|
-
});
|
|
892
|
-
|
|
893
|
-
test("Local state resume doesn't cause duplicate AddQuery", async () => {
|
|
894
|
-
await withInMemoryWebSocket(async ({ address, receive }) => {
|
|
895
|
-
const { client } = testReactClient(address);
|
|
896
|
-
|
|
897
|
-
// First we subscribe
|
|
898
|
-
client.watchQuery(anyApi.myQuery.default).onUpdate(() => {});
|
|
899
|
-
|
|
900
|
-
expect((await receive()).type).toEqual("Connect");
|
|
901
|
-
expect(await receive()).toMatchObject({
|
|
902
|
-
type: "ModifyQuerySet",
|
|
903
|
-
modifications: [{ type: "Add", queryId: 0 }],
|
|
904
|
-
baseVersion: 0,
|
|
905
|
-
});
|
|
906
|
-
|
|
907
|
-
// Before the server confirms, we set auth, leading to pause
|
|
908
|
-
// and unpause.
|
|
909
|
-
const tokenFetcher = vi.fn(async () =>
|
|
910
|
-
jwtEncode({ iat: 1234500, exp: 1244500 }, "secret"),
|
|
911
|
-
);
|
|
912
|
-
client.setAuth(tokenFetcher);
|
|
913
|
-
|
|
914
|
-
// We should only send Authenticate, since we already
|
|
915
|
-
// sent the Add modification
|
|
916
|
-
expect(await receive()).toMatchObject({
|
|
917
|
-
type: "Authenticate",
|
|
918
|
-
baseVersion: 0,
|
|
919
|
-
});
|
|
920
|
-
|
|
921
|
-
// Subscribe again
|
|
922
|
-
client
|
|
923
|
-
.watchQuery(anyApi.myQuery.default, { foo: "bla" })
|
|
924
|
-
.onUpdate(() => {});
|
|
925
|
-
// Now we're sending the second query, not the first!
|
|
926
|
-
expect(await receive()).toMatchObject({
|
|
927
|
-
type: "ModifyQuerySet",
|
|
928
|
-
modifications: [{ type: "Add", queryId: 1 }],
|
|
929
|
-
baseVersion: 1,
|
|
930
|
-
});
|
|
931
|
-
});
|
|
932
|
-
});
|
|
933
|
-
|
|
934
|
-
test("Local state resume doesn't send both Add and Remove", async () => {
|
|
935
|
-
await withInMemoryWebSocket(async ({ address, receive }) => {
|
|
936
|
-
const { client } = testReactClient(address);
|
|
937
|
-
|
|
938
|
-
// First we subscribe to kick off connect.
|
|
939
|
-
client.watchQuery(anyApi.myQuery.default).onUpdate(() => {});
|
|
940
|
-
|
|
941
|
-
expect((await receive()).type).toEqual("Connect");
|
|
942
|
-
expect(await receive()).toMatchObject({
|
|
943
|
-
type: "ModifyQuerySet",
|
|
944
|
-
modifications: [{ type: "Add", queryId: 0 }],
|
|
945
|
-
baseVersion: 0,
|
|
946
|
-
});
|
|
947
|
-
|
|
948
|
-
// Set slow auth, causing pause
|
|
949
|
-
let resolve: (value: string) => void;
|
|
950
|
-
const tokenFetcher2 = vi.fn(
|
|
951
|
-
() =>
|
|
952
|
-
new Promise<string>((r) => {
|
|
953
|
-
resolve = r;
|
|
954
|
-
}),
|
|
955
|
-
);
|
|
956
|
-
client.setAuth(tokenFetcher2);
|
|
957
|
-
|
|
958
|
-
// Subscribe to second query, while paused
|
|
959
|
-
const unsubscribe = client
|
|
960
|
-
.watchQuery(anyApi.myQuery.default, { foo: "bla" })
|
|
961
|
-
.onUpdate(() => {});
|
|
962
|
-
|
|
963
|
-
// Subscribe third query, while paused
|
|
964
|
-
client
|
|
965
|
-
.watchQuery(anyApi.myQuery.default, { foo: "da" })
|
|
966
|
-
.onUpdate(() => {});
|
|
967
|
-
|
|
968
|
-
// Unsubscribe from second query, while paused
|
|
969
|
-
unsubscribe();
|
|
970
|
-
|
|
971
|
-
// Unpause ie resume
|
|
972
|
-
resolve!(jwtEncode({ iat: 1234550, exp: 1244550 }, "secret"));
|
|
973
|
-
|
|
974
|
-
// We authenticate first
|
|
975
|
-
expect(await receive()).toMatchObject({
|
|
976
|
-
type: "Authenticate",
|
|
977
|
-
baseVersion: 0,
|
|
978
|
-
});
|
|
979
|
-
|
|
980
|
-
// We subscribe to the third query only!
|
|
981
|
-
expect(await receive()).toMatchObject({
|
|
982
|
-
type: "ModifyQuerySet",
|
|
983
|
-
modifications: [{ type: "Add", queryId: 2 }],
|
|
984
|
-
baseVersion: 1,
|
|
985
|
-
});
|
|
986
|
-
});
|
|
987
|
-
});
|
|
988
|
-
|
|
989
|
-
test("Local state resume refcounts", async () => {
|
|
990
|
-
await withInMemoryWebSocket(async ({ address, receive }) => {
|
|
991
|
-
const { client } = testReactClient(address);
|
|
992
|
-
|
|
993
|
-
// First we subscribe to kick off connect.
|
|
994
|
-
client.watchQuery(anyApi.myQuery.default).onUpdate(() => {});
|
|
995
|
-
|
|
996
|
-
expect((await receive()).type).toEqual("Connect");
|
|
997
|
-
expect(await receive()).toMatchObject({
|
|
998
|
-
type: "ModifyQuerySet",
|
|
999
|
-
modifications: [{ type: "Add", queryId: 0 }],
|
|
1000
|
-
baseVersion: 0,
|
|
1001
|
-
});
|
|
1002
|
-
|
|
1003
|
-
// Set slow auth, causing pause
|
|
1004
|
-
let resolve: (value: string) => void;
|
|
1005
|
-
const tokenFetcher2 = vi.fn(
|
|
1006
|
-
() =>
|
|
1007
|
-
new Promise<string>((r) => {
|
|
1008
|
-
resolve = r;
|
|
1009
|
-
}),
|
|
1010
|
-
);
|
|
1011
|
-
client.setAuth(tokenFetcher2);
|
|
1012
|
-
|
|
1013
|
-
// Subscribe to second query, while paused
|
|
1014
|
-
const unsubscribe = client
|
|
1015
|
-
.watchQuery(anyApi.myQuery.default, { foo: "bla" })
|
|
1016
|
-
.onUpdate(() => {});
|
|
1017
|
-
|
|
1018
|
-
// Subscribe to the same query, while paused
|
|
1019
|
-
client
|
|
1020
|
-
.watchQuery(anyApi.myQuery.default, { foo: "bla" })
|
|
1021
|
-
.onUpdate(() => {});
|
|
1022
|
-
|
|
1023
|
-
// Unsubscribe once from the second query, while paused
|
|
1024
|
-
unsubscribe();
|
|
1025
|
-
|
|
1026
|
-
// Unpause ie resume
|
|
1027
|
-
resolve!(jwtEncode({ iat: 1234550, exp: 1244550 }, "secret"));
|
|
1028
|
-
|
|
1029
|
-
// We authenticate first
|
|
1030
|
-
expect(await receive()).toMatchObject({
|
|
1031
|
-
type: "Authenticate",
|
|
1032
|
-
baseVersion: 0,
|
|
1033
|
-
});
|
|
1034
|
-
|
|
1035
|
-
// We subscribe to the second query, because there's still one subscriber
|
|
1036
|
-
// on it.
|
|
1037
|
-
expect(await receive()).toMatchObject({
|
|
1038
|
-
type: "ModifyQuerySet",
|
|
1039
|
-
modifications: [{ type: "Add", queryId: 1 }],
|
|
1040
|
-
baseVersion: 1,
|
|
1041
|
-
});
|
|
1042
|
-
});
|
|
1043
|
-
});
|
|
1044
|
-
|
|
1045
|
-
test("Local state restart doesn't send both Add and Remove", async () => {
|
|
1046
|
-
await withInMemoryWebSocket(async ({ address, receive }) => {
|
|
1047
|
-
const { client } = testReactClient(address);
|
|
1048
|
-
|
|
1049
|
-
// Set slow auth, causing pause while connecting
|
|
1050
|
-
let resolve: (value: string) => void;
|
|
1051
|
-
const tokenFetcher2 = vi.fn(
|
|
1052
|
-
() =>
|
|
1053
|
-
new Promise<string>((r) => {
|
|
1054
|
-
resolve = r;
|
|
1055
|
-
}),
|
|
1056
|
-
);
|
|
1057
|
-
client.setAuth(tokenFetcher2);
|
|
1058
|
-
|
|
1059
|
-
// Subscribe while paused and connecting
|
|
1060
|
-
const unsubscribe = client
|
|
1061
|
-
.watchQuery(anyApi.myQuery.default)
|
|
1062
|
-
.onUpdate(() => {});
|
|
1063
|
-
|
|
1064
|
-
// Unsubscribe while paused and connecting
|
|
1065
|
-
unsubscribe();
|
|
1066
|
-
|
|
1067
|
-
// Unpause
|
|
1068
|
-
resolve!(jwtEncode({ iat: 1234550, exp: 1244550 }, "secret"));
|
|
1069
|
-
|
|
1070
|
-
expect((await receive()).type).toEqual("Connect");
|
|
1071
|
-
expect((await receive()).type).toEqual("Authenticate");
|
|
1072
|
-
expect(await receive()).toMatchObject({
|
|
1073
|
-
type: "ModifyQuerySet",
|
|
1074
|
-
baseVersion: 0,
|
|
1075
|
-
modifications: [],
|
|
1076
|
-
});
|
|
1077
|
-
});
|
|
1078
|
-
});
|
|
1079
|
-
});
|
|
1080
|
-
|
|
1081
|
-
// When a client is created it can't necessarily have setAuth called
|
|
1082
|
-
// on it right away: often that library needs some setup.
|
|
1083
|
-
describe.sequential("authMode WebSocket", () => {
|
|
1084
|
-
test.each([false, true])("expectAuth: %s", async (expectAuth: boolean) => {
|
|
1085
|
-
await withInMemoryWebSocket(async ({ address, receive, close }) => {
|
|
1086
|
-
const { client } = testReactClient(
|
|
1087
|
-
address,
|
|
1088
|
-
expectAuth ? { expectAuth: true } : {},
|
|
1089
|
-
);
|
|
1090
|
-
|
|
1091
|
-
// ConvexReactClient connect is lazy, you have to subscribe to
|
|
1092
|
-
// a query or otherwise make a request before anything happens.
|
|
1093
|
-
const _mutP = client.mutation(anyApi.myMutation.default, {});
|
|
1094
|
-
|
|
1095
|
-
// If expectAuth isn't enabled, this kicks off connect etc.
|
|
1096
|
-
if (!expectAuth) {
|
|
1097
|
-
expect((await receive()).type).toBe("Connect");
|
|
1098
|
-
expect((await receive()).type).toBe("ModifyQuerySet");
|
|
1099
|
-
expect((await receive()).type).toBe("Mutation");
|
|
1100
|
-
} else {
|
|
1101
|
-
// but *nothing* happens if expectAuth is set.
|
|
1102
|
-
}
|
|
1103
|
-
|
|
1104
|
-
let resolve: (value: string) => void;
|
|
1105
|
-
const tokenFetcher2 = vi.fn(
|
|
1106
|
-
() =>
|
|
1107
|
-
new Promise<string>((r) => {
|
|
1108
|
-
resolve = r;
|
|
1109
|
-
}),
|
|
1110
|
-
);
|
|
1111
|
-
const onAuthChange = vi.fn();
|
|
1112
|
-
client.setAuth(tokenFetcher2, onAuthChange);
|
|
1113
|
-
|
|
1114
|
-
resolve!(jwtEncode({ iat: 1234550, exp: 1244550 }, "secret"));
|
|
1115
|
-
|
|
1116
|
-
if (!expectAuth) {
|
|
1117
|
-
expect((await receive()).type).toBe("Authenticate");
|
|
1118
|
-
} else {
|
|
1119
|
-
// We're still paused until auth is returned
|
|
1120
|
-
expect((await receive()).type).toBe("Connect");
|
|
1121
|
-
expect((await receive()).type).toBe("Authenticate");
|
|
1122
|
-
expect((await receive()).type).toBe("ModifyQuerySet");
|
|
1123
|
-
expect((await receive()).type).toBe("Mutation");
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
await client.close();
|
|
1127
|
-
close();
|
|
1128
|
-
}, true);
|
|
1129
|
-
});
|
|
1130
|
-
});
|
|
1131
|
-
|
|
1132
|
-
function assertAuthenticateMessage(
|
|
1133
|
-
message: ClientMessage,
|
|
1134
|
-
expected: {
|
|
1135
|
-
baseVersion: number;
|
|
1136
|
-
token: string;
|
|
1137
|
-
},
|
|
1138
|
-
) {
|
|
1139
|
-
expect(message.type).toEqual("Authenticate");
|
|
1140
|
-
// (These errors are redundant, but are necessary for type narrowing)
|
|
1141
|
-
if (message.type !== "Authenticate") {
|
|
1142
|
-
throw new Error("Expected an Authenticate message");
|
|
1143
|
-
}
|
|
1144
|
-
expect(message.baseVersion).toEqual(expected.baseVersion);
|
|
1145
|
-
expect(message.tokenType).toEqual("User");
|
|
1146
|
-
if (message.tokenType !== "User") {
|
|
1147
|
-
throw new Error("Expected a User token");
|
|
1148
|
-
}
|
|
1149
|
-
expect(message.value).toEqual(expected.token);
|
|
1150
|
-
}
|
|
1151
|
-
|
|
1152
|
-
async function assertReconnectWithAuth(
|
|
1153
|
-
receive: () => Promise<ClientMessage>,
|
|
1154
|
-
expectedAuth: {
|
|
1155
|
-
baseVersion: number;
|
|
1156
|
-
token: string;
|
|
1157
|
-
},
|
|
1158
|
-
) {
|
|
1159
|
-
expect((await receive()).type).toEqual("Connect");
|
|
1160
|
-
assertAuthenticateMessage(await receive(), expectedAuth);
|
|
1161
|
-
expect((await receive()).type).toEqual("ModifyQuerySet");
|
|
1162
|
-
}
|
|
1163
|
-
|
|
1164
|
-
async function simulateAuthError(args: {
|
|
1165
|
-
send: (message: WireServerMessage) => void;
|
|
1166
|
-
close: () => void;
|
|
1167
|
-
authError: AuthError;
|
|
1168
|
-
}) {
|
|
1169
|
-
args.send({
|
|
1170
|
-
type: "AuthError",
|
|
1171
|
-
error: args.authError.error,
|
|
1172
|
-
baseVersion: args.authError.baseVersion,
|
|
1173
|
-
authUpdateAttempted: args.authError.authUpdateAttempted,
|
|
1174
|
-
});
|
|
1175
|
-
// The server always closes the connection after an AuthError
|
|
1176
|
-
args.close();
|
|
1177
|
-
}
|