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
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/server/cron.ts"],
|
|
4
|
-
"sourcesContent": ["import { getFunctionName, OptionalRestArgs } from \"../server/api.js\";\nimport { parseArgs } from \"../common/index.js\";\nimport { convexToJson, JSONValue, Value } from \"../values/index.js\";\nimport { SchedulableFunctionReference } from \"./scheduler.js\";\n\ntype CronSchedule = {\n type: \"cron\";\n cron: string;\n};\n/** @public */\nexport type IntervalSchedule =\n | { type: \"interval\"; seconds: number }\n | { type: \"interval\"; minutes: number }\n | { type: \"interval\"; hours: number };\n/** @public */\nexport type HourlySchedule = {\n type: \"hourly\";\n minuteUTC: number;\n};\n/** @public */\nexport type DailySchedule = {\n type: \"daily\";\n hourUTC: number;\n minuteUTC: number;\n};\nconst DAYS_OF_WEEK = [\n \"sunday\",\n \"monday\",\n \"tuesday\",\n \"wednesday\",\n \"thursday\",\n \"friday\",\n \"saturday\",\n] as const;\ntype DayOfWeek = (typeof DAYS_OF_WEEK)[number];\n/** @public */\nexport type WeeklySchedule = {\n type: \"weekly\";\n dayOfWeek: DayOfWeek;\n hourUTC: number;\n minuteUTC: number;\n};\n/** @public */\nexport type MonthlySchedule = {\n type: \"monthly\";\n day: number;\n hourUTC: number;\n minuteUTC: number;\n};\n\n// Duplicating types so docstrings are visible in signatures:\n// `Expand<Omit<MonthlySchedule, \"type\">>` doesn't preserve docstrings.\n// When we get to TypeScript 4.9, `satisfies` would go nicely here.\n\n/** @public */\nexport type Interval =\n | {\n /**\n * Run a job every `seconds` seconds, beginning\n * when the job is first deployed to Convex.\n */\n seconds: number;\n minutes?: undefined;\n hours?: undefined;\n }\n | {\n /**\n * Run a job every `minutes` minutes, beginning\n * when the job is first deployed to Convex.\n */\n minutes: number;\n seconds?: undefined;\n hours?: undefined;\n }\n | {\n /**\n * Run a job every `hours` hours, beginning when\n * when the job is first deployed to Convex.\n */\n hours: number;\n seconds?: undefined;\n minutes?: undefined;\n };\n\n/** @public */\nexport type Hourly = {\n /**\n * Minutes past the hour, 0-59.\n */\n minuteUTC: number;\n};\n\n/** @public */\nexport type Daily = {\n /**\n * 0-23, hour of day. Remember, this is UTC.\n */\n hourUTC: number;\n /**\n * 0-59, minute of hour. Remember, this is UTC.\n */\n minuteUTC: number;\n};\n\n/** @public */\nexport type Monthly = {\n /**\n * 1-31, day of month. Days greater that 28 will not run every month.\n */\n day: number;\n /**\n * 0-23, hour of day. Remember to convert from your own time zone to UTC.\n */\n hourUTC: number;\n /**\n * 0-59, minute of hour. Remember to convert from your own time zone to UTC.\n */\n minuteUTC: number;\n};\n/** @public */\nexport type Weekly = {\n /**\n * \"monday\", \"tuesday\", etc.\n */\n dayOfWeek: DayOfWeek;\n /**\n * 0-23, hour of day. Remember to convert from your own time zone to UTC.\n */\n hourUTC: number;\n /**\n * 0-59, minute of hour. Remember to convert from your own time zone to UTC.\n */\n minuteUTC: number;\n};\n\n/** @public */\nexport type Schedule =\n | CronSchedule\n | IntervalSchedule\n | HourlySchedule\n | DailySchedule\n | WeeklySchedule\n | MonthlySchedule;\n\n/**\n * A schedule to run a Convex mutation or action on.\n * You can schedule Convex functions to run regularly with\n * {@link interval} and exporting it.\n *\n * @public\n **/\nexport interface CronJob {\n name: string;\n args: JSONValue;\n schedule: Schedule;\n}\n\n/**\n * Create a CronJobs object to schedule recurring tasks.\n *\n * ```js\n * // convex/crons.js\n * import { cronJobs } from 'convex/server';\n * import { api } from \"./_generated/api\";\n *\n * const crons = cronJobs();\n * crons.weekly(\n * \"weekly re-engagement email\",\n * {\n * hourUTC: 17, // (9:30am Pacific/10:30am Daylight Savings Pacific)\n * minuteUTC: 30,\n * },\n * api.emails.send\n * )\n * export default crons;\n * ```\n *\n * @public\n */\nexport const cronJobs = () => new Crons();\n\n/**\n * @public\n *\n * This is a cron string. They're complicated!\n */\ntype CronString = string;\n\nfunction validateIntervalNumber(n: number) {\n if (!Number.isInteger(n) || n <= 0) {\n throw new Error(\"Interval must be an integer greater than 0\");\n }\n}\n\nfunction validatedDayOfMonth(n: number) {\n if (!Number.isInteger(n) || n < 1 || n > 31) {\n throw new Error(\"Day of month must be an integer from 1 to 31\");\n }\n return n;\n}\n\nfunction validatedDayOfWeek(s: string) {\n if (!DAYS_OF_WEEK.includes(s as DayOfWeek)) {\n throw new Error('Day of week must be a string like \"monday\".');\n }\n return s as DayOfWeek;\n}\n\nfunction validatedHourOfDay(n: number) {\n if (!Number.isInteger(n) || n < 0 || n > 23) {\n throw new Error(\"Hour of day must be an integer from 0 to 23\");\n }\n return n;\n}\n\nfunction validatedMinuteOfHour(n: number) {\n if (!Number.isInteger(n) || n < 0 || n > 59) {\n throw new Error(\"Minute of hour must be an integer from 0 to 59\");\n }\n return n;\n}\n\nfunction validatedCronString(s: string) {\n return s;\n}\n\nfunction validatedCronIdentifier(s: string) {\n if (!s.match(/^[ -~]*$/)) {\n throw new Error(\n `Invalid cron identifier ${s}: use ASCII letters that are not control characters`,\n );\n }\n return s;\n}\n\n/**\n * A class for scheduling cron jobs.\n *\n * To learn more see the documentation at https://docs.convex.dev/scheduling/cron-jobs\n *\n * @public\n */\nexport class Crons {\n crons: Record<string, CronJob>;\n isCrons: true;\n constructor() {\n this.isCrons = true;\n this.crons = {};\n }\n\n /** @internal */\n schedule(\n cronIdentifier: string,\n schedule: Schedule,\n functionReference: SchedulableFunctionReference,\n args?: Record<string, Value>,\n ) {\n const cronArgs = parseArgs(args);\n validatedCronIdentifier(cronIdentifier);\n if (cronIdentifier in this.crons) {\n throw new Error(`Cron identifier registered twice: ${cronIdentifier}`);\n }\n this.crons[cronIdentifier] = {\n name: getFunctionName(functionReference),\n args: [convexToJson(cronArgs)],\n schedule: schedule,\n };\n }\n\n /**\n * Schedule a mutation or action to run at some interval.\n *\n * ```js\n * crons.interval(\"Clear presence data\", {seconds: 30}, api.presence.clear);\n * ```\n *\n * @param identifier - A unique name for this scheduled job.\n * @param schedule - The time between runs for this scheduled job.\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n * @param args - The arguments to the function.\n */\n interval<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n schedule: Interval,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const s = schedule;\n const hasSeconds = +(\"seconds\" in s && s.seconds !== undefined);\n const hasMinutes = +(\"minutes\" in s && s.minutes !== undefined);\n const hasHours = +(\"hours\" in s && s.hours !== undefined);\n const total = hasSeconds + hasMinutes + hasHours;\n if (total !== 1) {\n throw new Error(\"Must specify one of seconds, minutes, or hours\");\n }\n if (hasSeconds) {\n validateIntervalNumber(schedule.seconds!);\n } else if (hasMinutes) {\n validateIntervalNumber(schedule.minutes!);\n } else if (hasHours) {\n validateIntervalNumber(schedule.hours!);\n }\n this.schedule(\n cronIdentifier,\n { ...schedule, type: \"interval\" },\n functionReference,\n ...args,\n );\n }\n\n /**\n * Schedule a mutation or action to run on an hourly basis.\n *\n * ```js\n * crons.hourly(\n * \"Reset high scores\",\n * {\n * minuteUTC: 30,\n * },\n * api.scores.reset\n * )\n * ```\n *\n * @param cronIdentifier - A unique name for this scheduled job.\n * @param schedule - What time (UTC) each day to run this function.\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n * @param args - The arguments to the function.\n */\n hourly<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n schedule: Hourly,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const minuteUTC = validatedMinuteOfHour(schedule.minuteUTC);\n this.schedule(\n cronIdentifier,\n { minuteUTC, type: \"hourly\" },\n functionReference,\n ...args,\n );\n }\n\n /**\n * Schedule a mutation or action to run on a daily basis.\n *\n * ```js\n * crons.daily(\n * \"Reset high scores\",\n * {\n * hourUTC: 17, // (9:30am Pacific/10:30am Daylight Savings Pacific)\n * minuteUTC: 30,\n * },\n * api.scores.reset\n * )\n * ```\n *\n * @param cronIdentifier - A unique name for this scheduled job.\n * @param schedule - What time (UTC) each day to run this function.\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n * @param args - The arguments to the function.\n */\n daily<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n schedule: Daily,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const hourUTC = validatedHourOfDay(schedule.hourUTC);\n const minuteUTC = validatedMinuteOfHour(schedule.minuteUTC);\n this.schedule(\n cronIdentifier,\n { hourUTC, minuteUTC, type: \"daily\" },\n functionReference,\n ...args,\n );\n }\n\n /**\n * Schedule a mutation or action to run on a weekly basis.\n *\n * ```js\n * crons.weekly(\n * \"Weekly re-engagement email\",\n * {\n * dayOfWeek: \"Tuesday\",\n * hourUTC: 17, // (9:30am Pacific/10:30am Daylight Savings Pacific)\n * minuteUTC: 30,\n * },\n * api.emails.send\n * )\n * ```\n *\n * @param cronIdentifier - A unique name for this scheduled job.\n * @param schedule - What day and time (UTC) each week to run this function.\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n */\n weekly<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n schedule: Weekly,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const dayOfWeek = validatedDayOfWeek(schedule.dayOfWeek);\n const hourUTC = validatedHourOfDay(schedule.hourUTC);\n const minuteUTC = validatedMinuteOfHour(schedule.minuteUTC);\n this.schedule(\n cronIdentifier,\n { dayOfWeek, hourUTC, minuteUTC, type: \"weekly\" },\n functionReference,\n ...args,\n );\n }\n\n /**\n * Schedule a mutation or action to run on a monthly basis.\n *\n * Note that some months have fewer days than others, so e.g. a function\n * scheduled to run on the 30th will not run in February.\n *\n * ```js\n * crons.monthly(\n * \"Bill customers at \",\n * {\n * hourUTC: 17, // (9:30am Pacific/10:30am Daylight Savings Pacific)\n * minuteUTC: 30,\n * day: 1,\n * },\n * api.billing.billCustomers\n * )\n * ```\n *\n * @param cronIdentifier - A unique name for this scheduled job.\n * @param schedule - What day and time (UTC) each month to run this function.\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n * @param args - The arguments to the function.\n */\n monthly<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n schedule: Monthly,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const day = validatedDayOfMonth(schedule.day);\n const hourUTC = validatedHourOfDay(schedule.hourUTC);\n const minuteUTC = validatedMinuteOfHour(schedule.minuteUTC);\n this.schedule(\n cronIdentifier,\n { day, hourUTC, minuteUTC, type: \"monthly\" },\n functionReference,\n ...args,\n );\n }\n\n /**\n * Schedule a mutation or action to run on a recurring basis.\n *\n * Like the unix command `cron`, Sunday is 0, Monday is 1, etc.\n *\n * ```\n * \u250C\u2500 minute (0 - 59)\n * \u2502 \u250C\u2500 hour (0 - 23)\n * \u2502 \u2502 \u250C\u2500 day of the month (1 - 31)\n * \u2502 \u2502 \u2502 \u250C\u2500 month (1 - 12)\n * \u2502 \u2502 \u2502 \u2502 \u250C\u2500 day of the week (0 - 6) (Sunday to Saturday)\n * \"* * * * *\"\n * ```\n *\n * @param cronIdentifier - A unique name for this scheduled job.\n * @param cron - Cron string like `\"15 7 * * *\"` (Every day at 7:15 UTC)\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n * @param args - The arguments to the function.\n */\n cron<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n cron: CronString,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const c = validatedCronString(cron);\n this.schedule(\n cronIdentifier,\n { cron: c, type: \"cron\" },\n functionReference,\n ...args,\n );\n }\n\n /** @internal */\n export() {\n return JSON.stringify(this.crons);\n }\n}\n"],
|
|
5
|
-
"mappings": ";;;;AAAA,SAAS,uBAAyC;AAClD,SAAS,iBAAiB;AAC1B,SAAS,oBAAsC;
|
|
4
|
+
"sourcesContent": ["import { getFunctionName, OptionalRestArgs } from \"../server/api.js\";\nimport { parseArgs } from \"../common/index.js\";\nimport { convexToJson, JSONValue, Value } from \"../values/index.js\";\nimport { getFunctionAddress } from \"./components/paths.js\";\nimport { SchedulableFunctionReference } from \"./scheduler.js\";\n\ntype CronSchedule = {\n type: \"cron\";\n cron: string;\n};\n/** @public */\nexport type IntervalSchedule =\n | { type: \"interval\"; seconds: number }\n | { type: \"interval\"; minutes: number }\n | { type: \"interval\"; hours: number };\n/** @public */\nexport type HourlySchedule = {\n type: \"hourly\";\n minuteUTC?: number;\n};\n/** @public */\nexport type DailySchedule = {\n type: \"daily\";\n hourUTC: number;\n minuteUTC?: number;\n};\nconst DAYS_OF_WEEK = [\n \"sunday\",\n \"monday\",\n \"tuesday\",\n \"wednesday\",\n \"thursday\",\n \"friday\",\n \"saturday\",\n] as const;\ntype DayOfWeek = (typeof DAYS_OF_WEEK)[number];\n/** @public */\nexport type WeeklySchedule = {\n type: \"weekly\";\n dayOfWeek: DayOfWeek;\n hourUTC: number;\n minuteUTC?: number;\n};\n/** @public */\nexport type MonthlySchedule = {\n type: \"monthly\";\n day: number;\n hourUTC: number;\n minuteUTC?: number;\n};\n\n// Duplicating types so docstrings are visible in signatures:\n// `Expand<Omit<MonthlySchedule, \"type\">>` doesn't preserve docstrings.\n// When we get to TypeScript 4.9, `satisfies` would go nicely here.\n\n/** @public */\nexport type Interval =\n | {\n /**\n * Run a job every `seconds` seconds, beginning\n * when the job is first deployed to Convex.\n */\n seconds: number;\n minutes?: undefined;\n hours?: undefined;\n }\n | {\n /**\n * Run a job every `minutes` minutes, beginning\n * when the job is first deployed to Convex.\n */\n minutes: number;\n seconds?: undefined;\n hours?: undefined;\n }\n | {\n /**\n * Run a job every `hours` hours, beginning when\n * when the job is first deployed to Convex.\n */\n hours: number;\n seconds?: undefined;\n minutes?: undefined;\n };\n\n/** @public */\nexport type Hourly = {\n /**\n * Minutes past the hour, 0-59. If omitted, Convex picks a minute for you\n * and spreads runs across the hour so your job isn't tied to the busy top\n * of the hour.\n */\n minuteUTC?: number;\n};\n\n/** @public */\nexport type Daily = {\n /**\n * 0-23, hour of day. Remember, this is UTC.\n */\n hourUTC: number;\n /**\n * 0-59, minute of hour. Remember, this is UTC. If omitted, Convex picks a\n * minute for you and spreads runs across the hour.\n */\n minuteUTC?: number;\n};\n\n/** @public */\nexport type Monthly = {\n /**\n * 1-31, day of month. Days greater that 28 will not run every month.\n */\n day: number;\n /**\n * 0-23, hour of day. Remember to convert from your own time zone to UTC.\n */\n hourUTC: number;\n /**\n * 0-59, minute of hour. Remember to convert from your own time zone to UTC.\n * If omitted, Convex picks a minute for you and spreads runs across the\n * hour.\n */\n minuteUTC?: number;\n};\n/** @public */\nexport type Weekly = {\n /**\n * \"monday\", \"tuesday\", etc.\n */\n dayOfWeek: DayOfWeek;\n /**\n * 0-23, hour of day. Remember to convert from your own time zone to UTC.\n */\n hourUTC: number;\n /**\n * 0-59, minute of hour. Remember to convert from your own time zone to UTC.\n * If omitted, Convex picks a minute for you and spreads runs across the\n * hour.\n */\n minuteUTC?: number;\n};\n\n/** @public */\nexport type Schedule =\n | CronSchedule\n | IntervalSchedule\n | HourlySchedule\n | DailySchedule\n | WeeklySchedule\n | MonthlySchedule;\n\n/**\n * A schedule to run a Convex mutation or action on.\n * You can schedule Convex functions to run regularly with\n * {@link interval} and exporting it.\n *\n * @public\n **/\nexport interface CronJob {\n name: string;\n args: JSONValue;\n schedule: Schedule;\n}\n\n/**\n * Create a CronJobs object to schedule recurring tasks.\n *\n * ```js\n * // convex/crons.js\n * import { cronJobs } from 'convex/server';\n * import { api } from \"./_generated/api\";\n *\n * const crons = cronJobs();\n * crons.weekly(\n * \"weekly re-engagement email\",\n * {\n * hourUTC: 17, // (9:30am Pacific/10:30am Daylight Savings Pacific)\n * minuteUTC: 30,\n * },\n * api.emails.send\n * )\n * export default crons;\n * ```\n *\n * @public\n */\nexport const cronJobs = () => new Crons();\n\n/**\n * @public\n *\n * This is a cron string. They're complicated!\n */\ntype CronString = string;\n\nfunction validateIntervalNumber(n: number) {\n if (!Number.isInteger(n) || n <= 0) {\n throw new Error(\"Interval must be an integer greater than 0\");\n }\n}\n\nfunction validatedDayOfMonth(n: number) {\n if (!Number.isInteger(n) || n < 1 || n > 31) {\n throw new Error(\"Day of month must be an integer from 1 to 31\");\n }\n return n;\n}\n\nfunction validatedDayOfWeek(s: string) {\n if (!DAYS_OF_WEEK.includes(s as DayOfWeek)) {\n throw new Error('Day of week must be a string like \"monday\".');\n }\n return s as DayOfWeek;\n}\n\nfunction validatedHourOfDay(n: number) {\n if (!Number.isInteger(n) || n < 0 || n > 23) {\n throw new Error(\"Hour of day must be an integer from 0 to 23\");\n }\n return n;\n}\n\nfunction validatedMinuteOfHour(n: number) {\n if (!Number.isInteger(n) || n < 0 || n > 59) {\n throw new Error(\"Minute of hour must be an integer from 0 to 59\");\n }\n return n;\n}\n\n// `minuteUTC` is optional: when omitted the backend picks a minute per job and\n// spreads runs across the hour. Only validate when a minute was provided.\nfunction validatedOptionalMinuteOfHour(n: number | undefined) {\n return n === undefined ? undefined : validatedMinuteOfHour(n);\n}\n\n// `crons.hourly()` lets the schedule object be omitted entirely. Tell the two\n// call shapes apart by whether the second argument resolves to a function\n// reference (the way the scheduler syscalls do) rather than a schedule object.\nfunction isSchedulableFunctionReference(\n arg: Hourly | SchedulableFunctionReference,\n): arg is SchedulableFunctionReference {\n try {\n getFunctionAddress(arg);\n return true;\n } catch {\n return false;\n }\n}\n\nfunction validatedCronString(s: string) {\n return s;\n}\n\nfunction validatedCronIdentifier(s: string) {\n if (!s.match(/^[ -~]*$/)) {\n throw new Error(\n `Invalid cron identifier ${s}: use ASCII letters that are not control characters`,\n );\n }\n return s;\n}\n\n/**\n * A class for scheduling cron jobs.\n *\n * To learn more see the documentation at https://docs.convex.dev/scheduling/cron-jobs\n *\n * @public\n */\nexport class Crons {\n crons: Record<string, CronJob>;\n isCrons: true;\n constructor() {\n this.isCrons = true;\n this.crons = {};\n }\n\n /** @internal */\n schedule(\n cronIdentifier: string,\n schedule: Schedule,\n functionReference: SchedulableFunctionReference,\n args?: Record<string, Value>,\n ) {\n const cronArgs = parseArgs(args);\n validatedCronIdentifier(cronIdentifier);\n if (cronIdentifier in this.crons) {\n throw new Error(`Cron identifier registered twice: ${cronIdentifier}`);\n }\n this.crons[cronIdentifier] = {\n name: getFunctionName(functionReference),\n args: [convexToJson(cronArgs)],\n schedule: schedule,\n };\n }\n\n /**\n * Schedule a mutation or action to run at some interval.\n *\n * ```js\n * crons.interval(\"Clear presence data\", {seconds: 30}, api.presence.clear);\n * ```\n *\n * @param identifier - A unique name for this scheduled job.\n * @param schedule - The time between runs for this scheduled job.\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n * @param args - The arguments to the function.\n */\n interval<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n schedule: Interval,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const s = schedule;\n const hasSeconds = +(\"seconds\" in s && s.seconds !== undefined);\n const hasMinutes = +(\"minutes\" in s && s.minutes !== undefined);\n const hasHours = +(\"hours\" in s && s.hours !== undefined);\n const total = hasSeconds + hasMinutes + hasHours;\n if (total !== 1) {\n throw new Error(\"Must specify one of seconds, minutes, or hours\");\n }\n if (hasSeconds) {\n validateIntervalNumber(schedule.seconds!);\n } else if (hasMinutes) {\n validateIntervalNumber(schedule.minutes!);\n } else if (hasHours) {\n validateIntervalNumber(schedule.hours!);\n }\n this.schedule(\n cronIdentifier,\n { ...schedule, type: \"interval\" },\n functionReference,\n ...args,\n );\n }\n\n /**\n * Schedule a mutation or action to run on an hourly basis.\n *\n * ```js\n * crons.hourly(\n * \"Reset high scores\",\n * {\n * minuteUTC: 30,\n * },\n * api.scores.reset\n * )\n * ```\n *\n * @param cronIdentifier - A unique name for this scheduled job.\n * @param schedule - What minute (UTC) of each hour to run this function. May\n * be omitted to let Convex pick a minute and spread runs across the hour.\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n * @param args - The arguments to the function.\n */\n hourly<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ): void;\n hourly<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n schedule: Hourly,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ): void;\n hourly<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n scheduleOrFunctionReference: Hourly | FuncRef,\n functionReferenceOrArg?: FuncRef | Record<string, Value>,\n ...args: any[]\n ): void {\n // The schedule object may be omitted, so the second argument is either the\n // function reference (no schedule) or the schedule.\n if (isSchedulableFunctionReference(scheduleOrFunctionReference)) {\n this.schedule(\n cronIdentifier,\n { type: \"hourly\" },\n scheduleOrFunctionReference,\n functionReferenceOrArg as Record<string, Value> | undefined,\n );\n return;\n }\n const minuteUTC = validatedOptionalMinuteOfHour(\n scheduleOrFunctionReference.minuteUTC,\n );\n this.schedule(\n cronIdentifier,\n minuteUTC === undefined\n ? { type: \"hourly\" }\n : { minuteUTC, type: \"hourly\" },\n functionReferenceOrArg as FuncRef,\n ...args,\n );\n }\n\n /**\n * Schedule a mutation or action to run on a daily basis.\n *\n * ```js\n * crons.daily(\n * \"Reset high scores\",\n * {\n * hourUTC: 17, // (9:30am Pacific/10:30am Daylight Savings Pacific)\n * minuteUTC: 30,\n * },\n * api.scores.reset\n * )\n * ```\n *\n * @param cronIdentifier - A unique name for this scheduled job.\n * @param schedule - What time (UTC) each day to run this function.\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n * @param args - The arguments to the function.\n */\n daily<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n schedule: Daily,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const hourUTC = validatedHourOfDay(schedule.hourUTC);\n const minuteUTC = validatedOptionalMinuteOfHour(schedule.minuteUTC);\n this.schedule(\n cronIdentifier,\n minuteUTC === undefined\n ? { hourUTC, type: \"daily\" }\n : { hourUTC, minuteUTC, type: \"daily\" },\n functionReference,\n ...args,\n );\n }\n\n /**\n * Schedule a mutation or action to run on a weekly basis.\n *\n * ```js\n * crons.weekly(\n * \"Weekly re-engagement email\",\n * {\n * dayOfWeek: \"Tuesday\",\n * hourUTC: 17, // (9:30am Pacific/10:30am Daylight Savings Pacific)\n * minuteUTC: 30,\n * },\n * api.emails.send\n * )\n * ```\n *\n * @param cronIdentifier - A unique name for this scheduled job.\n * @param schedule - What day and time (UTC) each week to run this function.\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n */\n weekly<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n schedule: Weekly,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const dayOfWeek = validatedDayOfWeek(schedule.dayOfWeek);\n const hourUTC = validatedHourOfDay(schedule.hourUTC);\n const minuteUTC = validatedOptionalMinuteOfHour(schedule.minuteUTC);\n this.schedule(\n cronIdentifier,\n minuteUTC === undefined\n ? { dayOfWeek, hourUTC, type: \"weekly\" }\n : { dayOfWeek, hourUTC, minuteUTC, type: \"weekly\" },\n functionReference,\n ...args,\n );\n }\n\n /**\n * Schedule a mutation or action to run on a monthly basis.\n *\n * Note that some months have fewer days than others, so e.g. a function\n * scheduled to run on the 30th will not run in February.\n *\n * ```js\n * crons.monthly(\n * \"Bill customers at \",\n * {\n * hourUTC: 17, // (9:30am Pacific/10:30am Daylight Savings Pacific)\n * minuteUTC: 30,\n * day: 1,\n * },\n * api.billing.billCustomers\n * )\n * ```\n *\n * @param cronIdentifier - A unique name for this scheduled job.\n * @param schedule - What day and time (UTC) each month to run this function.\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n * @param args - The arguments to the function.\n */\n monthly<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n schedule: Monthly,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const day = validatedDayOfMonth(schedule.day);\n const hourUTC = validatedHourOfDay(schedule.hourUTC);\n const minuteUTC = validatedOptionalMinuteOfHour(schedule.minuteUTC);\n this.schedule(\n cronIdentifier,\n minuteUTC === undefined\n ? { day, hourUTC, type: \"monthly\" }\n : { day, hourUTC, minuteUTC, type: \"monthly\" },\n functionReference,\n ...args,\n );\n }\n\n /**\n * Schedule a mutation or action to run on a recurring basis.\n *\n * Like the unix command `cron`, Sunday is 0, Monday is 1, etc.\n *\n * ```\n * \u250C\u2500 minute (0 - 59)\n * \u2502 \u250C\u2500 hour (0 - 23)\n * \u2502 \u2502 \u250C\u2500 day of the month (1 - 31)\n * \u2502 \u2502 \u2502 \u250C\u2500 month (1 - 12)\n * \u2502 \u2502 \u2502 \u2502 \u250C\u2500 day of the week (0 - 6) (Sunday to Saturday)\n * \"* * * * *\"\n * ```\n *\n * @param cronIdentifier - A unique name for this scheduled job.\n * @param cron - Cron string like `\"15 7 * * *\"` (Every day at 7:15 UTC)\n * @param functionReference - A {@link FunctionReference} for the function\n * to schedule.\n * @param args - The arguments to the function.\n */\n cron<FuncRef extends SchedulableFunctionReference>(\n cronIdentifier: string,\n cron: CronString,\n functionReference: FuncRef,\n ...args: OptionalRestArgs<FuncRef>\n ) {\n const c = validatedCronString(cron);\n this.schedule(\n cronIdentifier,\n { cron: c, type: \"cron\" },\n functionReference,\n ...args,\n );\n }\n\n /** @internal */\n export() {\n return JSON.stringify(this.crons);\n }\n}\n"],
|
|
5
|
+
"mappings": ";;;;AAAA,SAAS,uBAAyC;AAClD,SAAS,iBAAiB;AAC1B,SAAS,oBAAsC;AAC/C,SAAS,0BAA0B;AAuBnC,MAAM,eAAe;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAyJO,aAAM,WAAW,MAAM,IAAI,MAAM;AASxC,SAAS,uBAAuB,GAAW;AACzC,MAAI,CAAC,OAAO,UAAU,CAAC,KAAK,KAAK,GAAG;AAClC,UAAM,IAAI,MAAM,4CAA4C;AAAA,EAC9D;AACF;AAEA,SAAS,oBAAoB,GAAW;AACtC,MAAI,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,KAAK,IAAI,IAAI;AAC3C,UAAM,IAAI,MAAM,8CAA8C;AAAA,EAChE;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,GAAW;AACrC,MAAI,CAAC,aAAa,SAAS,CAAc,GAAG;AAC1C,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,SAAO;AACT;AAEA,SAAS,mBAAmB,GAAW;AACrC,MAAI,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,KAAK,IAAI,IAAI;AAC3C,UAAM,IAAI,MAAM,6CAA6C;AAAA,EAC/D;AACA,SAAO;AACT;AAEA,SAAS,sBAAsB,GAAW;AACxC,MAAI,CAAC,OAAO,UAAU,CAAC,KAAK,IAAI,KAAK,IAAI,IAAI;AAC3C,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACA,SAAO;AACT;AAIA,SAAS,8BAA8B,GAAuB;AAC5D,SAAO,MAAM,SAAY,SAAY,sBAAsB,CAAC;AAC9D;AAKA,SAAS,+BACP,KACqC;AACrC,MAAI;AACF,uBAAmB,GAAG;AACtB,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;AAEA,SAAS,oBAAoB,GAAW;AACtC,SAAO;AACT;AAEA,SAAS,wBAAwB,GAAW;AAC1C,MAAI,CAAC,EAAE,MAAM,UAAU,GAAG;AACxB,UAAM,IAAI;AAAA,MACR,2BAA2B,CAAC;AAAA,IAC9B;AAAA,EACF;AACA,SAAO;AACT;AASO,aAAM,MAAM;AAAA,EAGjB,cAAc;AAFd;AACA;AAEE,SAAK,UAAU;AACf,SAAK,QAAQ,CAAC;AAAA,EAChB;AAAA;AAAA,EAGA,SACE,gBACA,UACA,mBACA,MACA;AACA,UAAM,WAAW,UAAU,IAAI;AAC/B,4BAAwB,cAAc;AACtC,QAAI,kBAAkB,KAAK,OAAO;AAChC,YAAM,IAAI,MAAM,qCAAqC,cAAc,EAAE;AAAA,IACvE;AACA,SAAK,MAAM,cAAc,IAAI;AAAA,MAC3B,MAAM,gBAAgB,iBAAiB;AAAA,MACvC,MAAM,CAAC,aAAa,QAAQ,CAAC;AAAA,MAC7B;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAeA,SACE,gBACA,UACA,sBACG,MACH;AACA,UAAM,IAAI;AACV,UAAM,aAAa,EAAE,aAAa,KAAK,EAAE,YAAY;AACrD,UAAM,aAAa,EAAE,aAAa,KAAK,EAAE,YAAY;AACrD,UAAM,WAAW,EAAE,WAAW,KAAK,EAAE,UAAU;AAC/C,UAAM,QAAQ,aAAa,aAAa;AACxC,QAAI,UAAU,GAAG;AACf,YAAM,IAAI,MAAM,gDAAgD;AAAA,IAClE;AACA,QAAI,YAAY;AACd,6BAAuB,SAAS,OAAQ;AAAA,IAC1C,WAAW,YAAY;AACrB,6BAAuB,SAAS,OAAQ;AAAA,IAC1C,WAAW,UAAU;AACnB,6BAAuB,SAAS,KAAM;AAAA,IACxC;AACA,SAAK;AAAA,MACH;AAAA,MACA,EAAE,GAAG,UAAU,MAAM,WAAW;AAAA,MAChC;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA,EAiCA,OACE,gBACA,6BACA,2BACG,MACG;AAGN,QAAI,+BAA+B,2BAA2B,GAAG;AAC/D,WAAK;AAAA,QACH;AAAA,QACA,EAAE,MAAM,SAAS;AAAA,QACjB;AAAA,QACA;AAAA,MACF;AACA;AAAA,IACF;AACA,UAAM,YAAY;AAAA,MAChB,4BAA4B;AAAA,IAC9B;AACA,SAAK;AAAA,MACH;AAAA,MACA,cAAc,SACV,EAAE,MAAM,SAAS,IACjB,EAAE,WAAW,MAAM,SAAS;AAAA,MAChC;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,MACE,gBACA,UACA,sBACG,MACH;AACA,UAAM,UAAU,mBAAmB,SAAS,OAAO;AACnD,UAAM,YAAY,8BAA8B,SAAS,SAAS;AAClE,SAAK;AAAA,MACH;AAAA,MACA,cAAc,SACV,EAAE,SAAS,MAAM,QAAQ,IACzB,EAAE,SAAS,WAAW,MAAM,QAAQ;AAAA,MACxC;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,OACE,gBACA,UACA,sBACG,MACH;AACA,UAAM,YAAY,mBAAmB,SAAS,SAAS;AACvD,UAAM,UAAU,mBAAmB,SAAS,OAAO;AACnD,UAAM,YAAY,8BAA8B,SAAS,SAAS;AAClE,SAAK;AAAA,MACH;AAAA,MACA,cAAc,SACV,EAAE,WAAW,SAAS,MAAM,SAAS,IACrC,EAAE,WAAW,SAAS,WAAW,MAAM,SAAS;AAAA,MACpD;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EA0BA,QACE,gBACA,UACA,sBACG,MACH;AACA,UAAM,MAAM,oBAAoB,SAAS,GAAG;AAC5C,UAAM,UAAU,mBAAmB,SAAS,OAAO;AACnD,UAAM,YAAY,8BAA8B,SAAS,SAAS;AAClE,SAAK;AAAA,MACH;AAAA,MACA,cAAc,SACV,EAAE,KAAK,SAAS,MAAM,UAAU,IAChC,EAAE,KAAK,SAAS,WAAW,MAAM,UAAU;AAAA,MAC/C;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAsBA,KACE,gBACA,MACA,sBACG,MACH;AACA,UAAM,IAAI,oBAAoB,IAAI;AAClC,SAAK;AAAA,MACH;AAAA,MACA,EAAE,MAAM,GAAG,MAAM,OAAO;AAAA,MACxB;AAAA,MACA,GAAG;AAAA,IACL;AAAA,EACF;AAAA;AAAA,EAGA,SAAS;AACP,WAAO,KAAK,UAAU,KAAK,KAAK;AAAA,EAClC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -7,7 +7,7 @@ import { performAsyncSyscall, performSyscall } from "./syscall.js";
|
|
|
7
7
|
import { QueryInitializerImpl } from "./query_impl.js";
|
|
8
8
|
import { validateArg } from "./validate.js";
|
|
9
9
|
import { version } from "../../index.js";
|
|
10
|
-
import { patchValueToJson } from "../../values/value.js";
|
|
10
|
+
import { commitTsPlaceholder, patchValueToJson } from "../../values/value.js";
|
|
11
11
|
async function get(table, id, isSystem) {
|
|
12
12
|
validateArg(id, 1, "get", "id");
|
|
13
13
|
if (typeof id !== "string") {
|
|
@@ -120,6 +120,9 @@ export function setupWriter() {
|
|
|
120
120
|
},
|
|
121
121
|
table: (tableName) => {
|
|
122
122
|
return new TableWriter(tableName, false);
|
|
123
|
+
},
|
|
124
|
+
vars: {
|
|
125
|
+
commitTs: commitTsPlaceholder
|
|
123
126
|
}
|
|
124
127
|
};
|
|
125
128
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/server/impl/database_impl.ts"],
|
|
4
|
-
"sourcesContent": ["import {\n convexToJson,\n GenericId,\n jsonToConvex,\n Value,\n} from \"../../values/index.js\";\nimport { performAsyncSyscall, performSyscall } from \"./syscall.js\";\nimport {\n GenericDatabaseReader,\n GenericDatabaseReaderWithTable,\n GenericDatabaseWriter,\n GenericDatabaseWriterWithTable,\n} from \"../database.js\";\nimport { QueryInitializerImpl } from \"./query_impl.js\";\nimport { GenericDataModel, GenericDocument } from \"../data_model.js\";\nimport { validateArg } from \"./validate.js\";\nimport { version } from \"../../index.js\";\nimport { patchValueToJson } from \"../../values/value.js\";\n\nasync function get(\n table: string | undefined,\n id: GenericId<string>,\n isSystem: boolean,\n) {\n // If the user doesn\u2019t provide any arguments, we use the new signature in the error message.\n // We don\u2019t do argument validation on the table argument since it\u2019s not provided when using the old signature.\n validateArg(id, 1, \"get\", \"id\");\n if (typeof id !== \"string\") {\n throw new Error(\n `Invalid argument \\`id\\` for \\`db.get\\`, expected string but got '${typeof id}': ${\n id as any\n }`,\n );\n }\n const args = {\n id: convexToJson(id),\n isSystem,\n version,\n table,\n };\n const syscallJSON = await performAsyncSyscall(\"1.0/get\", args);\n\n return jsonToConvex(syscallJSON) as GenericDocument;\n}\n\nexport function setupReader(): GenericDatabaseReader<GenericDataModel> {\n const reader = (\n isSystem = false,\n ): GenericDatabaseReader<GenericDataModel> &\n GenericDatabaseReaderWithTable<GenericDataModel> => {\n return {\n get: async (arg0: any, arg1?: any) => {\n return arg1 !== undefined\n ? await get(arg0, arg1, isSystem)\n : await get(undefined, arg0, isSystem);\n },\n query: (tableName: string) => {\n return new TableReader(tableName, isSystem).query();\n },\n normalizeId: <TableName extends string>(\n tableName: TableName,\n id: string,\n ): GenericId<TableName> | null => {\n validateArg(tableName, 1, \"normalizeId\", \"tableName\");\n validateArg(id, 2, \"normalizeId\", \"id\");\n const accessingSystemTable = tableName.startsWith(\"_\");\n if (accessingSystemTable !== isSystem) {\n throw new Error(\n `${\n accessingSystemTable ? \"System\" : \"User\"\n } tables can only be accessed from db.${\n isSystem ? \"\" : \"system.\"\n }normalizeId().`,\n );\n }\n const syscallJSON = performSyscall(\"1.0/db/normalizeId\", {\n table: tableName,\n idString: id,\n });\n const syscallResult = jsonToConvex(syscallJSON) as any;\n return syscallResult.id;\n },\n // We set the system reader on the next line\n system: null as any,\n table: (tableName) => {\n return new TableReader(tableName, isSystem);\n },\n };\n };\n const { system: _, ...rest } = reader(true);\n const r = reader();\n r.system = rest as any;\n return r;\n}\n\nasync function insert(tableName: string, value: any) {\n if (tableName.startsWith(\"_\")) {\n throw new Error(\"System tables (prefixed with `_`) are read-only.\");\n }\n validateArg(tableName, 1, \"insert\", \"table\");\n validateArg(value, 2, \"insert\", \"value\");\n const syscallJSON = await performAsyncSyscall(\"1.0/insert\", {\n table: tableName,\n value: convexToJson(value),\n });\n const syscallResult = jsonToConvex(syscallJSON) as any;\n return syscallResult._id;\n}\n\nasync function patch(table: string | undefined, id: any, value: any) {\n validateArg(id, 1, \"patch\", \"id\");\n validateArg(value, 2, \"patch\", \"value\");\n await performAsyncSyscall(\"1.0/shallowMerge\", {\n id: convexToJson(id),\n value: patchValueToJson(value as Value),\n table,\n });\n}\n\nasync function replace(table: string | undefined, id: any, value: any) {\n validateArg(id, 1, \"replace\", \"id\");\n validateArg(value, 2, \"replace\", \"value\");\n await performAsyncSyscall(\"1.0/replace\", {\n id: convexToJson(id),\n value: convexToJson(value),\n table,\n });\n}\n\nasync function delete_(table: string | undefined, id: any) {\n validateArg(id, 1, \"delete\", \"id\");\n await performAsyncSyscall(\"1.0/remove\", {\n id: convexToJson(id),\n table,\n });\n}\n\nexport function setupWriter(): GenericDatabaseWriter<GenericDataModel> &\n GenericDatabaseWriterWithTable<GenericDataModel> {\n const reader = setupReader();\n return {\n get: reader.get,\n query: reader.query,\n normalizeId: reader.normalizeId,\n system: reader.system as any,\n insert: async (table, value) => {\n return await insert(table, value);\n },\n patch: async (arg0: any, arg1: any, arg2?: any) => {\n return arg2 !== undefined\n ? await patch(arg0, arg1, arg2)\n : await patch(undefined, arg0, arg1);\n },\n replace: async (arg0: any, arg1: any, arg2?: any) => {\n return arg2 !== undefined\n ? await replace(arg0, arg1, arg2)\n : await replace(undefined, arg0, arg1);\n },\n delete: async (arg0: any, arg1?: any) => {\n return arg1 !== undefined\n ? await delete_(arg0, arg1)\n : await delete_(undefined, arg0);\n },\n table: (tableName) => {\n return new TableWriter(tableName, false);\n },\n };\n}\n\nclass TableReader {\n constructor(\n protected readonly tableName: string,\n protected readonly isSystem: boolean,\n ) {}\n\n async get(id: GenericId<string>) {\n return get(this.tableName, id, this.isSystem);\n }\n\n query() {\n const accessingSystemTable = this.tableName.startsWith(\"_\");\n if (accessingSystemTable !== this.isSystem) {\n throw new Error(\n `${\n accessingSystemTable ? \"System\" : \"User\"\n } tables can only be accessed from db.${\n this.isSystem ? \"\" : \"system.\"\n }query().`,\n );\n }\n return new QueryInitializerImpl(this.tableName);\n }\n}\n\nclass TableWriter extends TableReader {\n async insert(value: any) {\n return insert(this.tableName, value);\n }\n async patch(id: any, value: any) {\n return patch(this.tableName, id, value);\n }\n async replace(id: any, value: any) {\n return replace(this.tableName, id, value);\n }\n async delete(id: any) {\n return delete_(this.tableName, id);\n }\n}\n"],
|
|
5
|
-
"mappings": ";AAAA;AAAA,EACE;AAAA,EAEA;AAAA,OAEK;AACP,SAAS,qBAAqB,sBAAsB;AAOpD,SAAS,4BAA4B;AAErC,SAAS,mBAAmB;AAC5B,SAAS,eAAe;AACxB,SAAS,wBAAwB;
|
|
4
|
+
"sourcesContent": ["import {\n convexToJson,\n GenericId,\n jsonToConvex,\n Value,\n} from \"../../values/index.js\";\nimport { performAsyncSyscall, performSyscall } from \"./syscall.js\";\nimport {\n GenericDatabaseReader,\n GenericDatabaseReaderWithTable,\n GenericDatabaseWriter,\n GenericDatabaseWriterWithTable,\n} from \"../database.js\";\nimport { QueryInitializerImpl } from \"./query_impl.js\";\nimport { GenericDataModel, GenericDocument } from \"../data_model.js\";\nimport { validateArg } from \"./validate.js\";\nimport { version } from \"../../index.js\";\nimport { commitTsPlaceholder, patchValueToJson } from \"../../values/value.js\";\n\nasync function get(\n table: string | undefined,\n id: GenericId<string>,\n isSystem: boolean,\n) {\n // If the user doesn\u2019t provide any arguments, we use the new signature in the error message.\n // We don\u2019t do argument validation on the table argument since it\u2019s not provided when using the old signature.\n validateArg(id, 1, \"get\", \"id\");\n if (typeof id !== \"string\") {\n throw new Error(\n `Invalid argument \\`id\\` for \\`db.get\\`, expected string but got '${typeof id}': ${\n id as any\n }`,\n );\n }\n const args = {\n id: convexToJson(id),\n isSystem,\n version,\n table,\n };\n const syscallJSON = await performAsyncSyscall(\"1.0/get\", args);\n\n return jsonToConvex(syscallJSON) as GenericDocument;\n}\n\nexport function setupReader(): GenericDatabaseReader<GenericDataModel> {\n const reader = (\n isSystem = false,\n ): GenericDatabaseReader<GenericDataModel> &\n GenericDatabaseReaderWithTable<GenericDataModel> => {\n return {\n get: async (arg0: any, arg1?: any) => {\n return arg1 !== undefined\n ? await get(arg0, arg1, isSystem)\n : await get(undefined, arg0, isSystem);\n },\n query: (tableName: string) => {\n return new TableReader(tableName, isSystem).query();\n },\n normalizeId: <TableName extends string>(\n tableName: TableName,\n id: string,\n ): GenericId<TableName> | null => {\n validateArg(tableName, 1, \"normalizeId\", \"tableName\");\n validateArg(id, 2, \"normalizeId\", \"id\");\n const accessingSystemTable = tableName.startsWith(\"_\");\n if (accessingSystemTable !== isSystem) {\n throw new Error(\n `${\n accessingSystemTable ? \"System\" : \"User\"\n } tables can only be accessed from db.${\n isSystem ? \"\" : \"system.\"\n }normalizeId().`,\n );\n }\n const syscallJSON = performSyscall(\"1.0/db/normalizeId\", {\n table: tableName,\n idString: id,\n });\n const syscallResult = jsonToConvex(syscallJSON) as any;\n return syscallResult.id;\n },\n // We set the system reader on the next line\n system: null as any,\n table: (tableName) => {\n return new TableReader(tableName, isSystem);\n },\n };\n };\n const { system: _, ...rest } = reader(true);\n const r = reader();\n r.system = rest as any;\n return r;\n}\n\nasync function insert(tableName: string, value: any) {\n if (tableName.startsWith(\"_\")) {\n throw new Error(\"System tables (prefixed with `_`) are read-only.\");\n }\n validateArg(tableName, 1, \"insert\", \"table\");\n validateArg(value, 2, \"insert\", \"value\");\n const syscallJSON = await performAsyncSyscall(\"1.0/insert\", {\n table: tableName,\n value: convexToJson(value),\n });\n const syscallResult = jsonToConvex(syscallJSON) as any;\n return syscallResult._id;\n}\n\nasync function patch(table: string | undefined, id: any, value: any) {\n validateArg(id, 1, \"patch\", \"id\");\n validateArg(value, 2, \"patch\", \"value\");\n await performAsyncSyscall(\"1.0/shallowMerge\", {\n id: convexToJson(id),\n value: patchValueToJson(value as Value),\n table,\n });\n}\n\nasync function replace(table: string | undefined, id: any, value: any) {\n validateArg(id, 1, \"replace\", \"id\");\n validateArg(value, 2, \"replace\", \"value\");\n await performAsyncSyscall(\"1.0/replace\", {\n id: convexToJson(id),\n value: convexToJson(value),\n table,\n });\n}\n\nasync function delete_(table: string | undefined, id: any) {\n validateArg(id, 1, \"delete\", \"id\");\n await performAsyncSyscall(\"1.0/remove\", {\n id: convexToJson(id),\n table,\n });\n}\n\nexport function setupWriter(): GenericDatabaseWriter<GenericDataModel> &\n GenericDatabaseWriterWithTable<GenericDataModel> {\n const reader = setupReader();\n return {\n get: reader.get,\n query: reader.query,\n normalizeId: reader.normalizeId,\n system: reader.system as any,\n insert: async (table, value) => {\n return await insert(table, value);\n },\n patch: async (arg0: any, arg1: any, arg2?: any) => {\n return arg2 !== undefined\n ? await patch(arg0, arg1, arg2)\n : await patch(undefined, arg0, arg1);\n },\n replace: async (arg0: any, arg1: any, arg2?: any) => {\n return arg2 !== undefined\n ? await replace(arg0, arg1, arg2)\n : await replace(undefined, arg0, arg1);\n },\n delete: async (arg0: any, arg1?: any) => {\n return arg1 !== undefined\n ? await delete_(arg0, arg1)\n : await delete_(undefined, arg0);\n },\n table: (tableName) => {\n return new TableWriter(tableName, false);\n },\n vars: {\n commitTs: commitTsPlaceholder,\n },\n };\n}\n\nclass TableReader {\n constructor(\n protected readonly tableName: string,\n protected readonly isSystem: boolean,\n ) {}\n\n async get(id: GenericId<string>) {\n return get(this.tableName, id, this.isSystem);\n }\n\n query() {\n const accessingSystemTable = this.tableName.startsWith(\"_\");\n if (accessingSystemTable !== this.isSystem) {\n throw new Error(\n `${\n accessingSystemTable ? \"System\" : \"User\"\n } tables can only be accessed from db.${\n this.isSystem ? \"\" : \"system.\"\n }query().`,\n );\n }\n return new QueryInitializerImpl(this.tableName);\n }\n}\n\nclass TableWriter extends TableReader {\n async insert(value: any) {\n return insert(this.tableName, value);\n }\n async patch(id: any, value: any) {\n return patch(this.tableName, id, value);\n }\n async replace(id: any, value: any) {\n return replace(this.tableName, id, value);\n }\n async delete(id: any) {\n return delete_(this.tableName, id);\n }\n}\n"],
|
|
5
|
+
"mappings": ";AAAA;AAAA,EACE;AAAA,EAEA;AAAA,OAEK;AACP,SAAS,qBAAqB,sBAAsB;AAOpD,SAAS,4BAA4B;AAErC,SAAS,mBAAmB;AAC5B,SAAS,eAAe;AACxB,SAAS,qBAAqB,wBAAwB;AAEtD,eAAe,IACb,OACA,IACA,UACA;AAGA,cAAY,IAAI,GAAG,OAAO,IAAI;AAC9B,MAAI,OAAO,OAAO,UAAU;AAC1B,UAAM,IAAI;AAAA,MACR,oEAAoE,OAAO,EAAE,MAC3E,EACF;AAAA,IACF;AAAA,EACF;AACA,QAAM,OAAO;AAAA,IACX,IAAI,aAAa,EAAE;AAAA,IACnB;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACA,QAAM,cAAc,MAAM,oBAAoB,WAAW,IAAI;AAE7D,SAAO,aAAa,WAAW;AACjC;AAEO,gBAAS,cAAuD;AACrE,QAAM,SAAS,CACb,WAAW,UAEyC;AACpD,WAAO;AAAA,MACL,KAAK,OAAO,MAAW,SAAe;AACpC,eAAO,SAAS,SACZ,MAAM,IAAI,MAAM,MAAM,QAAQ,IAC9B,MAAM,IAAI,QAAW,MAAM,QAAQ;AAAA,MACzC;AAAA,MACA,OAAO,CAAC,cAAsB;AAC5B,eAAO,IAAI,YAAY,WAAW,QAAQ,EAAE,MAAM;AAAA,MACpD;AAAA,MACA,aAAa,CACX,WACA,OACgC;AAChC,oBAAY,WAAW,GAAG,eAAe,WAAW;AACpD,oBAAY,IAAI,GAAG,eAAe,IAAI;AACtC,cAAM,uBAAuB,UAAU,WAAW,GAAG;AACrD,YAAI,yBAAyB,UAAU;AACrC,gBAAM,IAAI;AAAA,YACR,GACE,uBAAuB,WAAW,MACpC,wCACE,WAAW,KAAK,SAClB;AAAA,UACF;AAAA,QACF;AACA,cAAM,cAAc,eAAe,sBAAsB;AAAA,UACvD,OAAO;AAAA,UACP,UAAU;AAAA,QACZ,CAAC;AACD,cAAM,gBAAgB,aAAa,WAAW;AAC9C,eAAO,cAAc;AAAA,MACvB;AAAA;AAAA,MAEA,QAAQ;AAAA,MACR,OAAO,CAAC,cAAc;AACpB,eAAO,IAAI,YAAY,WAAW,QAAQ;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AACA,QAAM,EAAE,QAAQ,GAAG,GAAG,KAAK,IAAI,OAAO,IAAI;AAC1C,QAAM,IAAI,OAAO;AACjB,IAAE,SAAS;AACX,SAAO;AACT;AAEA,eAAe,OAAO,WAAmB,OAAY;AACnD,MAAI,UAAU,WAAW,GAAG,GAAG;AAC7B,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACpE;AACA,cAAY,WAAW,GAAG,UAAU,OAAO;AAC3C,cAAY,OAAO,GAAG,UAAU,OAAO;AACvC,QAAM,cAAc,MAAM,oBAAoB,cAAc;AAAA,IAC1D,OAAO;AAAA,IACP,OAAO,aAAa,KAAK;AAAA,EAC3B,CAAC;AACD,QAAM,gBAAgB,aAAa,WAAW;AAC9C,SAAO,cAAc;AACvB;AAEA,eAAe,MAAM,OAA2B,IAAS,OAAY;AACnE,cAAY,IAAI,GAAG,SAAS,IAAI;AAChC,cAAY,OAAO,GAAG,SAAS,OAAO;AACtC,QAAM,oBAAoB,oBAAoB;AAAA,IAC5C,IAAI,aAAa,EAAE;AAAA,IACnB,OAAO,iBAAiB,KAAc;AAAA,IACtC;AAAA,EACF,CAAC;AACH;AAEA,eAAe,QAAQ,OAA2B,IAAS,OAAY;AACrE,cAAY,IAAI,GAAG,WAAW,IAAI;AAClC,cAAY,OAAO,GAAG,WAAW,OAAO;AACxC,QAAM,oBAAoB,eAAe;AAAA,IACvC,IAAI,aAAa,EAAE;AAAA,IACnB,OAAO,aAAa,KAAK;AAAA,IACzB;AAAA,EACF,CAAC;AACH;AAEA,eAAe,QAAQ,OAA2B,IAAS;AACzD,cAAY,IAAI,GAAG,UAAU,IAAI;AACjC,QAAM,oBAAoB,cAAc;AAAA,IACtC,IAAI,aAAa,EAAE;AAAA,IACnB;AAAA,EACF,CAAC;AACH;AAEO,gBAAS,cACmC;AACjD,QAAM,SAAS,YAAY;AAC3B,SAAO;AAAA,IACL,KAAK,OAAO;AAAA,IACZ,OAAO,OAAO;AAAA,IACd,aAAa,OAAO;AAAA,IACpB,QAAQ,OAAO;AAAA,IACf,QAAQ,OAAO,OAAO,UAAU;AAC9B,aAAO,MAAM,OAAO,OAAO,KAAK;AAAA,IAClC;AAAA,IACA,OAAO,OAAO,MAAW,MAAW,SAAe;AACjD,aAAO,SAAS,SACZ,MAAM,MAAM,MAAM,MAAM,IAAI,IAC5B,MAAM,MAAM,QAAW,MAAM,IAAI;AAAA,IACvC;AAAA,IACA,SAAS,OAAO,MAAW,MAAW,SAAe;AACnD,aAAO,SAAS,SACZ,MAAM,QAAQ,MAAM,MAAM,IAAI,IAC9B,MAAM,QAAQ,QAAW,MAAM,IAAI;AAAA,IACzC;AAAA,IACA,QAAQ,OAAO,MAAW,SAAe;AACvC,aAAO,SAAS,SACZ,MAAM,QAAQ,MAAM,IAAI,IACxB,MAAM,QAAQ,QAAW,IAAI;AAAA,IACnC;AAAA,IACA,OAAO,CAAC,cAAc;AACpB,aAAO,IAAI,YAAY,WAAW,KAAK;AAAA,IACzC;AAAA,IACA,MAAM;AAAA,MACJ,UAAU;AAAA,IACZ;AAAA,EACF;AACF;AAEA,MAAM,YAAY;AAAA,EAChB,YACqB,WACA,UACnB;AAFmB;AACA;AAAA,EAClB;AAAA,EAEH,MAAM,IAAI,IAAuB;AAC/B,WAAO,IAAI,KAAK,WAAW,IAAI,KAAK,QAAQ;AAAA,EAC9C;AAAA,EAEA,QAAQ;AACN,UAAM,uBAAuB,KAAK,UAAU,WAAW,GAAG;AAC1D,QAAI,yBAAyB,KAAK,UAAU;AAC1C,YAAM,IAAI;AAAA,QACR,GACE,uBAAuB,WAAW,MACpC,wCACE,KAAK,WAAW,KAAK,SACvB;AAAA,MACF;AAAA,IACF;AACA,WAAO,IAAI,qBAAqB,KAAK,SAAS;AAAA,EAChD;AACF;AAEA,MAAM,oBAAoB,YAAY;AAAA,EACpC,MAAM,OAAO,OAAY;AACvB,WAAO,OAAO,KAAK,WAAW,KAAK;AAAA,EACrC;AAAA,EACA,MAAM,MAAM,IAAS,OAAY;AAC/B,WAAO,MAAM,KAAK,WAAW,IAAI,KAAK;AAAA,EACxC;AAAA,EACA,MAAM,QAAQ,IAAS,OAAY;AACjC,WAAO,QAAQ,KAAK,WAAW,IAAI,KAAK;AAAA,EAC1C;AAAA,EACA,MAAM,OAAO,IAAS;AACpB,WAAO,QAAQ,KAAK,WAAW,EAAE;AAAA,EACnC;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/server/log.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/server/log.ts"],
|
|
4
|
-
"sourcesContent": ["import { audit } from \"./audit_logging.js\";\nimport { vars } from \"./logVars.js\";\n\n// Type annotations are needed for the `unique symbol` types in `vars` to typecheck correctly\ninterface Log {\n /**\n * Emit a durable audit log. This functionality is only available for Convex\n * Enterprise (see https://www.convex.dev/enterprise/pricing).\n *\n * Use dynamic variables from `log.vars` to include deferred values that will\n * be resolved when emitting the log. Cached query hits will replay audit logs\n * with updated values.\n * ```ts\n * await log.audit({\n * action: \"document.viewed\",\n * actor: { userId },\n * source: {\n * ip: log.vars.ip,\n * userAgent: log.vars.userAgent,\n * },\n * timestamp: log.vars.now,\n * });\n * ```\n *\n * The log body must be JSON-serializable.\n */\n audit: typeof audit;\n vars: typeof vars;\n}\n\nexport const log: Log = {\n audit,\n vars,\n};\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,aAAa;AACtB,SAAS,YAAY;
|
|
4
|
+
"sourcesContent": ["import { audit } from \"./audit_logging.js\";\nimport { internalVars, vars } from \"./logVars.js\";\n\n// Type annotations are needed for the `unique symbol` types in `vars` to typecheck correctly\ninterface Log {\n /**\n * Emit a durable audit log. This functionality is only available for Convex\n * Enterprise (see https://www.convex.dev/enterprise/pricing).\n *\n * Use dynamic variables from `log.vars` to include deferred values that will\n * be resolved when emitting the log. Cached query hits will replay audit logs\n * with updated values.\n * ```ts\n * await log.audit({\n * action: \"document.viewed\",\n * actor: { userId },\n * source: {\n * ip: log.vars.ip,\n * userAgent: log.vars.userAgent,\n * },\n * timestamp: log.vars.now,\n * });\n * ```\n *\n * The log body must be JSON-serializable.\n */\n audit: typeof audit;\n vars: typeof vars;\n /** @internal */\n internalVars: typeof internalVars;\n}\n\nexport const log: Log = {\n audit,\n vars,\n internalVars,\n};\n"],
|
|
5
|
+
"mappings": ";AAAA,SAAS,aAAa;AACtB,SAAS,cAAc,YAAY;AA+B5B,aAAM,MAAW;AAAA,EACtB;AAAA,EACA;AAAA,EACA;AACF;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,11 +3,13 @@ const REQUEST_ID = Symbol("var.requestId");
|
|
|
3
3
|
const IP = Symbol("var.ip");
|
|
4
4
|
const USER_AGENT = Symbol("var.userAgent");
|
|
5
5
|
const NOW = Symbol("var.now");
|
|
6
|
+
const CONVEX_ACTOR = Symbol("var.convexActor");
|
|
6
7
|
export const varNames = {
|
|
7
8
|
[REQUEST_ID]: "requestId",
|
|
8
9
|
[IP]: "ip",
|
|
9
10
|
[USER_AGENT]: "userAgent",
|
|
10
|
-
[NOW]: "now"
|
|
11
|
+
[NOW]: "now",
|
|
12
|
+
[CONVEX_ACTOR]: "convexActor"
|
|
11
13
|
};
|
|
12
14
|
export const vars = {
|
|
13
15
|
/** Resolved to the request ID. */
|
|
@@ -22,4 +24,12 @@ export const vars = {
|
|
|
22
24
|
*/
|
|
23
25
|
now: NOW
|
|
24
26
|
};
|
|
27
|
+
export const internalVars = {
|
|
28
|
+
/**
|
|
29
|
+
* If the function was invoked using admin auth (either directly or while
|
|
30
|
+
* acting as an end user, e.g. from the dashboard), resolved to information
|
|
31
|
+
* about the admin. Otherwise, resolved to `null`.
|
|
32
|
+
*/
|
|
33
|
+
convexActor: CONVEX_ACTOR
|
|
34
|
+
};
|
|
25
35
|
//# sourceMappingURL=logVars.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/server/logVars.ts"],
|
|
4
|
-
"sourcesContent": ["const REQUEST_ID = Symbol(\"var.requestId\");\nconst IP = Symbol(\"var.ip\");\nconst USER_AGENT = Symbol(\"var.userAgent\");\nconst NOW = Symbol(\"var.now\");\n\nexport type LogVar =\n | typeof REQUEST_ID\n | typeof IP\n | typeof USER_AGENT\n | typeof NOW;\n\nexport const varNames: Record<symbol, string> = {\n [REQUEST_ID]: \"requestId\",\n [IP]: \"ip\",\n [USER_AGENT]: \"userAgent\",\n [NOW]: \"now\",\n};\n\nexport const vars = {\n /** Resolved to the request ID. */\n requestId: REQUEST_ID,\n /** Resolved to the client's IP address. */\n ip: IP,\n /** Resolved to the client's User-Agent header. */\n userAgent: USER_AGENT,\n /**\n * Resolved to the current server timestamp, as milliseconds from the\n * Unix epoch.\n */\n now: NOW,\n} as const;\n"],
|
|
5
|
-
"mappings": ";AAAA,MAAM,aAAa,OAAO,eAAe;AACzC,MAAM,KAAK,OAAO,QAAQ;AAC1B,MAAM,aAAa,OAAO,eAAe;AACzC,MAAM,MAAM,OAAO,SAAS;
|
|
4
|
+
"sourcesContent": ["const REQUEST_ID = Symbol(\"var.requestId\");\nconst IP = Symbol(\"var.ip\");\nconst USER_AGENT = Symbol(\"var.userAgent\");\nconst NOW = Symbol(\"var.now\");\nconst CONVEX_ACTOR = Symbol(\"var.convexActor\");\n\nexport type LogVar =\n | typeof REQUEST_ID\n | typeof IP\n | typeof USER_AGENT\n | typeof NOW\n | typeof CONVEX_ACTOR;\n\nexport const varNames: Record<symbol, string> = {\n [REQUEST_ID]: \"requestId\",\n [IP]: \"ip\",\n [USER_AGENT]: \"userAgent\",\n [NOW]: \"now\",\n [CONVEX_ACTOR]: \"convexActor\",\n};\n\nexport const vars = {\n /** Resolved to the request ID. */\n requestId: REQUEST_ID,\n /** Resolved to the client's IP address. */\n ip: IP,\n /** Resolved to the client's User-Agent header. */\n userAgent: USER_AGENT,\n /**\n * Resolved to the current server timestamp, as milliseconds from the\n * Unix epoch.\n */\n now: NOW,\n} as const;\n\n/**\n * Internal-only log vars, surfaced via `log.internalVars`. These are kept out\n * of the public `log.vars` surface.\n */\nexport const internalVars = {\n /**\n * If the function was invoked using admin auth (either directly or while\n * acting as an end user, e.g. from the dashboard), resolved to information\n * about the admin. Otherwise, resolved to `null`.\n */\n convexActor: CONVEX_ACTOR,\n} as const;\n"],
|
|
5
|
+
"mappings": ";AAAA,MAAM,aAAa,OAAO,eAAe;AACzC,MAAM,KAAK,OAAO,QAAQ;AAC1B,MAAM,aAAa,OAAO,eAAe;AACzC,MAAM,MAAM,OAAO,SAAS;AAC5B,MAAM,eAAe,OAAO,iBAAiB;AAStC,aAAM,WAAmC;AAAA,EAC9C,CAAC,UAAU,GAAG;AAAA,EACd,CAAC,EAAE,GAAG;AAAA,EACN,CAAC,UAAU,GAAG;AAAA,EACd,CAAC,GAAG,GAAG;AAAA,EACP,CAAC,YAAY,GAAG;AAClB;AAEO,aAAM,OAAO;AAAA;AAAA,EAElB,WAAW;AAAA;AAAA,EAEX,IAAI;AAAA;AAAA,EAEJ,WAAW;AAAA;AAAA;AAAA;AAAA;AAAA,EAKX,KAAK;AACP;AAMO,aAAM,eAAe;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAM1B,aAAa;AACf;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
import { CommitTsPlaceholder, MAX_INT64 } from "./value.js";
|
|
2
3
|
import { compareUTF8 } from "./compare_utf8.js";
|
|
3
4
|
export function compareValues(k1, k2) {
|
|
4
5
|
return compareAsTuples(makeComparable(k1), makeComparable(k2));
|
|
@@ -111,6 +112,9 @@ function makeComparable(v) {
|
|
|
111
112
|
if (typeof v === "bigint") {
|
|
112
113
|
return [2, v];
|
|
113
114
|
}
|
|
115
|
+
if (v instanceof CommitTsPlaceholder) {
|
|
116
|
+
return [2, MAX_INT64];
|
|
117
|
+
}
|
|
114
118
|
if (typeof v === "number") {
|
|
115
119
|
return [3, v];
|
|
116
120
|
}
|
|
@@ -128,6 +132,6 @@ function makeComparable(v) {
|
|
|
128
132
|
}
|
|
129
133
|
const keys = Object.keys(v).sort();
|
|
130
134
|
const pojo = keys.map((k) => [k, v[k]]);
|
|
131
|
-
return [
|
|
135
|
+
return [9, pojo.map(makeComparable)];
|
|
132
136
|
}
|
|
133
137
|
//# sourceMappingURL=compare.js.map
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/values/compare.ts"],
|
|
4
|
-
"sourcesContent": ["import { Value } from \"./value.js\";\nimport { compareUTF8 } from \"./compare_utf8.js\";\n\nexport function compareValues(k1: Value | undefined, k2: Value | undefined) {\n return compareAsTuples(makeComparable(k1), makeComparable(k2));\n}\n\nfunction compareAsTuples<T>(a: [number, T], b: [number, T]): number {\n if (a[0] === b[0]) {\n return compareSameTypeValues(a[1], b[1]);\n } else if (a[0] < b[0]) {\n return -1;\n }\n return 1;\n}\n\nfunction compareSameTypeValues<T>(v1: T, v2: T): number {\n if (v1 === undefined || v1 === null) {\n return 0;\n }\n if (typeof v1 === \"number\") {\n if (typeof v2 !== \"number\") {\n throw new Error(`Unexpected type ${v2 as any}`);\n }\n return compareNumbers(v1, v2);\n }\n if (typeof v1 === \"string\") {\n if (typeof v2 !== \"string\") {\n throw new Error(`Unexpected type ${v2 as any}`);\n }\n return compareUTF8(v1, v2);\n }\n if (\n typeof v1 === \"bigint\" ||\n typeof v1 === \"boolean\" ||\n typeof v1 === \"string\"\n ) {\n return v1 < v2 ? -1 : v1 === v2 ? 0 : 1;\n }\n if (!Array.isArray(v1) || !Array.isArray(v2)) {\n throw new Error(`Unexpected type ${v1 as any}`);\n }\n for (let i = 0; i < v1.length && i < v2.length; i++) {\n const cmp = compareAsTuples(v1[i], v2[i]);\n if (cmp !== 0) {\n return cmp;\n }\n }\n if (v1.length < v2.length) {\n return -1;\n }\n if (v1.length > v2.length) {\n return 1;\n }\n return 0;\n}\n\nfunction compareNumbers(v1: number, v2: number): number {\n // Handle NaN values\n if (isNaN(v1) || isNaN(v2)) {\n // Create DataViews for bit-level comparison\n const buffer1 = new ArrayBuffer(8);\n const buffer2 = new ArrayBuffer(8);\n new DataView(buffer1).setFloat64(0, v1, /* little-endian */ true);\n new DataView(buffer2).setFloat64(0, v2, /* little-endian */ true);\n\n // Read as BigInt to compare bits\n const v1Bits = BigInt(\n new DataView(buffer1).getBigInt64(0, /* little-endian */ true),\n );\n const v2Bits = BigInt(\n new DataView(buffer2).getBigInt64(0, /* little-endian */ true),\n );\n\n // The sign bit is the most significant bit (bit 63)\n const v1Sign = (v1Bits & 0x8000000000000000n) !== 0n;\n const v2Sign = (v2Bits & 0x8000000000000000n) !== 0n;\n\n // If one value is NaN and the other isn't, use sign bits first\n if (isNaN(v1) !== isNaN(v2)) {\n // If v1 is NaN, compare based on sign bits\n if (isNaN(v1)) {\n return v1Sign ? -1 : 1;\n }\n // If v2 is NaN, compare based on sign bits\n return v2Sign ? 1 : -1;\n }\n\n // If both are NaN, compare their binary representations\n if (v1Sign !== v2Sign) {\n return v1Sign ? -1 : 1; // true means negative\n }\n return v1Bits < v2Bits ? -1 : v1Bits === v2Bits ? 0 : 1;\n }\n\n if (Object.is(v1, v2)) {\n return 0;\n }\n\n if (Object.is(v1, -0)) {\n return Object.is(v2, 0) ? -1 : -Math.sign(v2);\n }\n if (Object.is(v2, -0)) {\n return Object.is(v1, 0) ? 1 : Math.sign(v1);\n }\n\n // Handle regular number comparison\n return v1 < v2 ? -1 : 1;\n}\n\n// Returns an array which can be compared to other arrays as if they were tuples.\n// For example, [1, null] < [2, 1n] means null sorts before all bigints\n// And [3, 5] < [3, 6] means floats sort as expected\n// And [7, [[5, \"a\"]]] < [7, [[5, \"a\"], [5, \"b\"]]] means arrays sort as expected\nfunction makeComparable(v: Value | undefined): [number, any] {\n if (v === undefined) {\n return [0, undefined];\n }\n if (v === null) {\n return [1, null];\n }\n if (typeof v === \"bigint\") {\n return [2, v];\n }\n if (typeof v === \"number\") {\n return [3, v];\n }\n if (typeof v === \"boolean\") {\n return [4, v];\n }\n if (typeof v === \"string\") {\n return [5, v];\n }\n if (v instanceof ArrayBuffer) {\n return [6, Array.from(new Uint8Array(v)).map(makeComparable)];\n }\n if (Array.isArray(v)) {\n return [7, v.map(makeComparable)];\n }\n // Otherwise, it's an POJO.\n const keys = Object.keys(v).sort();\n const pojo: Value[] = keys.map((k) => [k, v[k]!]);\n return [
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["import { CommitTsPlaceholder, MAX_INT64, Value } from \"./value.js\";\nimport { compareUTF8 } from \"./compare_utf8.js\";\n\nexport function compareValues(k1: Value | undefined, k2: Value | undefined) {\n return compareAsTuples(makeComparable(k1), makeComparable(k2));\n}\n\nfunction compareAsTuples<T>(a: [number, T], b: [number, T]): number {\n if (a[0] === b[0]) {\n return compareSameTypeValues(a[1], b[1]);\n } else if (a[0] < b[0]) {\n return -1;\n }\n return 1;\n}\n\nfunction compareSameTypeValues<T>(v1: T, v2: T): number {\n if (v1 === undefined || v1 === null) {\n return 0;\n }\n if (typeof v1 === \"number\") {\n if (typeof v2 !== \"number\") {\n throw new Error(`Unexpected type ${v2 as any}`);\n }\n return compareNumbers(v1, v2);\n }\n if (typeof v1 === \"string\") {\n if (typeof v2 !== \"string\") {\n throw new Error(`Unexpected type ${v2 as any}`);\n }\n return compareUTF8(v1, v2);\n }\n if (\n typeof v1 === \"bigint\" ||\n typeof v1 === \"boolean\" ||\n typeof v1 === \"string\"\n ) {\n return v1 < v2 ? -1 : v1 === v2 ? 0 : 1;\n }\n if (!Array.isArray(v1) || !Array.isArray(v2)) {\n throw new Error(`Unexpected type ${v1 as any}`);\n }\n for (let i = 0; i < v1.length && i < v2.length; i++) {\n const cmp = compareAsTuples(v1[i], v2[i]);\n if (cmp !== 0) {\n return cmp;\n }\n }\n if (v1.length < v2.length) {\n return -1;\n }\n if (v1.length > v2.length) {\n return 1;\n }\n return 0;\n}\n\nfunction compareNumbers(v1: number, v2: number): number {\n // Handle NaN values\n if (isNaN(v1) || isNaN(v2)) {\n // Create DataViews for bit-level comparison\n const buffer1 = new ArrayBuffer(8);\n const buffer2 = new ArrayBuffer(8);\n new DataView(buffer1).setFloat64(0, v1, /* little-endian */ true);\n new DataView(buffer2).setFloat64(0, v2, /* little-endian */ true);\n\n // Read as BigInt to compare bits\n const v1Bits = BigInt(\n new DataView(buffer1).getBigInt64(0, /* little-endian */ true),\n );\n const v2Bits = BigInt(\n new DataView(buffer2).getBigInt64(0, /* little-endian */ true),\n );\n\n // The sign bit is the most significant bit (bit 63)\n const v1Sign = (v1Bits & 0x8000000000000000n) !== 0n;\n const v2Sign = (v2Bits & 0x8000000000000000n) !== 0n;\n\n // If one value is NaN and the other isn't, use sign bits first\n if (isNaN(v1) !== isNaN(v2)) {\n // If v1 is NaN, compare based on sign bits\n if (isNaN(v1)) {\n return v1Sign ? -1 : 1;\n }\n // If v2 is NaN, compare based on sign bits\n return v2Sign ? 1 : -1;\n }\n\n // If both are NaN, compare their binary representations\n if (v1Sign !== v2Sign) {\n return v1Sign ? -1 : 1; // true means negative\n }\n return v1Bits < v2Bits ? -1 : v1Bits === v2Bits ? 0 : 1;\n }\n\n if (Object.is(v1, v2)) {\n return 0;\n }\n\n if (Object.is(v1, -0)) {\n return Object.is(v2, 0) ? -1 : -Math.sign(v2);\n }\n if (Object.is(v2, -0)) {\n return Object.is(v1, 0) ? 1 : Math.sign(v1);\n }\n\n // Handle regular number comparison\n return v1 < v2 ? -1 : 1;\n}\n\n// Returns an array which can be compared to other arrays as if they were tuples.\n// For example, [1, null] < [2, 1n] means null sorts before all bigints\n// And [3, 5] < [3, 6] means floats sort as expected\n// And [7, [[5, \"a\"]]] < [7, [[5, \"a\"], [5, \"b\"]]] means arrays sort as expected\nfunction makeComparable(v: Value | undefined): [number, any] {\n if (v === undefined) {\n return [0, undefined];\n }\n if (v === null) {\n return [1, null];\n }\n if (typeof v === \"bigint\") {\n return [2, v];\n }\n if (v instanceof CommitTsPlaceholder) {\n return [2, MAX_INT64];\n }\n if (typeof v === \"number\") {\n return [3, v];\n }\n if (typeof v === \"boolean\") {\n return [4, v];\n }\n if (typeof v === \"string\") {\n return [5, v];\n }\n if (v instanceof ArrayBuffer) {\n return [6, Array.from(new Uint8Array(v)).map(makeComparable)];\n }\n if (Array.isArray(v)) {\n return [7, v.map(makeComparable)];\n }\n // Otherwise, it's an POJO.\n const keys = Object.keys(v).sort();\n const pojo: Value[] = keys.map((k) => [k, v[k]!]);\n return [9, pojo.map(makeComparable)];\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/values/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
export { convexToJson, jsonToConvex } from "./value.js";
|
|
2
|
+
export { convexToJson, jsonToConvex, CommitTsPlaceholder } from "./value.js";
|
|
3
3
|
export { v, asObjectValidator } from "./validator.js";
|
|
4
4
|
import * as Base64 from "./base64.js";
|
|
5
5
|
export { Base64 };
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/values/index.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Utilities for working with values stored in Convex.\n *\n * You can see the full set of supported types at\n * [Types](https://docs.convex.dev/using/types).\n * @module\n */\n\nexport { convexToJson, jsonToConvex } from \"./value.js\";\nexport type {\n Id as GenericId,\n JSONValue,\n Value,\n NumericValue,\n} from \"./value.js\";\nexport { v, asObjectValidator } from \"./validator.js\";\nexport type {\n AsObjectValidator,\n GenericValidator,\n ObjectType,\n PropertyValidators,\n} from \"./validator.js\";\nexport type {\n ValidatorJSON,\n RecordKeyValidatorJSON,\n RecordValueValidatorJSON,\n ObjectFieldType,\n Validator,\n OptionalProperty,\n VId,\n VFloat64,\n VInt64,\n VBoolean,\n VBytes,\n VString,\n VNull,\n VAny,\n VObject,\n VLiteral,\n VArray,\n VRecord,\n VUnion,\n VOptional,\n} from \"./validators.js\";\nimport * as Base64 from \"./base64.js\";\nexport { Base64 };\nexport type { Infer } from \"./validator.js\";\nexport * from \"./errors.js\";\nexport { compareValues } from \"./compare.js\";\nexport { getConvexSize, getDocumentSize } from \"./size.js\";\n"],
|
|
5
|
-
"mappings": ";AAQA,SAAS,cAAc,
|
|
4
|
+
"sourcesContent": ["/**\n * Utilities for working with values stored in Convex.\n *\n * You can see the full set of supported types at\n * [Types](https://docs.convex.dev/using/types).\n * @module\n */\n\nexport { convexToJson, jsonToConvex, CommitTsPlaceholder } from \"./value.js\";\nexport type {\n Id as GenericId,\n JSONValue,\n Value,\n NumericValue,\n} from \"./value.js\";\nexport { v, asObjectValidator } from \"./validator.js\";\nexport type {\n AsObjectValidator,\n GenericValidator,\n ObjectType,\n PropertyValidators,\n} from \"./validator.js\";\nexport type {\n ValidatorJSON,\n RecordKeyValidatorJSON,\n RecordValueValidatorJSON,\n ObjectFieldType,\n Validator,\n OptionalProperty,\n VId,\n VFloat64,\n VInt64,\n VCommitTs,\n VBoolean,\n VBytes,\n VString,\n VNull,\n VAny,\n VObject,\n VLiteral,\n VArray,\n VRecord,\n VUnion,\n VOptional,\n} from \"./validators.js\";\nimport * as Base64 from \"./base64.js\";\nexport { Base64 };\nexport type { Infer } from \"./validator.js\";\nexport * from \"./errors.js\";\nexport { compareValues } from \"./compare.js\";\nexport { getConvexSize, getDocumentSize } from \"./size.js\";\n"],
|
|
5
|
+
"mappings": ";AAQA,SAAS,cAAc,cAAc,2BAA2B;AAOhE,SAAS,GAAG,yBAAyB;AA8BrC,YAAY,YAAY;AACxB,SAAS;AAET,cAAc;AACd,SAAS,qBAAqB;AAC9B,SAAS,eAAe,uBAAuB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
package/dist/esm/values/size.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
import { CommitTsPlaceholder } from "./value.js";
|
|
2
3
|
import { isSimpleObject } from "../common/index.js";
|
|
3
4
|
export function getConvexSize(value) {
|
|
4
5
|
if (value === void 0) {
|
|
@@ -13,6 +14,9 @@ export function getConvexSize(value) {
|
|
|
13
14
|
if (typeof value === "bigint") {
|
|
14
15
|
return 9;
|
|
15
16
|
}
|
|
17
|
+
if (value instanceof CommitTsPlaceholder) {
|
|
18
|
+
return 9;
|
|
19
|
+
}
|
|
16
20
|
if (typeof value === "number") {
|
|
17
21
|
return 9;
|
|
18
22
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/values/size.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Calculate the size of a Convex value in bytes.\n *\n * This matches the Rust implementation in crates/value/src/ which is used\n * to compute bandwidth and document size limits.\n *\n * Size formula by type:\n * - Undefined: 0 bytes (not a valid Convex value, but returns 0 for convenience)\n * - Null: 1 byte (type marker)\n * - Boolean: 1 byte (type marker, value stored in marker)\n * - Int64 (bigint): 9 bytes (1 type marker + 8 bytes for 64-bit value)\n * - Float64 (number): 9 bytes (1 type marker + 8 bytes for 64-bit value)\n * - String: 2 + string.length bytes (1 type marker + UTF-8 bytes + 1 null terminator)\n * - Bytes (ArrayBuffer): 2 + bytes.length bytes (1 type marker + bytes + 1 terminator)\n * - Array: 2 + sum(element sizes) bytes (1 type marker + elements + 1 terminator)\n * - Object: 2 + sum(field_name.length + 1 + value.size) bytes\n * (1 type marker + (field_name + null terminator + value)* + 1 terminator)\n *\n * For documents with system fields (_id and _creationTime), the size includes:\n * - _id field: 4 bytes (field name + null) + string size (2 + 31+ chars)\n * - _creationTime field: 14 bytes (field name + null) + 9 bytes (Float64)\n *\n * @module\n */\n\nimport type
|
|
5
|
-
"mappings": ";
|
|
4
|
+
"sourcesContent": ["/**\n * Calculate the size of a Convex value in bytes.\n *\n * This matches the Rust implementation in crates/value/src/ which is used\n * to compute bandwidth and document size limits.\n *\n * Size formula by type:\n * - Undefined: 0 bytes (not a valid Convex value, but returns 0 for convenience)\n * - Null: 1 byte (type marker)\n * - Boolean: 1 byte (type marker, value stored in marker)\n * - Int64 (bigint): 9 bytes (1 type marker + 8 bytes for 64-bit value)\n * - Float64 (number): 9 bytes (1 type marker + 8 bytes for 64-bit value)\n * - String: 2 + string.length bytes (1 type marker + UTF-8 bytes + 1 null terminator)\n * - Bytes (ArrayBuffer): 2 + bytes.length bytes (1 type marker + bytes + 1 terminator)\n * - Array: 2 + sum(element sizes) bytes (1 type marker + elements + 1 terminator)\n * - Object: 2 + sum(field_name.length + 1 + value.size) bytes\n * (1 type marker + (field_name + null terminator + value)* + 1 terminator)\n *\n * For documents with system fields (_id and _creationTime), the size includes:\n * - _id field: 4 bytes (field name + null) + string size (2 + 31+ chars)\n * - _creationTime field: 14 bytes (field name + null) + 9 bytes (Float64)\n *\n * @module\n */\n\nimport { CommitTsPlaceholder, type Value } from \"./value.js\";\nimport { isSimpleObject } from \"../common/index.js\";\n\n/**\n * Calculate the size in bytes of a Convex value.\n *\n * This matches how Convex calculates document size for bandwidth tracking\n * and size limit enforcement.\n *\n * @param value - A Convex value to measure\n * @returns The size in bytes\n *\n * @public\n */\nexport function getConvexSize(value: Value | undefined): number {\n if (value === undefined) {\n return 0;\n }\n if (value === null) {\n return 1;\n }\n if (typeof value === \"boolean\") {\n return 1;\n }\n if (typeof value === \"bigint\") {\n // Int64: 1 byte type marker + 8 bytes value\n return 9;\n }\n if (value instanceof CommitTsPlaceholder) {\n // Same as bigint\n return 9;\n }\n if (typeof value === \"number\") {\n // Float64: 1 byte type marker + 8 bytes value\n return 9;\n }\n if (typeof value === \"string\") {\n // String: 1 byte type marker + UTF-8 bytes + 1 byte null terminator\n // Use TextEncoder to get the actual UTF-8 byte length\n return 2 + getUtf8ByteLength(value);\n }\n if (value instanceof ArrayBuffer) {\n // Bytes: 1 byte type marker + byte array length + 1 byte terminator\n return 2 + value.byteLength;\n }\n if (Array.isArray(value)) {\n // Array: 1 byte type marker + sum of element sizes + 1 byte terminator\n let size = 2; // marker + terminator\n for (const element of value) {\n size += getConvexSize(element);\n }\n return size;\n }\n if (isSimpleObject(value)) {\n // Object: 1 byte type marker + sum(field_name + null + value) + 1 byte terminator\n let size = 2; // marker + terminator\n for (const [key, val] of Object.entries(value)) {\n if (val !== undefined) {\n // field name length + null terminator + value size\n size += getUtf8ByteLength(key) + 1 + getConvexSize(val);\n }\n }\n return size;\n }\n\n throw new Error(`Unsupported value type: ${typeof value}`);\n}\n\n/**\n * Threshold above which we use TextEncoder instead of manual counting.\n * For short strings, the JS loop is ~15x faster due to avoiding allocation.\n * For long strings (500+ chars), TextEncoder's native implementation wins.\n */\nconst UTF8_LENGTH_THRESHOLD = 500;\n\n/**\n * Get the UTF-8 byte length of a string.\n *\n * For short strings, counts bytes directly from UTF-16 code units to avoid allocation.\n * For long strings, uses native TextEncoder which is faster despite allocation.\n *\n * @internal\n */\nfunction getUtf8ByteLength(str: string): number {\n // For long strings, native TextEncoder is faster despite allocation\n if (str.length > UTF8_LENGTH_THRESHOLD) {\n return new TextEncoder().encode(str).length;\n }\n\n // For short strings, avoid allocation overhead with manual counting\n let bytes = 0;\n for (let i = 0; i < str.length; i++) {\n const code = str.charCodeAt(i);\n if (code < 0x80) {\n // ASCII: 1 byte\n bytes += 1;\n } else if (code < 0x800) {\n // 2-byte UTF-8\n bytes += 2;\n } else if (code >= 0xd800 && code <= 0xdbff) {\n // High surrogate - part of a surrogate pair encoding a code point >= U+10000\n // These are encoded as 4 bytes in UTF-8\n bytes += 4;\n i++; // Skip the low surrogate\n } else {\n // 3-byte UTF-8 (includes low surrogates if encountered alone, which is invalid but handled)\n bytes += 3;\n }\n }\n return bytes;\n}\n\n// Note: The exact _id size varies based on the table number:\n// - Tables 1-127: 31 char ID\n// - Tables 128-16383: 32 char ID\n// We use 32 chars as a typical value (tables 128-16383).\nexport const SYSTEM_FIELD_ID_ESTIMATE = 38;\n// _creationTime: field name (14) + Float64 (9)\nexport const SYSTEM_FIELD_CREATION_TIME_SIZE = 23;\n\n/**\n * Calculate the size of a document including system fields.\n *\n * If your value already has _id and _creationTime fields, this will count them\n * in the normal size calculation. Otherwise, it adds the constant overhead\n * for system fields.\n *\n * @param value - A Convex object (document body)\n * @param options - Options for size calculation\n * @returns The size in bytes\n *\n * @public\n */\nexport function getDocumentSize(\n value: Record<string, Value>,\n options?: {\n /**\n * @internal\n * Length of the _id field if it is missing. Defaults to standard length.\n */\n customIdLength?: number;\n },\n): number {\n const baseSize = getConvexSize(value);\n\n // Check if system fields are already present\n const hasId = \"_id\" in value && value[\"_id\"] !== undefined;\n const hasCreationTime =\n \"_creationTime\" in value && value[\"_creationTime\"] !== undefined;\n\n if (hasId && hasCreationTime) {\n return baseSize;\n }\n\n // Add size for missing system fields\n let additionalSize = 0;\n\n if (!hasId) {\n if (options?.customIdLength) {\n // 4 bytes for _id field name + 2 bytes for string overhead.\n additionalSize += options.customIdLength + 6;\n } else {\n additionalSize += SYSTEM_FIELD_ID_ESTIMATE;\n }\n }\n\n if (!hasCreationTime) {\n additionalSize += SYSTEM_FIELD_CREATION_TIME_SIZE;\n }\n\n // The base size includes 2 bytes for object markers, but we need to account\n // for adding new fields to an existing object structure\n return baseSize + additionalSize;\n}\n"],
|
|
5
|
+
"mappings": ";AAyBA,SAAS,2BAAuC;AAChD,SAAS,sBAAsB;AAaxB,gBAAS,cAAc,OAAkC;AAC9D,MAAI,UAAU,QAAW;AACvB,WAAO;AAAA,EACT;AACA,MAAI,UAAU,MAAM;AAClB,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,WAAW;AAC9B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAE7B,WAAO;AAAA,EACT;AACA,MAAI,iBAAiB,qBAAqB;AAExC,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAE7B,WAAO;AAAA,EACT;AACA,MAAI,OAAO,UAAU,UAAU;AAG7B,WAAO,IAAI,kBAAkB,KAAK;AAAA,EACpC;AACA,MAAI,iBAAiB,aAAa;AAEhC,WAAO,IAAI,MAAM;AAAA,EACnB;AACA,MAAI,MAAM,QAAQ,KAAK,GAAG;AAExB,QAAI,OAAO;AACX,eAAW,WAAW,OAAO;AAC3B,cAAQ,cAAc,OAAO;AAAA,IAC/B;AACA,WAAO;AAAA,EACT;AACA,MAAI,eAAe,KAAK,GAAG;AAEzB,QAAI,OAAO;AACX,eAAW,CAAC,KAAK,GAAG,KAAK,OAAO,QAAQ,KAAK,GAAG;AAC9C,UAAI,QAAQ,QAAW;AAErB,gBAAQ,kBAAkB,GAAG,IAAI,IAAI,cAAc,GAAG;AAAA,MACxD;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAEA,QAAM,IAAI,MAAM,2BAA2B,OAAO,KAAK,EAAE;AAC3D;AAOA,MAAM,wBAAwB;AAU9B,SAAS,kBAAkB,KAAqB;AAE9C,MAAI,IAAI,SAAS,uBAAuB;AACtC,WAAO,IAAI,YAAY,EAAE,OAAO,GAAG,EAAE;AAAA,EACvC;AAGA,MAAI,QAAQ;AACZ,WAAS,IAAI,GAAG,IAAI,IAAI,QAAQ,KAAK;AACnC,UAAM,OAAO,IAAI,WAAW,CAAC;AAC7B,QAAI,OAAO,KAAM;AAEf,eAAS;AAAA,IACX,WAAW,OAAO,MAAO;AAEvB,eAAS;AAAA,IACX,WAAW,QAAQ,SAAU,QAAQ,OAAQ;AAG3C,eAAS;AACT;AAAA,IACF,OAAO;AAEL,eAAS;AAAA,IACX;AAAA,EACF;AACA,SAAO;AACT;AAMO,aAAM,2BAA2B;AAEjC,aAAM,kCAAkC;AAexC,gBAAS,gBACd,OACA,SAOQ;AACR,QAAM,WAAW,cAAc,KAAK;AAGpC,QAAM,QAAQ,SAAS,SAAS,MAAM,KAAK,MAAM;AACjD,QAAM,kBACJ,mBAAmB,SAAS,MAAM,eAAe,MAAM;AAEzD,MAAI,SAAS,iBAAiB;AAC5B,WAAO;AAAA,EACT;AAGA,MAAI,iBAAiB;AAErB,MAAI,CAAC,OAAO;AACV,QAAI,SAAS,gBAAgB;AAE3B,wBAAkB,QAAQ,iBAAiB;AAAA,IAC7C,OAAO;AACL,wBAAkB;AAAA,IACpB;AAAA,EACF;AAEA,MAAI,CAAC,iBAAiB;AACpB,sBAAkB;AAAA,EACpB;AAIA,SAAO,WAAW;AACpB;",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -6,6 +6,7 @@ import {
|
|
|
6
6
|
VBytes,
|
|
7
7
|
VFloat64,
|
|
8
8
|
VId,
|
|
9
|
+
VCommitTs,
|
|
9
10
|
VInt64,
|
|
10
11
|
VLiteral,
|
|
11
12
|
VNull,
|
|
@@ -93,6 +94,17 @@ export const v = {
|
|
|
93
94
|
int64: () => {
|
|
94
95
|
return new VInt64({ isOptional: "required" });
|
|
95
96
|
},
|
|
97
|
+
/**
|
|
98
|
+
* Validates that the value is a commit timestamp: an int64 (`bigint`)
|
|
99
|
+
* assigned from the transaction's commit timestamp.
|
|
100
|
+
*
|
|
101
|
+
* An index on a field with this validator orders documents by commit order.
|
|
102
|
+
* Accepts any int64 value; write `db.vars.commitTs` to have the field
|
|
103
|
+
* resolve to the commit timestamp when the mutation commits.
|
|
104
|
+
*/
|
|
105
|
+
commitTs: () => {
|
|
106
|
+
return new VCommitTs({ isOptional: "required" });
|
|
107
|
+
},
|
|
96
108
|
/**
|
|
97
109
|
* Validates that the value is a `boolean`.
|
|
98
110
|
*/
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/values/validator.ts"],
|
|
4
|
-
"sourcesContent": ["import { Expand } from \"../type_utils.js\";\nimport { GenericId } from \"./index.js\";\nimport {\n OptionalProperty,\n VAny,\n VArray,\n VBoolean,\n VBytes,\n VFloat64,\n VId,\n VInt64,\n VLiteral,\n VNull,\n VObject,\n VOptional,\n VRecord,\n VString,\n VUnion,\n Validator,\n} from \"./validators.js\";\n\n/**\n * The type that all validators must extend.\n *\n * @public\n */\nexport type GenericValidator = Validator<any, any, any>;\n\nexport function isValidator(v: any): v is GenericValidator {\n return !!v.isConvexValidator;\n}\n\n/**\n * Coerce an object with validators as properties to a validator.\n * If a validator is passed, return it.\n *\n * @public\n */\nexport function asObjectValidator<\n V extends Validator<any, any, any> | PropertyValidators,\n>(\n obj: V,\n): V extends Validator<any, any, any>\n ? V\n : V extends PropertyValidators\n ? Validator<ObjectType<V>>\n : never {\n if (isValidator(obj)) {\n return obj as any;\n } else {\n return v.object(obj as PropertyValidators) as any;\n }\n}\n\n/**\n * Coerce an object with validators as properties to a validator.\n * If a validator is passed, return it.\n *\n * @public\n */\nexport type AsObjectValidator<\n V extends Validator<any, any, any> | PropertyValidators,\n> =\n V extends Validator<any, any, any>\n ? V\n : V extends PropertyValidators\n ? Validator<ObjectType<V>>\n : never;\n\n/**\n * The validator builder.\n *\n * This builder allows you to build validators for Convex values. Validators\n * are used in two places:\n *\n * 1. **Schema definitions** - to define the shape of documents in your tables.\n * 2. **Function arguments and return values** - to validate inputs and outputs\n * of your Convex queries, mutations, and actions.\n *\n * Always include `args` and `returns` validators on all Convex functions. If a\n * function doesn't return a value, use `returns: v.null()`.\n *\n * **Convex type reference:**\n *\n * | Convex Type | JS/TS Type | Validator |\n * |-------------|---------------|--------------------------------|\n * | Id | `string` | `v.id(\"tableName\")` |\n * | Null | `null` | `v.null()` |\n * | Float64 | `number` | `v.number()` |\n * | Int64 | `bigint` | `v.int64()` |\n * | Boolean | `boolean` | `v.boolean()` |\n * | String | `string` | `v.string()` |\n * | Bytes | `ArrayBuffer` | `v.bytes()` |\n * | Array | `Array` | `v.array(element)` |\n * | Object | `Object` | `v.object({ field: value })` |\n * | Record | `Record` | `v.record(keys, values)` |\n *\n * **Modifiers and meta-types:**\n * - `v.union(member1, member2)` - a value matching at least one validator\n * - `v.literal(\"value\")` - a specific literal string, number, bigint, or boolean\n * - `v.optional(validator)` - makes a property optional in an object (`T | undefined`)\n *\n * **Important notes:**\n * - JavaScript's `undefined` is **not** a valid Convex value. Functions that\n * return `undefined` or have no return will return `null` to the client.\n * Objects with `undefined` values will strip those keys during serialization.\n * For arrays, use an explicit `null` instead.\n * - `v.bigint()` is deprecated, use `v.int64()` instead.\n * - `v.map()` and `v.set()` are not supported. Use `v.array()` of tuples or\n * `v.record()` as alternatives.\n *\n * @example\n * ```typescript\n * import { v } from \"convex/values\";\n *\n * // Use in function definition:\n * export const createUser = mutation({\n * args: {\n * name: v.string(),\n * email: v.string(),\n * age: v.optional(v.number()),\n * },\n * returns: v.id(\"users\"),\n * handler: async (ctx, args) => {\n * return await ctx.db.insert(\"users\", args);\n * },\n * });\n * ```\n *\n * @see https://docs.convex.dev/database/types\n * @see https://docs.convex.dev/functions/validation\n * @public\n */\nexport const v = {\n /**\n * Validates that the value is a document ID for the given table.\n *\n * IDs are strings at runtime but are typed as `Id<\"tableName\">` in\n * TypeScript for type safety.\n *\n * @example\n * ```typescript\n * args: { userId: v.id(\"users\") }\n * ```\n *\n * @param tableName The name of the table.\n */\n id: <TableName extends string>(tableName: TableName) => {\n return new VId<GenericId<TableName>>({\n isOptional: \"required\",\n tableName,\n });\n },\n\n /**\n * Validates that the value is `null`.\n *\n * Use `returns: v.null()` for functions that don't return a meaningful value.\n * JavaScript `undefined` is not a valid Convex value, it is automatically\n * converted to `null`.\n */\n null: () => {\n return new VNull({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a JavaScript `number` (Convex Float64).\n *\n * Supports all IEEE-754 double-precision floating point numbers including\n * NaN and Infinity.\n *\n * Alias for `v.float64()`.\n */\n number: () => {\n return new VFloat64({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a JavaScript `number` (Convex Float64).\n *\n * Supports all IEEE-754 double-precision floating point numbers.\n */\n float64: () => {\n return new VFloat64({ isOptional: \"required\" });\n },\n\n /**\n * @deprecated Use `v.int64()` instead.\n */\n bigint: () => {\n return new VInt64({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a JavaScript `bigint` (Convex Int64).\n *\n * Supports BigInts between -2^63 and 2^63-1.\n *\n * @example\n * ```typescript\n * args: { timestamp: v.int64() }\n * // Usage: createDoc({ timestamp: 1234567890n })\n * ```\n */\n int64: () => {\n return new VInt64({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a `boolean`.\n */\n boolean: () => {\n return new VBoolean({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a `string`.\n *\n * Strings are stored as UTF-8 and their storage size is calculated as their\n * UTF-8 encoded size.\n */\n string: () => {\n return new VString({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is an `ArrayBuffer` (Convex Bytes).\n *\n * Use for binary data.\n */\n bytes: () => {\n return new VBytes({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is exactly equal to the given literal.\n *\n * Useful for discriminated unions and enum-like patterns.\n *\n * @example\n * ```typescript\n * // Discriminated union pattern:\n * v.union(\n * v.object({ kind: v.literal(\"error\"), message: v.string() }),\n * v.object({ kind: v.literal(\"success\"), value: v.number() }),\n * )\n * ```\n *\n * @param literal The literal value to compare against.\n */\n literal: <T extends string | number | bigint | boolean>(literal: T) => {\n return new VLiteral<T>({ isOptional: \"required\", value: literal });\n },\n\n /**\n * Validates that the value is an `Array` where every element matches the\n * given validator.\n *\n * Arrays can have at most 8192 elements.\n *\n * @example\n * ```typescript\n * args: { tags: v.array(v.string()) }\n * args: { coordinates: v.array(v.number()) }\n * args: { items: v.array(v.object({ name: v.string(), qty: v.number() })) }\n * ```\n *\n * @param element The validator for the elements of the array.\n */\n array: <T extends Validator<any, \"required\", any>>(element: T) => {\n return new VArray<T[\"type\"][], T>({ isOptional: \"required\", element });\n },\n\n /**\n * Validates that the value is an `Object` with the specified properties.\n *\n * Objects can have at most 1024 entries. Field names must be non-empty and\n * must not start with `\"$\"` or `\"_\"` (`_` is reserved for system fields\n * like `_id` and `_creationTime`; `$` is reserved for Convex internal use).\n *\n * @example\n * ```typescript\n * args: {\n * user: v.object({\n * name: v.string(),\n * email: v.string(),\n * age: v.optional(v.number()),\n * })\n * }\n * ```\n *\n * @param fields An object mapping property names to their validators.\n */\n object: <T extends PropertyValidators>(fields: T) => {\n return new VObject<ObjectType<T>, T>({ isOptional: \"required\", fields });\n },\n\n /**\n * Validates that the value is a `Record` (object with dynamic keys).\n *\n * Records are objects at runtime but allow dynamic keys, unlike `v.object()`\n * which requires known property names. Keys must be ASCII characters only,\n * non-empty, and not start with `\"$\"` or `\"_\"`.\n *\n * @example\n * ```typescript\n * // Map of user IDs to scores:\n * args: { scores: v.record(v.id(\"users\"), v.number()) }\n *\n * // Map of string keys to string values:\n * args: { metadata: v.record(v.string(), v.string()) }\n * ```\n *\n * @param keys The validator for the keys of the record.\n * @param values The validator for the values of the record.\n */\n record: <\n Key extends Validator<string, \"required\", any>,\n Value extends Validator<any, \"required\", any>,\n >(\n keys: Key,\n values: Value,\n ) => {\n return new VRecord<Record<Infer<Key>, Value[\"type\"]>, Key, Value>({\n isOptional: \"required\",\n key: keys,\n value: values,\n });\n },\n\n /**\n * Validates that the value matches at least one of the given validators.\n *\n * @example\n * ```typescript\n * // Allow string or number:\n * args: { value: v.union(v.string(), v.number()) }\n *\n * // Discriminated union (recommended pattern):\n * v.union(\n * v.object({ kind: v.literal(\"text\"), body: v.string() }),\n * v.object({ kind: v.literal(\"image\"), url: v.string() }),\n * )\n *\n * // Nullable value:\n * returns: v.union(v.object({ ... }), v.null())\n * ```\n *\n * @param members The validators to match against.\n */\n union: <T extends Validator<any, \"required\", any>[]>(...members: T) => {\n return new VUnion<T[number][\"type\"], T>({\n isOptional: \"required\",\n members,\n });\n },\n\n /**\n * A validator that accepts any Convex value without validation.\n *\n * Prefer using specific validators when possible for better type safety\n * and runtime validation.\n */\n any: () => {\n return new VAny({ isOptional: \"required\" });\n },\n\n /**\n * Makes a property optional in an object validator.\n *\n * An optional property can be omitted entirely when creating a document or\n * calling a function. This is different from `v.nullable()` which requires\n * the property to be present but allows `null`.\n *\n * @example\n * ```typescript\n * v.object({\n * name: v.string(), // required\n * nickname: v.optional(v.string()), // can be omitted\n * })\n *\n * // Valid: { name: \"Alice\" }\n * // Valid: { name: \"Alice\", nickname: \"Ali\" }\n * // Invalid: { name: \"Alice\", nickname: null } - use v.nullable() for this\n * ```\n *\n * @param value The property value validator to make optional.\n */\n optional: <T extends GenericValidator>(value: T) => {\n return value.asOptional() as VOptional<T>;\n },\n\n /**\n * Allows a value to be either the given type or `null`.\n *\n * This is shorthand for `v.union(value, v.null())`. Unlike `v.optional()`,\n * the property must still be present, but may be `null`.\n *\n * @example\n * ```typescript\n * v.object({\n * name: v.string(),\n * deletedAt: v.nullable(v.number()), // must be present, can be null\n * })\n *\n * // Valid: { name: \"Alice\", deletedAt: null }\n * // Valid: { name: \"Alice\", deletedAt: 1234567890 }\n * // Invalid: { name: \"Alice\" } - deletedAt is required\n * ```\n */\n nullable: <T extends Validator<any, \"required\", any>>(value: T) => {\n return v.union(value, v.null());\n },\n};\n\n/**\n * Validators for each property of an object.\n *\n * This is represented as an object mapping the property name to its\n * {@link Validator}.\n *\n * @public\n */\nexport type PropertyValidators = Record<\n string,\n Validator<any, OptionalProperty, any>\n>;\n\n/**\n * Compute the type of an object from {@link PropertyValidators}.\n *\n * @public\n */\nexport type ObjectType<Fields extends PropertyValidators> = Expand<\n // Map each key to the corresponding property validator's type making\n // the optional ones optional.\n {\n // This `Exclude<..., undefined>` does nothing unless\n // the tsconfig.json option `\"exactOptionalPropertyTypes\": true,`\n // is used. When it is it results in a more accurate type.\n // When it is not the `Exclude` removes `undefined` but it is\n // added again by the optional property.\n [Property in OptionalKeys<Fields>]?: Exclude<\n Infer<Fields[Property]>,\n undefined\n >;\n } & {\n [Property in RequiredKeys<Fields>]: Infer<Fields[Property]>;\n }\n>;\n\ntype OptionalKeys<PropertyValidators extends Record<string, GenericValidator>> =\n {\n [Property in keyof PropertyValidators]: PropertyValidators[Property][\"isOptional\"] extends \"optional\"\n ? Property\n : never;\n }[keyof PropertyValidators];\n\ntype RequiredKeys<PropertyValidators extends Record<string, GenericValidator>> =\n Exclude<keyof PropertyValidators, OptionalKeys<PropertyValidators>>;\n\n/**\n * Extract a TypeScript type from a validator.\n *\n * Example usage:\n * ```ts\n * const objectSchema = v.object({\n * property: v.string(),\n * });\n * type MyObject = Infer<typeof objectSchema>; // { property: string }\n * ```\n * @typeParam V - The type of a {@link Validator} constructed with {@link v}.\n *\n * @public\n */\nexport type Infer<T extends Validator<any, OptionalProperty, any>> = T[\"type\"];\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { Expand } from \"../type_utils.js\";\nimport { GenericId } from \"./index.js\";\nimport {\n OptionalProperty,\n VAny,\n VArray,\n VBoolean,\n VBytes,\n VFloat64,\n VId,\n VCommitTs,\n VInt64,\n VLiteral,\n VNull,\n VObject,\n VOptional,\n VRecord,\n VString,\n VUnion,\n Validator,\n} from \"./validators.js\";\n\n/**\n * The type that all validators must extend.\n *\n * @public\n */\nexport type GenericValidator = Validator<any, any, any>;\n\nexport function isValidator(v: any): v is GenericValidator {\n return !!v.isConvexValidator;\n}\n\n/**\n * Coerce an object with validators as properties to a validator.\n * If a validator is passed, return it.\n *\n * @public\n */\nexport function asObjectValidator<\n V extends Validator<any, any, any> | PropertyValidators,\n>(\n obj: V,\n): V extends Validator<any, any, any>\n ? V\n : V extends PropertyValidators\n ? Validator<ObjectType<V>>\n : never {\n if (isValidator(obj)) {\n return obj as any;\n } else {\n return v.object(obj as PropertyValidators) as any;\n }\n}\n\n/**\n * Coerce an object with validators as properties to a validator.\n * If a validator is passed, return it.\n *\n * @public\n */\nexport type AsObjectValidator<\n V extends Validator<any, any, any> | PropertyValidators,\n> =\n V extends Validator<any, any, any>\n ? V\n : V extends PropertyValidators\n ? Validator<ObjectType<V>>\n : never;\n\n/**\n * The validator builder.\n *\n * This builder allows you to build validators for Convex values. Validators\n * are used in two places:\n *\n * 1. **Schema definitions** - to define the shape of documents in your tables.\n * 2. **Function arguments and return values** - to validate inputs and outputs\n * of your Convex queries, mutations, and actions.\n *\n * Always include `args` and `returns` validators on all Convex functions. If a\n * function doesn't return a value, use `returns: v.null()`.\n *\n * **Convex type reference:**\n *\n * | Convex Type | JS/TS Type | Validator |\n * |-------------|---------------|--------------------------------|\n * | Id | `string` | `v.id(\"tableName\")` |\n * | Null | `null` | `v.null()` |\n * | Float64 | `number` | `v.number()` |\n * | Int64 | `bigint` | `v.int64()` |\n * | Boolean | `boolean` | `v.boolean()` |\n * | String | `string` | `v.string()` |\n * | Bytes | `ArrayBuffer` | `v.bytes()` |\n * | Array | `Array` | `v.array(element)` |\n * | Object | `Object` | `v.object({ field: value })` |\n * | Record | `Record` | `v.record(keys, values)` |\n *\n * **Modifiers and meta-types:**\n * - `v.union(member1, member2)` - a value matching at least one validator\n * - `v.literal(\"value\")` - a specific literal string, number, bigint, or boolean\n * - `v.optional(validator)` - makes a property optional in an object (`T | undefined`)\n *\n * **Important notes:**\n * - JavaScript's `undefined` is **not** a valid Convex value. Functions that\n * return `undefined` or have no return will return `null` to the client.\n * Objects with `undefined` values will strip those keys during serialization.\n * For arrays, use an explicit `null` instead.\n * - `v.bigint()` is deprecated, use `v.int64()` instead.\n * - `v.map()` and `v.set()` are not supported. Use `v.array()` of tuples or\n * `v.record()` as alternatives.\n *\n * @example\n * ```typescript\n * import { v } from \"convex/values\";\n *\n * // Use in function definition:\n * export const createUser = mutation({\n * args: {\n * name: v.string(),\n * email: v.string(),\n * age: v.optional(v.number()),\n * },\n * returns: v.id(\"users\"),\n * handler: async (ctx, args) => {\n * return await ctx.db.insert(\"users\", args);\n * },\n * });\n * ```\n *\n * @see https://docs.convex.dev/database/types\n * @see https://docs.convex.dev/functions/validation\n * @public\n */\nexport const v = {\n /**\n * Validates that the value is a document ID for the given table.\n *\n * IDs are strings at runtime but are typed as `Id<\"tableName\">` in\n * TypeScript for type safety.\n *\n * @example\n * ```typescript\n * args: { userId: v.id(\"users\") }\n * ```\n *\n * @param tableName The name of the table.\n */\n id: <TableName extends string>(tableName: TableName) => {\n return new VId<GenericId<TableName>>({\n isOptional: \"required\",\n tableName,\n });\n },\n\n /**\n * Validates that the value is `null`.\n *\n * Use `returns: v.null()` for functions that don't return a meaningful value.\n * JavaScript `undefined` is not a valid Convex value, it is automatically\n * converted to `null`.\n */\n null: () => {\n return new VNull({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a JavaScript `number` (Convex Float64).\n *\n * Supports all IEEE-754 double-precision floating point numbers including\n * NaN and Infinity.\n *\n * Alias for `v.float64()`.\n */\n number: () => {\n return new VFloat64({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a JavaScript `number` (Convex Float64).\n *\n * Supports all IEEE-754 double-precision floating point numbers.\n */\n float64: () => {\n return new VFloat64({ isOptional: \"required\" });\n },\n\n /**\n * @deprecated Use `v.int64()` instead.\n */\n bigint: () => {\n return new VInt64({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a JavaScript `bigint` (Convex Int64).\n *\n * Supports BigInts between -2^63 and 2^63-1.\n *\n * @example\n * ```typescript\n * args: { timestamp: v.int64() }\n * // Usage: createDoc({ timestamp: 1234567890n })\n * ```\n */\n int64: () => {\n return new VInt64({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a commit timestamp: an int64 (`bigint`)\n * assigned from the transaction's commit timestamp.\n *\n * An index on a field with this validator orders documents by commit order.\n * Accepts any int64 value; write `db.vars.commitTs` to have the field\n * resolve to the commit timestamp when the mutation commits.\n */\n commitTs: () => {\n return new VCommitTs({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a `boolean`.\n */\n boolean: () => {\n return new VBoolean({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is a `string`.\n *\n * Strings are stored as UTF-8 and their storage size is calculated as their\n * UTF-8 encoded size.\n */\n string: () => {\n return new VString({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is an `ArrayBuffer` (Convex Bytes).\n *\n * Use for binary data.\n */\n bytes: () => {\n return new VBytes({ isOptional: \"required\" });\n },\n\n /**\n * Validates that the value is exactly equal to the given literal.\n *\n * Useful for discriminated unions and enum-like patterns.\n *\n * @example\n * ```typescript\n * // Discriminated union pattern:\n * v.union(\n * v.object({ kind: v.literal(\"error\"), message: v.string() }),\n * v.object({ kind: v.literal(\"success\"), value: v.number() }),\n * )\n * ```\n *\n * @param literal The literal value to compare against.\n */\n literal: <T extends string | number | bigint | boolean>(literal: T) => {\n return new VLiteral<T>({ isOptional: \"required\", value: literal });\n },\n\n /**\n * Validates that the value is an `Array` where every element matches the\n * given validator.\n *\n * Arrays can have at most 8192 elements.\n *\n * @example\n * ```typescript\n * args: { tags: v.array(v.string()) }\n * args: { coordinates: v.array(v.number()) }\n * args: { items: v.array(v.object({ name: v.string(), qty: v.number() })) }\n * ```\n *\n * @param element The validator for the elements of the array.\n */\n array: <T extends Validator<any, \"required\", any>>(element: T) => {\n return new VArray<T[\"type\"][], T>({ isOptional: \"required\", element });\n },\n\n /**\n * Validates that the value is an `Object` with the specified properties.\n *\n * Objects can have at most 1024 entries. Field names must be non-empty and\n * must not start with `\"$\"` or `\"_\"` (`_` is reserved for system fields\n * like `_id` and `_creationTime`; `$` is reserved for Convex internal use).\n *\n * @example\n * ```typescript\n * args: {\n * user: v.object({\n * name: v.string(),\n * email: v.string(),\n * age: v.optional(v.number()),\n * })\n * }\n * ```\n *\n * @param fields An object mapping property names to their validators.\n */\n object: <T extends PropertyValidators>(fields: T) => {\n return new VObject<ObjectType<T>, T>({ isOptional: \"required\", fields });\n },\n\n /**\n * Validates that the value is a `Record` (object with dynamic keys).\n *\n * Records are objects at runtime but allow dynamic keys, unlike `v.object()`\n * which requires known property names. Keys must be ASCII characters only,\n * non-empty, and not start with `\"$\"` or `\"_\"`.\n *\n * @example\n * ```typescript\n * // Map of user IDs to scores:\n * args: { scores: v.record(v.id(\"users\"), v.number()) }\n *\n * // Map of string keys to string values:\n * args: { metadata: v.record(v.string(), v.string()) }\n * ```\n *\n * @param keys The validator for the keys of the record.\n * @param values The validator for the values of the record.\n */\n record: <\n Key extends Validator<string, \"required\", any>,\n Value extends Validator<any, \"required\", any>,\n >(\n keys: Key,\n values: Value,\n ) => {\n return new VRecord<Record<Infer<Key>, Value[\"type\"]>, Key, Value>({\n isOptional: \"required\",\n key: keys,\n value: values,\n });\n },\n\n /**\n * Validates that the value matches at least one of the given validators.\n *\n * @example\n * ```typescript\n * // Allow string or number:\n * args: { value: v.union(v.string(), v.number()) }\n *\n * // Discriminated union (recommended pattern):\n * v.union(\n * v.object({ kind: v.literal(\"text\"), body: v.string() }),\n * v.object({ kind: v.literal(\"image\"), url: v.string() }),\n * )\n *\n * // Nullable value:\n * returns: v.union(v.object({ ... }), v.null())\n * ```\n *\n * @param members The validators to match against.\n */\n union: <T extends Validator<any, \"required\", any>[]>(...members: T) => {\n return new VUnion<T[number][\"type\"], T>({\n isOptional: \"required\",\n members,\n });\n },\n\n /**\n * A validator that accepts any Convex value without validation.\n *\n * Prefer using specific validators when possible for better type safety\n * and runtime validation.\n */\n any: () => {\n return new VAny({ isOptional: \"required\" });\n },\n\n /**\n * Makes a property optional in an object validator.\n *\n * An optional property can be omitted entirely when creating a document or\n * calling a function. This is different from `v.nullable()` which requires\n * the property to be present but allows `null`.\n *\n * @example\n * ```typescript\n * v.object({\n * name: v.string(), // required\n * nickname: v.optional(v.string()), // can be omitted\n * })\n *\n * // Valid: { name: \"Alice\" }\n * // Valid: { name: \"Alice\", nickname: \"Ali\" }\n * // Invalid: { name: \"Alice\", nickname: null } - use v.nullable() for this\n * ```\n *\n * @param value The property value validator to make optional.\n */\n optional: <T extends GenericValidator>(value: T) => {\n return value.asOptional() as VOptional<T>;\n },\n\n /**\n * Allows a value to be either the given type or `null`.\n *\n * This is shorthand for `v.union(value, v.null())`. Unlike `v.optional()`,\n * the property must still be present, but may be `null`.\n *\n * @example\n * ```typescript\n * v.object({\n * name: v.string(),\n * deletedAt: v.nullable(v.number()), // must be present, can be null\n * })\n *\n * // Valid: { name: \"Alice\", deletedAt: null }\n * // Valid: { name: \"Alice\", deletedAt: 1234567890 }\n * // Invalid: { name: \"Alice\" } - deletedAt is required\n * ```\n */\n nullable: <T extends Validator<any, \"required\", any>>(value: T) => {\n return v.union(value, v.null());\n },\n};\n\n/**\n * Validators for each property of an object.\n *\n * This is represented as an object mapping the property name to its\n * {@link Validator}.\n *\n * @public\n */\nexport type PropertyValidators = Record<\n string,\n Validator<any, OptionalProperty, any>\n>;\n\n/**\n * Compute the type of an object from {@link PropertyValidators}.\n *\n * @public\n */\nexport type ObjectType<Fields extends PropertyValidators> = Expand<\n // Map each key to the corresponding property validator's type making\n // the optional ones optional.\n {\n // This `Exclude<..., undefined>` does nothing unless\n // the tsconfig.json option `\"exactOptionalPropertyTypes\": true,`\n // is used. When it is it results in a more accurate type.\n // When it is not the `Exclude` removes `undefined` but it is\n // added again by the optional property.\n [Property in OptionalKeys<Fields>]?: Exclude<\n Infer<Fields[Property]>,\n undefined\n >;\n } & {\n [Property in RequiredKeys<Fields>]: Infer<Fields[Property]>;\n }\n>;\n\ntype OptionalKeys<PropertyValidators extends Record<string, GenericValidator>> =\n {\n [Property in keyof PropertyValidators]: PropertyValidators[Property][\"isOptional\"] extends \"optional\"\n ? Property\n : never;\n }[keyof PropertyValidators];\n\ntype RequiredKeys<PropertyValidators extends Record<string, GenericValidator>> =\n Exclude<keyof PropertyValidators, OptionalKeys<PropertyValidators>>;\n\n/**\n * Extract a TypeScript type from a validator.\n *\n * Example usage:\n * ```ts\n * const objectSchema = v.object({\n * property: v.string(),\n * });\n * type MyObject = Infer<typeof objectSchema>; // { property: string }\n * ```\n * @typeParam V - The type of a {@link Validator} constructed with {@link v}.\n *\n * @public\n */\nexport type Infer<T extends Validator<any, OptionalProperty, any>> = T[\"type\"];\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["v"]
|
|
7
7
|
}
|
|
@@ -104,6 +104,25 @@ export class VInt64 extends BaseValidator {
|
|
|
104
104
|
return new VInt64({ isOptional: "optional" });
|
|
105
105
|
}
|
|
106
106
|
}
|
|
107
|
+
export class VCommitTs extends BaseValidator {
|
|
108
|
+
constructor() {
|
|
109
|
+
super(...arguments);
|
|
110
|
+
/**
|
|
111
|
+
* The kind of validator, `"commitTs"`.
|
|
112
|
+
*/
|
|
113
|
+
__publicField(this, "kind", "commitTs");
|
|
114
|
+
}
|
|
115
|
+
/** @internal */
|
|
116
|
+
get json() {
|
|
117
|
+
return { type: this.kind };
|
|
118
|
+
}
|
|
119
|
+
/** @internal */
|
|
120
|
+
asOptional() {
|
|
121
|
+
return new VCommitTs({
|
|
122
|
+
isOptional: "optional"
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
107
126
|
export class VBoolean extends BaseValidator {
|
|
108
127
|
constructor() {
|
|
109
128
|
super(...arguments);
|