convex 1.42.2 → 1.43.0-alpha.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 +8 -1
- package/bin/main-dev +6 -1
- package/dist/browser.bundle.js +49 -10
- package/dist/browser.bundle.js.map +2 -2
- package/dist/cjs/browser/index.js.map +2 -2
- package/dist/cjs/browser/simple_client-node.js +35 -35
- package/dist/cjs/browser/simple_client-node.js.map +2 -2
- package/dist/cjs/browser/sync/client.js.map +1 -1
- package/dist/cjs/browser/sync/paginated_query_client.js +20 -9
- package/dist/cjs/browser/sync/paginated_query_client.js.map +2 -2
- package/dist/cjs/cli/codegen_templates/component_api.js +2 -2
- package/dist/cjs/cli/codegen_templates/component_api.js.map +2 -2
- package/dist/cjs/cli/codegen_templates/validator_helpers.js +2 -0
- package/dist/cjs/cli/codegen_templates/validator_helpers.js.map +2 -2
- package/dist/cjs/cli/deployment.js +2 -1
- package/dist/cjs/cli/deployment.js.map +2 -2
- package/dist/cjs/cli/deploymentCreate.js.map +2 -2
- package/dist/cjs/cli/generatedApi.js.map +1 -1
- package/dist/cjs/cli/lib/deployApi/validator.js +1 -0
- package/dist/cjs/cli/lib/deployApi/validator.js.map +2 -2
- package/dist/cjs/cli/lib/deploymentSelection.js.map +2 -2
- package/dist/cjs/cli/lib/generateDocs.js +1 -1
- package/dist/cjs/cli/lib/generateDocs.js.map +2 -2
- package/dist/cjs/cli/lib/generatedFunctionLogsApi.js.map +1 -1
- package/dist/cjs/cli/lib/localDeployment/projectMismatch.js.map +2 -2
- package/dist/cjs/cli/lib/login.js +23 -23
- package/dist/cjs/cli/lib/login.js.map +2 -2
- package/dist/cjs/cli/lib/typecheck.js +28 -25
- package/dist/cjs/cli/lib/typecheck.js.map +2 -2
- package/dist/cjs/cli/lib/usageLimits.js +164 -0
- package/dist/cjs/cli/lib/usageLimits.js.map +7 -0
- package/dist/cjs/cli/usageLimits.js +326 -0
- package/dist/cjs/cli/usageLimits.js.map +7 -0
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/react/client.js.map +2 -2
- package/dist/cjs/server/components/index.js.map +2 -2
- package/dist/cjs/server/cron.js +33 -29
- package/dist/cjs/server/cron.js.map +2 -2
- package/dist/cjs/server/database.js.map +1 -1
- package/dist/cjs/server/impl/database_impl.js +3 -0
- package/dist/cjs/server/impl/database_impl.js.map +2 -2
- package/dist/cjs/server/log.js +2 -1
- package/dist/cjs/server/log.js.map +2 -2
- package/dist/cjs/server/logVars.js +12 -1
- package/dist/cjs/server/logVars.js.map +2 -2
- package/dist/cjs/server/meta.js.map +1 -1
- package/dist/cjs/values/compare.js +5 -1
- package/dist/cjs/values/compare.js.map +2 -2
- package/dist/cjs/values/index.js +1 -0
- package/dist/cjs/values/index.js.map +2 -2
- package/dist/cjs/values/size.js +4 -0
- package/dist/cjs/values/size.js.map +2 -2
- package/dist/cjs/values/validator.js +11 -0
- package/dist/cjs/values/validator.js.map +2 -2
- package/dist/cjs/values/validators.js +20 -0
- package/dist/cjs/values/validators.js.map +2 -2
- package/dist/cjs/values/value.js +31 -0
- package/dist/cjs/values/value.js.map +2 -2
- package/dist/cjs-types/browser/index.d.ts.map +1 -1
- package/dist/cjs-types/browser/sync/paginated_query_client.d.ts +1 -38
- package/dist/cjs-types/browser/sync/paginated_query_client.d.ts.map +1 -1
- package/dist/cjs-types/cli/codegen_templates/component_api.d.ts.map +1 -1
- package/dist/cjs-types/cli/codegen_templates/validator_helpers.d.ts.map +1 -1
- package/dist/cjs-types/cli/codegen_templates/validator_helpers.test.d.ts +2 -0
- package/dist/cjs-types/cli/codegen_templates/validator_helpers.test.d.ts.map +1 -0
- package/dist/cjs-types/cli/deployment.d.ts.map +1 -1
- package/dist/cjs-types/cli/deploymentCreate.d.ts +2 -2
- package/dist/cjs-types/cli/generatedApi.d.ts +43 -43
- package/dist/cjs-types/cli/generatedApi.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/deployApi/validator.d.ts +6 -0
- package/dist/cjs-types/cli/lib/deployApi/validator.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/deploymentSelection.d.ts +2 -2
- package/dist/cjs-types/cli/lib/deploymentSelection.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts +45 -45
- package/dist/cjs-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/localDeployment/projectMismatch.d.ts +2 -2
- package/dist/cjs-types/cli/lib/localDeployment/projectMismatch.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/login.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/mcp/tools/insights.d.ts +24 -24
- package/dist/cjs-types/cli/lib/typecheck.d.ts +2 -0
- package/dist/cjs-types/cli/lib/typecheck.d.ts.map +1 -1
- package/dist/cjs-types/cli/lib/typecheck.test.d.ts +2 -0
- package/dist/cjs-types/cli/lib/typecheck.test.d.ts.map +1 -0
- package/dist/cjs-types/cli/lib/usageLimits.d.ts +46 -0
- package/dist/cjs-types/cli/lib/usageLimits.d.ts.map +1 -0
- package/dist/cjs-types/cli/usageLimits.d.ts +22 -0
- package/dist/cjs-types/cli/usageLimits.d.ts.map +1 -0
- package/dist/cjs-types/index.d.ts +1 -1
- package/dist/cjs-types/index.d.ts.map +1 -1
- package/dist/cjs-types/react/client.d.ts.map +1 -1
- package/dist/cjs-types/server/components/index.d.ts +26 -8
- package/dist/cjs-types/server/components/index.d.ts.map +1 -1
- package/dist/cjs-types/server/cron.d.ts +20 -11
- package/dist/cjs-types/server/cron.d.ts.map +1 -1
- package/dist/cjs-types/server/cron.test.d.ts +2 -0
- package/dist/cjs-types/server/cron.test.d.ts.map +1 -0
- package/dist/cjs-types/server/database.d.ts.map +1 -1
- package/dist/cjs-types/server/impl/database_impl.d.ts.map +1 -1
- package/dist/cjs-types/server/log.d.ts.map +1 -1
- package/dist/cjs-types/server/logVars.d.ts +14 -1
- package/dist/cjs-types/server/logVars.d.ts.map +1 -1
- package/dist/cjs-types/server/meta.d.ts +2 -2
- package/dist/cjs-types/server/meta.d.ts.map +1 -1
- package/dist/cjs-types/values/compare.d.ts.map +1 -1
- package/dist/cjs-types/values/index.d.ts +2 -2
- package/dist/cjs-types/values/index.d.ts.map +1 -1
- package/dist/cjs-types/values/size.d.ts +1 -1
- package/dist/cjs-types/values/size.d.ts.map +1 -1
- package/dist/cjs-types/values/validator.d.ts +10 -1
- package/dist/cjs-types/values/validator.d.ts.map +1 -1
- package/dist/cjs-types/values/validators.d.ts +14 -3
- package/dist/cjs-types/values/validators.d.ts.map +1 -1
- package/dist/cjs-types/values/value.d.ts +18 -1
- package/dist/cjs-types/values/value.d.ts.map +1 -1
- package/dist/cli.bundle.cjs +2327 -1866
- package/dist/cli.bundle.cjs.map +4 -4
- package/dist/esm/browser/index.js.map +2 -2
- package/dist/esm/browser/simple_client-node.js +35 -35
- package/dist/esm/browser/simple_client-node.js.map +1 -1
- package/dist/esm/browser/sync/client.js.map +1 -1
- package/dist/esm/browser/sync/paginated_query_client.js +20 -9
- package/dist/esm/browser/sync/paginated_query_client.js.map +2 -2
- package/dist/esm/cli/codegen_templates/component_api.js +8 -3
- package/dist/esm/cli/codegen_templates/component_api.js.map +2 -2
- package/dist/esm/cli/codegen_templates/validator_helpers.js +2 -0
- package/dist/esm/cli/codegen_templates/validator_helpers.js.map +2 -2
- package/dist/esm/cli/deployment.js +2 -1
- package/dist/esm/cli/deployment.js.map +2 -2
- package/dist/esm/cli/deploymentCreate.js.map +2 -2
- package/dist/esm/cli/lib/deployApi/validator.js +1 -0
- package/dist/esm/cli/lib/deployApi/validator.js.map +2 -2
- package/dist/esm/cli/lib/deploymentSelection.js.map +2 -2
- package/dist/esm/cli/lib/generateDocs.js +1 -1
- package/dist/esm/cli/lib/generateDocs.js.map +2 -2
- package/dist/esm/cli/lib/localDeployment/projectMismatch.js.map +2 -2
- package/dist/esm/cli/lib/login.js +23 -23
- package/dist/esm/cli/lib/login.js.map +2 -2
- package/dist/esm/cli/lib/typecheck.js +27 -25
- package/dist/esm/cli/lib/typecheck.js.map +2 -2
- package/dist/esm/cli/lib/usageLimits.js +129 -0
- package/dist/esm/cli/lib/usageLimits.js.map +7 -0
- package/dist/esm/cli/usageLimits.js +316 -0
- package/dist/esm/cli/usageLimits.js.map +7 -0
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/react/client.js.map +2 -2
- package/dist/esm/server/components/index.js.map +2 -2
- package/dist/esm/server/cron.js +33 -29
- package/dist/esm/server/cron.js.map +2 -2
- package/dist/esm/server/impl/database_impl.js +4 -1
- package/dist/esm/server/impl/database_impl.js.map +2 -2
- package/dist/esm/server/log.js +3 -2
- package/dist/esm/server/log.js.map +2 -2
- package/dist/esm/server/logVars.js +11 -1
- package/dist/esm/server/logVars.js.map +2 -2
- package/dist/esm/values/compare.js +5 -1
- package/dist/esm/values/compare.js.map +2 -2
- package/dist/esm/values/index.js +1 -1
- package/dist/esm/values/index.js.map +2 -2
- package/dist/esm/values/size.js +4 -0
- package/dist/esm/values/size.js.map +2 -2
- package/dist/esm/values/validator.js +12 -0
- package/dist/esm/values/validator.js.map +2 -2
- package/dist/esm/values/validators.js +19 -0
- package/dist/esm/values/validators.js.map +2 -2
- package/dist/esm/values/value.js +29 -1
- package/dist/esm/values/value.js.map +2 -2
- package/dist/esm-types/browser/index.d.ts.map +1 -1
- package/dist/esm-types/browser/sync/paginated_query_client.d.ts +1 -38
- package/dist/esm-types/browser/sync/paginated_query_client.d.ts.map +1 -1
- package/dist/esm-types/cli/codegen_templates/component_api.d.ts.map +1 -1
- package/dist/esm-types/cli/codegen_templates/validator_helpers.d.ts.map +1 -1
- package/dist/esm-types/cli/codegen_templates/validator_helpers.test.d.ts +2 -0
- package/dist/esm-types/cli/codegen_templates/validator_helpers.test.d.ts.map +1 -0
- package/dist/esm-types/cli/deployment.d.ts.map +1 -1
- package/dist/esm-types/cli/deploymentCreate.d.ts +2 -2
- package/dist/esm-types/cli/generatedApi.d.ts +43 -43
- package/dist/esm-types/cli/generatedApi.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/deployApi/validator.d.ts +6 -0
- package/dist/esm-types/cli/lib/deployApi/validator.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/deploymentSelection.d.ts +2 -2
- package/dist/esm-types/cli/lib/deploymentSelection.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts +45 -45
- package/dist/esm-types/cli/lib/generatedFunctionLogsApi.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/localDeployment/projectMismatch.d.ts +2 -2
- package/dist/esm-types/cli/lib/localDeployment/projectMismatch.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/login.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/mcp/tools/insights.d.ts +24 -24
- package/dist/esm-types/cli/lib/typecheck.d.ts +2 -0
- package/dist/esm-types/cli/lib/typecheck.d.ts.map +1 -1
- package/dist/esm-types/cli/lib/typecheck.test.d.ts +2 -0
- package/dist/esm-types/cli/lib/typecheck.test.d.ts.map +1 -0
- package/dist/esm-types/cli/lib/usageLimits.d.ts +46 -0
- package/dist/esm-types/cli/lib/usageLimits.d.ts.map +1 -0
- package/dist/esm-types/cli/usageLimits.d.ts +22 -0
- package/dist/esm-types/cli/usageLimits.d.ts.map +1 -0
- package/dist/esm-types/index.d.ts +1 -1
- package/dist/esm-types/index.d.ts.map +1 -1
- package/dist/esm-types/react/client.d.ts.map +1 -1
- package/dist/esm-types/server/components/index.d.ts +26 -8
- package/dist/esm-types/server/components/index.d.ts.map +1 -1
- package/dist/esm-types/server/cron.d.ts +20 -11
- package/dist/esm-types/server/cron.d.ts.map +1 -1
- package/dist/esm-types/server/cron.test.d.ts +2 -0
- package/dist/esm-types/server/cron.test.d.ts.map +1 -0
- package/dist/esm-types/server/database.d.ts.map +1 -1
- package/dist/esm-types/server/impl/database_impl.d.ts.map +1 -1
- package/dist/esm-types/server/log.d.ts.map +1 -1
- package/dist/esm-types/server/logVars.d.ts +14 -1
- package/dist/esm-types/server/logVars.d.ts.map +1 -1
- package/dist/esm-types/server/meta.d.ts +2 -2
- package/dist/esm-types/server/meta.d.ts.map +1 -1
- package/dist/esm-types/values/compare.d.ts.map +1 -1
- package/dist/esm-types/values/index.d.ts +2 -2
- package/dist/esm-types/values/index.d.ts.map +1 -1
- package/dist/esm-types/values/size.d.ts +1 -1
- package/dist/esm-types/values/size.d.ts.map +1 -1
- package/dist/esm-types/values/validator.d.ts +10 -1
- package/dist/esm-types/values/validator.d.ts.map +1 -1
- package/dist/esm-types/values/validators.d.ts +14 -3
- package/dist/esm-types/values/validators.d.ts.map +1 -1
- package/dist/esm-types/values/value.d.ts +18 -1
- package/dist/esm-types/values/value.d.ts.map +1 -1
- package/dist/react.bundle.js +53 -11
- package/dist/react.bundle.js.map +2 -2
- package/package.json +8 -8
- package/schemas/convex.schema.json +2 -1
- package/src/browser/index.ts +2 -0
- package/src/browser/sync/client.test.ts +8 -1
- package/src/browser/sync/client.ts +63 -0
- package/src/browser/sync/paginated_query_client.test.ts +209 -1
- package/src/browser/sync/paginated_query_client.ts +29 -11
- package/src/cli/codegen_templates/component_api.ts +8 -3
- package/src/cli/codegen_templates/validator_helpers.test.ts +31 -0
- package/src/cli/codegen_templates/validator_helpers.ts +6 -0
- package/src/cli/deployment.ts +4 -1
- package/src/cli/deploymentCreate.test.ts +2 -2
- package/src/cli/deploymentCreate.ts +2 -2
- package/src/cli/generatedApi.ts +43 -43
- package/src/cli/lib/deployApi/validator.ts +1 -0
- package/src/cli/lib/deploymentSelection.ts +2 -2
- package/src/cli/lib/generateDocs.test.ts +1 -1
- package/src/cli/lib/generateDocs.ts +3 -3
- package/src/cli/lib/generatedFunctionLogsApi.ts +45 -45
- package/src/cli/lib/localDeployment/projectMismatch.ts +2 -2
- package/src/cli/lib/login.ts +33 -30
- package/src/cli/lib/typecheck.test.ts +71 -0
- package/src/cli/lib/typecheck.ts +33 -27
- package/src/cli/lib/usageLimits.ts +242 -0
- package/src/cli/usageLimits.ts +420 -0
- package/src/index.ts +1 -1
- package/src/react/ConvexAuthState.test.tsx +24 -8
- package/src/react/auth_websocket.test.tsx +39 -29
- package/src/react/client.ts +3 -2
- package/src/react/client_provided_base_client.test.tsx +154 -36
- package/src/server/audit_logging.test.ts +2 -0
- package/src/server/components/index.test.ts +33 -1
- package/src/server/components/index.ts +41 -14
- package/src/server/cron.test.ts +58 -0
- package/src/server/cron.ts +82 -21
- package/src/server/database.ts +17 -0
- package/src/server/impl/database_impl.ts +4 -1
- package/src/server/log.ts +4 -1
- package/src/server/logVars.ts +17 -1
- package/src/server/meta.ts +2 -2
- package/src/server/schema.test.ts +6 -1
- package/src/values/compare.ts +5 -2
- package/src/values/index.ts +2 -1
- package/src/values/size.test.ts +5 -0
- package/src/values/size.ts +5 -1
- package/src/values/validator.test.ts +16 -1
- package/src/values/validator.ts +13 -0
- package/src/values/validators.ts +29 -1
- package/src/values/value.test.ts +35 -0
- package/src/values/value.ts +56 -1
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "convex",
|
|
3
3
|
"description": "Client for the Convex Cloud",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.43.0-alpha.0",
|
|
5
5
|
"author": "Convex, Inc. <no-reply@convex.dev>",
|
|
6
6
|
"homepage": "https://convex.dev",
|
|
7
7
|
"repository": {
|
|
@@ -204,10 +204,15 @@
|
|
|
204
204
|
"@babel/types": "^7.27.1",
|
|
205
205
|
"@clerk/react": "^6.4.3",
|
|
206
206
|
"@commander-js/extra-typings": "^14.0.0",
|
|
207
|
-
"@convex-dev/platform": "0.1.
|
|
207
|
+
"@convex-dev/platform": "0.1.10",
|
|
208
208
|
"@eslint/compat": "~2.0.0",
|
|
209
209
|
"@eslint/eslintrc": "^3",
|
|
210
210
|
"@eslint/js": "~9.39.0",
|
|
211
|
+
"@inquirer/confirm": "^6.0.4",
|
|
212
|
+
"@inquirer/input": "^5.0.4",
|
|
213
|
+
"@inquirer/search": "^4.1.0",
|
|
214
|
+
"@inquirer/select": "^5.0.4",
|
|
215
|
+
"@inquirer/testing": "^3.3.0",
|
|
211
216
|
"@modelcontextprotocol/sdk": "^1.25.2",
|
|
212
217
|
"@octokit/openapi-types": "~27.0.0",
|
|
213
218
|
"@sentry/node": "^7.23.0",
|
|
@@ -217,11 +222,6 @@
|
|
|
217
222
|
"@types/adm-zip": "^0.5.7",
|
|
218
223
|
"@types/babel__code-frame": "^7.0.6",
|
|
219
224
|
"@types/deep-equal": "1.0.4",
|
|
220
|
-
"@inquirer/confirm": "^6.0.4",
|
|
221
|
-
"@inquirer/input": "^5.0.4",
|
|
222
|
-
"@inquirer/search": "^4.1.0",
|
|
223
|
-
"@inquirer/select": "^5.0.4",
|
|
224
|
-
"@inquirer/testing": "^3.3.0",
|
|
225
225
|
"@types/node": "^18.17.0",
|
|
226
226
|
"@types/react": "^18.0.0",
|
|
227
227
|
"@types/react-dom": "^18.0.0",
|
|
@@ -271,8 +271,8 @@
|
|
|
271
271
|
"typedoc": "^0.24.6",
|
|
272
272
|
"typescript": "~5.0.3",
|
|
273
273
|
"typescript-eslint": "~8.57.0",
|
|
274
|
-
"vitest": "^4.1.0",
|
|
275
274
|
"undici": "7.28.0",
|
|
275
|
+
"vitest": "^4.1.0",
|
|
276
276
|
"wait-for-expect": "~4.0.0",
|
|
277
277
|
"zod": "^3.24.0",
|
|
278
278
|
"zod-to-json-schema": "^3.24.0"
|
|
@@ -180,7 +180,8 @@
|
|
|
180
180
|
"typescriptCompiler": {
|
|
181
181
|
"type": "string",
|
|
182
182
|
"enum": ["tsc", "tsgo"],
|
|
183
|
-
"description": "
|
|
183
|
+
"description": "Deprecated. Set to `tsgo` to use the TypeScript Native Preview compiler (`@typescript/native-preview`). TypeScript 7 uses the native compiler without needing this setting to be set.",
|
|
184
|
+
"deprecated": true
|
|
184
185
|
},
|
|
185
186
|
"authKit": {
|
|
186
187
|
"$ref": "#/definitions/authKitConfig"
|
package/src/browser/index.ts
CHANGED
|
@@ -24,6 +24,8 @@ export type {
|
|
|
24
24
|
ConnectionState,
|
|
25
25
|
AuthTokenFetcher,
|
|
26
26
|
} from "./sync/client.js";
|
|
27
|
+
/** @internal */
|
|
28
|
+
export type { BaseConvexClientInterface } from "./sync/client.js";
|
|
27
29
|
export type { PaginationStatus } from "./sync/pagination.js";
|
|
28
30
|
export type { ConvexClientOptions } from "./simple_client.js";
|
|
29
31
|
export { ConvexClient } from "./simple_client.js";
|
|
@@ -4,9 +4,16 @@
|
|
|
4
4
|
|
|
5
5
|
import { test, expect } from "vitest";
|
|
6
6
|
|
|
7
|
-
import { BaseConvexClient } from "./client.js";
|
|
7
|
+
import { BaseConvexClient, BaseConvexClientInterface } from "./client.js";
|
|
8
8
|
import { anyApi } from "../../server/api.js";
|
|
9
9
|
|
|
10
|
+
// Compile-time assertion that `BaseConvexClient` satisfies
|
|
11
|
+
// `BaseConvexClientInterface`. We can't use an `implements` clause on the class
|
|
12
|
+
// because `BaseConvexClientInterface` is `@internal`: that would leak the
|
|
13
|
+
// interface name into the public `.d.ts` where it has been stripped.
|
|
14
|
+
const _assertBaseConvexClientImplementsInterface: BaseConvexClientInterface =
|
|
15
|
+
undefined as unknown as BaseConvexClient;
|
|
16
|
+
|
|
10
17
|
test("localQueryResult reflects optimistic results", async () => {
|
|
11
18
|
const client = new BaseConvexClient("http://127.0.0.1:8000", () => {
|
|
12
19
|
// ignore updates.
|
|
@@ -1126,3 +1126,66 @@ export class BaseConvexClient {
|
|
|
1126
1126
|
});
|
|
1127
1127
|
}
|
|
1128
1128
|
}
|
|
1129
|
+
|
|
1130
|
+
/**
|
|
1131
|
+
* The public API of {@link BaseConvexClient}.
|
|
1132
|
+
*
|
|
1133
|
+
* @internal
|
|
1134
|
+
*/
|
|
1135
|
+
export interface BaseConvexClientInterface {
|
|
1136
|
+
addOnTransitionHandler(fn: (transition: Transition) => void): () => void;
|
|
1137
|
+
|
|
1138
|
+
setAuth(
|
|
1139
|
+
fetchToken: AuthTokenFetcher,
|
|
1140
|
+
onChange: (isAuthenticated: boolean) => void,
|
|
1141
|
+
onRefreshChange?: (isRefreshing: boolean) => void,
|
|
1142
|
+
): void;
|
|
1143
|
+
|
|
1144
|
+
/** @internal */
|
|
1145
|
+
setAdminAuth(value: string, fakeUserIdentity?: UserIdentityAttributes): void;
|
|
1146
|
+
|
|
1147
|
+
clearAuth(): void;
|
|
1148
|
+
|
|
1149
|
+
subscribe(
|
|
1150
|
+
name: string,
|
|
1151
|
+
args?: Record<string, Value>,
|
|
1152
|
+
options?: SubscribeOptions,
|
|
1153
|
+
): { queryToken: QueryToken; unsubscribe: () => void };
|
|
1154
|
+
|
|
1155
|
+
localQueryResult(
|
|
1156
|
+
udfPath: string,
|
|
1157
|
+
args?: Record<string, Value>,
|
|
1158
|
+
): Value | undefined;
|
|
1159
|
+
|
|
1160
|
+
localQueryResultByToken(queryToken: QueryToken): Value | undefined;
|
|
1161
|
+
|
|
1162
|
+
hasLocalQueryResultByToken(queryToken: QueryToken): boolean;
|
|
1163
|
+
|
|
1164
|
+
localQueryLogs(
|
|
1165
|
+
udfPath: string,
|
|
1166
|
+
args?: Record<string, Value>,
|
|
1167
|
+
): string[] | undefined;
|
|
1168
|
+
|
|
1169
|
+
queryJournal(
|
|
1170
|
+
name: string,
|
|
1171
|
+
args?: Record<string, Value>,
|
|
1172
|
+
): QueryJournal | undefined;
|
|
1173
|
+
|
|
1174
|
+
connectionState(): ConnectionState;
|
|
1175
|
+
|
|
1176
|
+
subscribeToConnectionState(
|
|
1177
|
+
cb: (connectionState: ConnectionState) => void,
|
|
1178
|
+
): () => void;
|
|
1179
|
+
|
|
1180
|
+
mutation(
|
|
1181
|
+
name: string,
|
|
1182
|
+
args?: Record<string, Value>,
|
|
1183
|
+
options?: MutationOptions,
|
|
1184
|
+
): Promise<any>;
|
|
1185
|
+
|
|
1186
|
+
action(name: string, args?: Record<string, Value>): Promise<any>;
|
|
1187
|
+
|
|
1188
|
+
close(): Promise<void>;
|
|
1189
|
+
|
|
1190
|
+
readonly url: string;
|
|
1191
|
+
}
|
|
@@ -1,17 +1,150 @@
|
|
|
1
1
|
import { test, expect, describe } from "vitest";
|
|
2
2
|
|
|
3
3
|
import { BaseConvexClient } from "./client.js";
|
|
4
|
-
import {
|
|
4
|
+
import {
|
|
5
|
+
ClientMessage,
|
|
6
|
+
QuerySetModification,
|
|
7
|
+
WireServerMessage,
|
|
8
|
+
} from "./protocol.js";
|
|
5
9
|
import {
|
|
6
10
|
nodeWebSocket,
|
|
7
11
|
UpdateQueue,
|
|
8
12
|
withInMemoryWebSocket,
|
|
9
13
|
} from "./client_node_test_helpers.js";
|
|
10
14
|
import { PaginationOptions } from "../../server/pagination.js";
|
|
15
|
+
import { JSONValue } from "../../values/index.js";
|
|
11
16
|
import { Long } from "../../vendor/long.js";
|
|
12
17
|
import { anyApi } from "../../server/index.js";
|
|
13
18
|
import { PaginatedQueryClient } from "./paginated_query_client.js";
|
|
14
19
|
|
|
20
|
+
/**
|
|
21
|
+
* A faithful in-memory pagination backend for the split test below. It answers
|
|
22
|
+
* each page query by slicing `data` according to the `cursor`/`endCursor` it
|
|
23
|
+
* actually receives, so the test can assert on the pages the client ends up
|
|
24
|
+
* with rather than on the arguments the client happened to send. Cursors are
|
|
25
|
+
* opaque to callers: internally they encode an offset into `data`.
|
|
26
|
+
*/
|
|
27
|
+
class FakePaginationServer {
|
|
28
|
+
// The client only requires each transition's startVersion to equal the
|
|
29
|
+
// previous endVersion; the querySet/ts numbers are otherwise unconstrained.
|
|
30
|
+
private querySetVersion = 0;
|
|
31
|
+
private ts = 0;
|
|
32
|
+
|
|
33
|
+
constructor(
|
|
34
|
+
private io: {
|
|
35
|
+
receive: () => Promise<ClientMessage>;
|
|
36
|
+
send: (message: WireServerMessage) => void;
|
|
37
|
+
},
|
|
38
|
+
private data: JSONValue[],
|
|
39
|
+
// A freshly loaded page (one requested without an endCursor) comes back with
|
|
40
|
+
// a `splitCursor` and `SplitRecommended` once it reaches this many items.
|
|
41
|
+
// Split halves carry an endCursor and are never re-split, so the server
|
|
42
|
+
// converges. Omit to never recommend a split.
|
|
43
|
+
private options: { splitThreshold?: number } = {},
|
|
44
|
+
) {}
|
|
45
|
+
|
|
46
|
+
private toOffset(cursor: string | null | undefined): number {
|
|
47
|
+
return cursor === null || cursor === undefined
|
|
48
|
+
? 0
|
|
49
|
+
: parseInt(cursor.slice(1));
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
private toCursor(offset: number): string {
|
|
53
|
+
return `c${offset}`;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
private pageResult(paginationOpts: {
|
|
57
|
+
cursor: string | null;
|
|
58
|
+
endCursor?: string | null;
|
|
59
|
+
numItems: number;
|
|
60
|
+
}): JSONValue {
|
|
61
|
+
const start = this.toOffset(paginationOpts.cursor);
|
|
62
|
+
const hasEndCursor =
|
|
63
|
+
paginationOpts.endCursor !== null &&
|
|
64
|
+
paginationOpts.endCursor !== undefined;
|
|
65
|
+
const end = hasEndCursor
|
|
66
|
+
? this.toOffset(paginationOpts.endCursor)
|
|
67
|
+
: Math.min(start + paginationOpts.numItems, this.data.length);
|
|
68
|
+
const page = this.data.slice(start, end);
|
|
69
|
+
const recommendSplit =
|
|
70
|
+
!hasEndCursor &&
|
|
71
|
+
this.options.splitThreshold !== undefined &&
|
|
72
|
+
page.length >= this.options.splitThreshold;
|
|
73
|
+
return {
|
|
74
|
+
page,
|
|
75
|
+
isDone: end >= this.data.length,
|
|
76
|
+
continueCursor: this.toCursor(end),
|
|
77
|
+
splitCursor: recommendSplit
|
|
78
|
+
? this.toCursor(start + Math.floor(page.length / 2))
|
|
79
|
+
: null,
|
|
80
|
+
pageStatus: recommendSplit ? "SplitRecommended" : null,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Consume the connection handshake: the client's `Connect` message and the
|
|
86
|
+
* (empty) query set it sends on connecting.
|
|
87
|
+
*/
|
|
88
|
+
async awaitConnect(): Promise<void> {
|
|
89
|
+
const connect = await this.io.receive();
|
|
90
|
+
if (connect.type !== "Connect") {
|
|
91
|
+
throw new Error(`Expected Connect, received ${connect.type}`);
|
|
92
|
+
}
|
|
93
|
+
const initialQuerySet = await this.io.receive();
|
|
94
|
+
if (initialQuerySet.type !== "ModifyQuerySet") {
|
|
95
|
+
throw new Error(
|
|
96
|
+
`Expected initial ModifyQuerySet, received ${initialQuerySet.type}`,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/**
|
|
102
|
+
* Receive query subscriptions until `count` new pages (Add modifications)
|
|
103
|
+
* have been requested, then answer them all in a single transition.
|
|
104
|
+
*/
|
|
105
|
+
async answerNextQueries({ count }: { count: number }): Promise<void> {
|
|
106
|
+
const adds: { queryId: number; args: JSONValue[] }[] = [];
|
|
107
|
+
while (adds.length < count) {
|
|
108
|
+
const message = await this.io.receive();
|
|
109
|
+
if (message.type !== "ModifyQuerySet") {
|
|
110
|
+
throw new Error(`Expected ModifyQuerySet, received ${message.type}`);
|
|
111
|
+
}
|
|
112
|
+
for (const modification of message.modifications) {
|
|
113
|
+
if (modification.type === "Add") {
|
|
114
|
+
adds.push({ queryId: modification.queryId, args: modification.args });
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const startVersion = {
|
|
120
|
+
querySet: this.querySetVersion,
|
|
121
|
+
identity: 0,
|
|
122
|
+
ts: Long.fromNumber(this.ts),
|
|
123
|
+
};
|
|
124
|
+
this.querySetVersion += 1;
|
|
125
|
+
this.ts += 1;
|
|
126
|
+
this.io.send({
|
|
127
|
+
type: "Transition",
|
|
128
|
+
startVersion,
|
|
129
|
+
endVersion: {
|
|
130
|
+
querySet: this.querySetVersion,
|
|
131
|
+
identity: 0,
|
|
132
|
+
ts: Long.fromNumber(this.ts),
|
|
133
|
+
},
|
|
134
|
+
modifications: adds.map((add) => ({
|
|
135
|
+
type: "QueryUpdated" as const,
|
|
136
|
+
queryId: add.queryId,
|
|
137
|
+
value: this.pageResult(
|
|
138
|
+
(add.args[0] as unknown as { paginationOpts: PaginationOptions })
|
|
139
|
+
.paginationOpts,
|
|
140
|
+
),
|
|
141
|
+
logLines: [],
|
|
142
|
+
journal: null,
|
|
143
|
+
})),
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
15
148
|
describe("BaseConvexClient paginated queries with server mocked at ws level", () => {
|
|
16
149
|
test("Subscribing and adding a page", async () => {
|
|
17
150
|
await withInMemoryWebSocket(async ({ address, receive, send }) => {
|
|
@@ -231,6 +364,81 @@ describe("BaseConvexClient paginated queries with server mocked at ws level", ()
|
|
|
231
364
|
await client.close();
|
|
232
365
|
});
|
|
233
366
|
});
|
|
367
|
+
|
|
368
|
+
test("Splitting a non-first page yields the correct concatenated pages", async () => {
|
|
369
|
+
await withInMemoryWebSocket(async ({ address, receive, send }) => {
|
|
370
|
+
const DATA = ["a", "b", "c", "d", "e", "f", "g", "h"];
|
|
371
|
+
// Recommend splitting any full 5-item page, so the oversized second page
|
|
372
|
+
// (loaded with numItems 5) splits while the 3-item first page does not.
|
|
373
|
+
const server = new FakePaginationServer({ receive, send }, DATA, {
|
|
374
|
+
splitThreshold: 5,
|
|
375
|
+
});
|
|
376
|
+
|
|
377
|
+
const q = new UpdateQueue();
|
|
378
|
+
const client = new BaseConvexClient(
|
|
379
|
+
address,
|
|
380
|
+
() => {}, // use paginated query client for all transitions
|
|
381
|
+
{
|
|
382
|
+
webSocketConstructor: nodeWebSocket,
|
|
383
|
+
unsavedChangesWarning: false,
|
|
384
|
+
},
|
|
385
|
+
);
|
|
386
|
+
|
|
387
|
+
const paginatedClient: PaginatedQueryClient = new PaginatedQueryClient(
|
|
388
|
+
client,
|
|
389
|
+
({ queries, paginatedQueries }) =>
|
|
390
|
+
q.onTransition(
|
|
391
|
+
client,
|
|
392
|
+
paginatedClient,
|
|
393
|
+
)([
|
|
394
|
+
...queries.map((t) => t.token),
|
|
395
|
+
...paginatedQueries.map((t) => t.token),
|
|
396
|
+
]),
|
|
397
|
+
);
|
|
398
|
+
|
|
399
|
+
const getResult = () =>
|
|
400
|
+
paginatedClient.localQueryResult(
|
|
401
|
+
"myQuery",
|
|
402
|
+
{ channel: "general" },
|
|
403
|
+
{ initialNumItems: 3, id: 1 },
|
|
404
|
+
);
|
|
405
|
+
|
|
406
|
+
await server.awaitConnect();
|
|
407
|
+
|
|
408
|
+
paginatedClient.subscribe(
|
|
409
|
+
"myQuery",
|
|
410
|
+
{ channel: "general" },
|
|
411
|
+
{ initialNumItems: 3, id: 1 },
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
let i = 0;
|
|
415
|
+
|
|
416
|
+
// Load the first page: DATA[0..3) = [a, b, c].
|
|
417
|
+
await server.answerNextQueries({ count: 1 });
|
|
418
|
+
await q.awaitPromiseAtIndexWithTimeout(i++);
|
|
419
|
+
expect(getResult()?.results).toEqual(["a", "b", "c"]);
|
|
420
|
+
expect(getResult()?.status).toEqual("CanLoadMore");
|
|
421
|
+
|
|
422
|
+
// Load a second page, which starts at the first page's continueCursor and
|
|
423
|
+
// comes back oversized so the server recommends a split.
|
|
424
|
+
getResult()!.loadMore(5);
|
|
425
|
+
await q.awaitPromiseAtIndexWithTimeout(i++);
|
|
426
|
+
await server.answerNextQueries({ count: 1 });
|
|
427
|
+
await q.awaitPromiseAtIndexWithTimeout(i++);
|
|
428
|
+
|
|
429
|
+
// The split subscribes two new page queries. Answer both together so the
|
|
430
|
+
// split completes in a single transition.
|
|
431
|
+
await server.answerNextQueries({ count: 2 });
|
|
432
|
+
await q.awaitPromiseAtIndexWithTimeout(i++);
|
|
433
|
+
|
|
434
|
+
// The visible pages must be the dataset exactly once, in order — no rows
|
|
435
|
+
// duplicated from re-reading the start of the dataset in a split half.
|
|
436
|
+
expect(getResult()?.results).toEqual(DATA);
|
|
437
|
+
expect(getResult()?.status).toEqual("Exhausted");
|
|
438
|
+
|
|
439
|
+
await client.close();
|
|
440
|
+
});
|
|
441
|
+
});
|
|
234
442
|
});
|
|
235
443
|
|
|
236
444
|
describe("BaseConvexClient paginated queries without connecting", () => {
|
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
serializePaginatedPathAndArgs,
|
|
18
18
|
canonicalizeUdfPath,
|
|
19
19
|
} from "./udf_path_utils.js";
|
|
20
|
-
import {
|
|
20
|
+
import { BaseConvexClientInterface, Transition } from "./client.js";
|
|
21
21
|
import {
|
|
22
22
|
PaginatedQueryResult,
|
|
23
23
|
PaginationStatus,
|
|
@@ -46,7 +46,7 @@ type LocalPaginatedQuery = {
|
|
|
46
46
|
// Map page keys to their query subscriptions
|
|
47
47
|
pageKeyToQuery: Map<
|
|
48
48
|
QueryPageKey,
|
|
49
|
-
{ queryToken: QueryToken; unsubscribe: () => void }
|
|
49
|
+
{ queryToken: QueryToken; unsubscribe: () => void; cursor: string | null }
|
|
50
50
|
>;
|
|
51
51
|
ongoingSplits: Map<QueryPageKey, [QueryPageKey, QueryPageKey]>;
|
|
52
52
|
skip: boolean;
|
|
@@ -74,6 +74,7 @@ export type ExtendedTransition = Transition & {
|
|
|
74
74
|
}>;
|
|
75
75
|
};
|
|
76
76
|
|
|
77
|
+
/** @internal */
|
|
77
78
|
export class PaginatedQueryClient {
|
|
78
79
|
private paginatedQuerySet: Map<PaginatedQueryToken, LocalPaginatedQuery> =
|
|
79
80
|
new Map();
|
|
@@ -81,7 +82,7 @@ export class PaginatedQueryClient {
|
|
|
81
82
|
private lastTransitionTs: TS;
|
|
82
83
|
|
|
83
84
|
constructor(
|
|
84
|
-
private client:
|
|
85
|
+
private client: BaseConvexClientInterface,
|
|
85
86
|
private onTransition: (transition: ExtendedTransition) => void,
|
|
86
87
|
) {
|
|
87
88
|
// Nonsense initial value to construct synthetic Transitions
|
|
@@ -387,8 +388,11 @@ export class PaginatedQueryClient {
|
|
|
387
388
|
continue; // Already splitting
|
|
388
389
|
}
|
|
389
390
|
|
|
390
|
-
const
|
|
391
|
-
|
|
391
|
+
const pageEntry = pageKeyToQuery.get(pageKey);
|
|
392
|
+
if (!pageEntry) {
|
|
393
|
+
throw new Error(`No page query for active pageKey ${pageKey}`);
|
|
394
|
+
}
|
|
395
|
+
const pageResult = getResult(pageEntry.queryToken);
|
|
392
396
|
if (!pageResult) {
|
|
393
397
|
continue;
|
|
394
398
|
}
|
|
@@ -406,6 +410,7 @@ export class PaginatedQueryClient {
|
|
|
406
410
|
this.splitPaginatedQueryPage(
|
|
407
411
|
paginatedQuery,
|
|
408
412
|
pageKey,
|
|
413
|
+
pageEntry.cursor,
|
|
409
414
|
result.splitCursor!, // we just checked
|
|
410
415
|
result.continueCursor,
|
|
411
416
|
);
|
|
@@ -417,31 +422,38 @@ export class PaginatedQueryClient {
|
|
|
417
422
|
private splitPaginatedQueryPage(
|
|
418
423
|
paginatedQuery: LocalPaginatedQuery,
|
|
419
424
|
pageKey: QueryPageKey,
|
|
425
|
+
// Where the page being split started.
|
|
426
|
+
startCursor: string | null,
|
|
427
|
+
// The split position - will be end of the first split page and the start
|
|
428
|
+
// of the second.
|
|
420
429
|
splitCursor: string,
|
|
430
|
+
// Where the page being split ended.
|
|
421
431
|
continueCursor: string | null,
|
|
422
432
|
): void {
|
|
423
433
|
const splitKey1 = paginatedQuery.nextPageKey++;
|
|
424
434
|
const splitKey2 = paginatedQuery.nextPageKey++;
|
|
425
435
|
|
|
426
436
|
const paginationOpts: Value = {
|
|
427
|
-
cursor: continueCursor,
|
|
428
437
|
numItems: paginatedQuery.options.initialNumItems,
|
|
429
438
|
id: paginatedQuery.id,
|
|
430
439
|
};
|
|
431
440
|
|
|
432
|
-
// First split page: same cursor as original,
|
|
441
|
+
// First split page: same cursor as the original page, ending at splitCursor
|
|
433
442
|
const firstSubscription = this.client.subscribe(
|
|
434
443
|
paginatedQuery.canonicalizedUdfPath,
|
|
435
444
|
{
|
|
436
445
|
...paginatedQuery.args,
|
|
437
446
|
paginationOpts: {
|
|
438
447
|
...paginationOpts,
|
|
439
|
-
cursor:
|
|
448
|
+
cursor: startCursor,
|
|
440
449
|
endCursor: splitCursor,
|
|
441
450
|
},
|
|
442
451
|
},
|
|
443
452
|
);
|
|
444
|
-
paginatedQuery.pageKeyToQuery.set(splitKey1,
|
|
453
|
+
paginatedQuery.pageKeyToQuery.set(splitKey1, {
|
|
454
|
+
...firstSubscription,
|
|
455
|
+
cursor: startCursor,
|
|
456
|
+
});
|
|
445
457
|
|
|
446
458
|
// Second split page: cursor starts at splitCursor, endCursor is the original continueCursor
|
|
447
459
|
const secondSubscription = this.client.subscribe(
|
|
@@ -455,7 +467,10 @@ export class PaginatedQueryClient {
|
|
|
455
467
|
},
|
|
456
468
|
},
|
|
457
469
|
);
|
|
458
|
-
paginatedQuery.pageKeyToQuery.set(splitKey2,
|
|
470
|
+
paginatedQuery.pageKeyToQuery.set(splitKey2, {
|
|
471
|
+
...secondSubscription,
|
|
472
|
+
cursor: splitCursor,
|
|
473
|
+
});
|
|
459
474
|
|
|
460
475
|
paginatedQuery.ongoingSplits.set(pageKey, [splitKey1, splitKey2]);
|
|
461
476
|
}
|
|
@@ -488,7 +503,10 @@ export class PaginatedQueryClient {
|
|
|
488
503
|
);
|
|
489
504
|
|
|
490
505
|
paginatedQuery.pageKeys.push(pageKey);
|
|
491
|
-
paginatedQuery.pageKeyToQuery.set(pageKey,
|
|
506
|
+
paginatedQuery.pageKeyToQuery.set(pageKey, {
|
|
507
|
+
...subscription,
|
|
508
|
+
cursor: continueCursor,
|
|
509
|
+
});
|
|
492
510
|
return subscription;
|
|
493
511
|
}
|
|
494
512
|
|
|
@@ -9,7 +9,12 @@ import {
|
|
|
9
9
|
} from "../lib/components/definition/directoryStructure.js";
|
|
10
10
|
import { StartPushResponse } from "../lib/deployApi/startPush.js";
|
|
11
11
|
import { importPath, moduleIdentifier } from "./api.js";
|
|
12
|
-
import {
|
|
12
|
+
import {
|
|
13
|
+
apiComment,
|
|
14
|
+
compareModulePaths,
|
|
15
|
+
compareStrings,
|
|
16
|
+
header,
|
|
17
|
+
} from "./common.js";
|
|
13
18
|
import {
|
|
14
19
|
ComponentExports,
|
|
15
20
|
EvaluatedComponentDefinition,
|
|
@@ -346,7 +351,7 @@ async function* codegenDynamicApiObjects(
|
|
|
346
351
|
const absModulePaths = await entryPoints(ctx, componentDirectory.path);
|
|
347
352
|
const modulePaths = absModulePaths
|
|
348
353
|
.map((p) => path.relative(componentDirectory.path, p))
|
|
349
|
-
.sort();
|
|
354
|
+
.sort(compareModulePaths);
|
|
350
355
|
for (const modulePath of modulePaths) {
|
|
351
356
|
const ident = moduleIdentifier(modulePath);
|
|
352
357
|
const path = importPath(modulePath);
|
|
@@ -382,7 +387,7 @@ async function* codegenDynamicApiObjectsTS(
|
|
|
382
387
|
const absModulePaths = await entryPoints(ctx, componentDirectory.path);
|
|
383
388
|
const modulePaths = absModulePaths
|
|
384
389
|
.map((p) => path.relative(componentDirectory.path, p))
|
|
385
|
-
.sort();
|
|
390
|
+
.sort(compareModulePaths);
|
|
386
391
|
for (const modulePath of modulePaths) {
|
|
387
392
|
const ident = moduleIdentifier(modulePath);
|
|
388
393
|
const path = importPath(modulePath);
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { describe, test, expect } from "vitest";
|
|
2
|
+
import { validatorToType } from "./validator_helpers.js";
|
|
3
|
+
|
|
4
|
+
describe("validatorToType", () => {
|
|
5
|
+
test("commitTs matches Infer<v.commitTs()>, valid in any generated file", () => {
|
|
6
|
+
// Writes go through `db.vars.commitTs` (a `CommitTsPlaceholder`), so a
|
|
7
|
+
// bigint-only type would reject the intended insert/patch value.
|
|
8
|
+
expect(validatorToType({ type: "commitTs" }, false)).toEqual(
|
|
9
|
+
'bigint | import("convex/values").CommitTsPlaceholder',
|
|
10
|
+
);
|
|
11
|
+
});
|
|
12
|
+
|
|
13
|
+
test("commitTs composes into container types", () => {
|
|
14
|
+
expect(
|
|
15
|
+
validatorToType(
|
|
16
|
+
{
|
|
17
|
+
type: "object",
|
|
18
|
+
value: {
|
|
19
|
+
commitTs: { fieldType: { type: "commitTs" }, optional: false },
|
|
20
|
+
},
|
|
21
|
+
},
|
|
22
|
+
false,
|
|
23
|
+
),
|
|
24
|
+
).toEqual(
|
|
25
|
+
'{ commitTs: bigint | import("convex/values").CommitTsPlaceholder }',
|
|
26
|
+
);
|
|
27
|
+
expect(
|
|
28
|
+
validatorToType({ type: "array", value: { type: "commitTs" } }, false),
|
|
29
|
+
).toEqual('Array<bigint | import("convex/values").CommitTsPlaceholder>');
|
|
30
|
+
});
|
|
31
|
+
});
|
|
@@ -21,6 +21,12 @@ export function validatorToType(
|
|
|
21
21
|
return "number";
|
|
22
22
|
} else if (validator.type === "bigint") {
|
|
23
23
|
return "bigint";
|
|
24
|
+
} else if (validator.type === "commitTs") {
|
|
25
|
+
// Match `Infer<v.commitTs()>`: the field holds a bigint once committed,
|
|
26
|
+
// but writes go through `db.vars.commitTs` (a `CommitTsPlaceholder`) and
|
|
27
|
+
// same-mutation read-backs yield the placeholder. The inline import keeps
|
|
28
|
+
// this valid in every generated file regardless of its header imports.
|
|
29
|
+
return 'bigint | import("convex/values").CommitTsPlaceholder';
|
|
24
30
|
} else if (validator.type === "boolean") {
|
|
25
31
|
return "boolean";
|
|
26
32
|
} else if (validator.type === "string") {
|
package/src/cli/deployment.ts
CHANGED
|
@@ -2,10 +2,13 @@ import { Command } from "@commander-js/extra-typings";
|
|
|
2
2
|
import { deploymentSelect } from "./deploymentSelect.js";
|
|
3
3
|
import { deploymentCreate } from "./deploymentCreate.js";
|
|
4
4
|
import { deploymentToken } from "./deploymentToken.js";
|
|
5
|
+
import { usage, usageLimits } from "./usageLimits.js";
|
|
5
6
|
|
|
6
7
|
export const deployment = new Command("deployment")
|
|
7
8
|
.summary("Manage deployments")
|
|
8
9
|
.description("Manage deployments in your project.")
|
|
9
10
|
.addCommand(deploymentSelect)
|
|
10
11
|
.addCommand(deploymentCreate)
|
|
11
|
-
.addCommand(deploymentToken)
|
|
12
|
+
.addCommand(deploymentToken)
|
|
13
|
+
.addCommand(usage)
|
|
14
|
+
.addCommand(usageLimits);
|
|
@@ -9,7 +9,7 @@ import {
|
|
|
9
9
|
selectRegion,
|
|
10
10
|
logNoDefaultRegionMessage,
|
|
11
11
|
} from "./lib/utils/utils.js";
|
|
12
|
-
import {
|
|
12
|
+
import { ProjectResponse } from "@convex-dev/platform/managementApi";
|
|
13
13
|
import {
|
|
14
14
|
DeploymentSelection,
|
|
15
15
|
getDeploymentSelection,
|
|
@@ -190,7 +190,7 @@ const fakeProject = {
|
|
|
190
190
|
createTime: 0,
|
|
191
191
|
name: "My Project",
|
|
192
192
|
teamSlug: "my-team",
|
|
193
|
-
} satisfies
|
|
193
|
+
} satisfies ProjectResponse;
|
|
194
194
|
|
|
195
195
|
const createdDeployment = {
|
|
196
196
|
kind: "cloud" as const,
|
|
@@ -20,7 +20,7 @@ import {
|
|
|
20
20
|
typedBigBrainClient,
|
|
21
21
|
typedPlatformClient,
|
|
22
22
|
} from "./lib/utils/utils.js";
|
|
23
|
-
import {
|
|
23
|
+
import { ProjectResponse } from "@convex-dev/platform/managementApi";
|
|
24
24
|
import { getTeamAndProjectFromPreviewAdminKey } from "./lib/deployment.js";
|
|
25
25
|
import { saveSelectedDeployment } from "./deploymentSelect.js";
|
|
26
26
|
import { promptOptions, promptString } from "./lib/utils/prompts.js";
|
|
@@ -710,7 +710,7 @@ function parseLocalCreateTarget(
|
|
|
710
710
|
async function resolveProject(
|
|
711
711
|
ctx: Context,
|
|
712
712
|
deploymentSelection: DeploymentSelection,
|
|
713
|
-
): Promise<
|
|
713
|
+
): Promise<ProjectResponse> {
|
|
714
714
|
switch (deploymentSelection.kind) {
|
|
715
715
|
case "existingDeployment": {
|
|
716
716
|
const { deploymentFields } = deploymentSelection.deploymentToActOn;
|