convex 1.42.3 → 1.43.0-alpha.1
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/bin/main-dev +6 -1
- package/dist/browser.bundle.js +49 -10
- package/dist/browser.bundle.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/paginated_query_client.js +20 -9
- package/dist/cjs/browser/sync/paginated_query_client.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/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/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/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/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 +14 -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/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 +2534 -2009
- package/dist/cli.bundle.cjs.map +4 -4
- 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/paginated_query_client.js +20 -9
- package/dist/esm/browser/sync/paginated_query_client.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/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/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/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 +14 -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/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 +9 -10
- package/schemas/convex.schema.json +2 -1
- package/src/browser/sync/paginated_query_client.test.ts +209 -1
- package/src/browser/sync/paginated_query_client.ts +26 -9
- 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/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 +15 -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/schema.test.ts +6 -1
- package/src/values/compare.ts +5 -2
- package/src/values/index.ts +2 -1
- package/src/values/size.test.ts +5 -0
- package/src/values/size.ts +5 -1
- package/src/values/validator.test.ts +16 -1
- package/src/values/validator.ts +13 -0
- package/src/values/validators.ts +29 -1
- package/src/values/value.test.ts +35 -0
- package/src/values/value.ts +56 -1
package/src/server/cron.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { getFunctionName, OptionalRestArgs } from "../server/api.js";
|
|
2
2
|
import { parseArgs } from "../common/index.js";
|
|
3
3
|
import { convexToJson, JSONValue, Value } from "../values/index.js";
|
|
4
|
+
import { getFunctionAddress } from "./components/paths.js";
|
|
4
5
|
import { SchedulableFunctionReference } from "./scheduler.js";
|
|
5
6
|
|
|
6
7
|
type CronSchedule = {
|
|
@@ -15,13 +16,13 @@ export type IntervalSchedule =
|
|
|
15
16
|
/** @public */
|
|
16
17
|
export type HourlySchedule = {
|
|
17
18
|
type: "hourly";
|
|
18
|
-
minuteUTC
|
|
19
|
+
minuteUTC?: number;
|
|
19
20
|
};
|
|
20
21
|
/** @public */
|
|
21
22
|
export type DailySchedule = {
|
|
22
23
|
type: "daily";
|
|
23
24
|
hourUTC: number;
|
|
24
|
-
minuteUTC
|
|
25
|
+
minuteUTC?: number;
|
|
25
26
|
};
|
|
26
27
|
const DAYS_OF_WEEK = [
|
|
27
28
|
"sunday",
|
|
@@ -38,14 +39,14 @@ export type WeeklySchedule = {
|
|
|
38
39
|
type: "weekly";
|
|
39
40
|
dayOfWeek: DayOfWeek;
|
|
40
41
|
hourUTC: number;
|
|
41
|
-
minuteUTC
|
|
42
|
+
minuteUTC?: number;
|
|
42
43
|
};
|
|
43
44
|
/** @public */
|
|
44
45
|
export type MonthlySchedule = {
|
|
45
46
|
type: "monthly";
|
|
46
47
|
day: number;
|
|
47
48
|
hourUTC: number;
|
|
48
|
-
minuteUTC
|
|
49
|
+
minuteUTC?: number;
|
|
49
50
|
};
|
|
50
51
|
|
|
51
52
|
// Duplicating types so docstrings are visible in signatures:
|
|
@@ -85,9 +86,11 @@ export type Interval =
|
|
|
85
86
|
/** @public */
|
|
86
87
|
export type Hourly = {
|
|
87
88
|
/**
|
|
88
|
-
* Minutes past the hour, 0-59.
|
|
89
|
+
* Minutes past the hour, 0-59. If omitted, Convex picks a minute for you
|
|
90
|
+
* and spreads runs across the hour so your job isn't tied to the busy top
|
|
91
|
+
* of the hour.
|
|
89
92
|
*/
|
|
90
|
-
minuteUTC
|
|
93
|
+
minuteUTC?: number;
|
|
91
94
|
};
|
|
92
95
|
|
|
93
96
|
/** @public */
|
|
@@ -97,9 +100,10 @@ export type Daily = {
|
|
|
97
100
|
*/
|
|
98
101
|
hourUTC: number;
|
|
99
102
|
/**
|
|
100
|
-
* 0-59, minute of hour. Remember, this is UTC.
|
|
103
|
+
* 0-59, minute of hour. Remember, this is UTC. If omitted, Convex picks a
|
|
104
|
+
* minute for you and spreads runs across the hour.
|
|
101
105
|
*/
|
|
102
|
-
minuteUTC
|
|
106
|
+
minuteUTC?: number;
|
|
103
107
|
};
|
|
104
108
|
|
|
105
109
|
/** @public */
|
|
@@ -114,8 +118,10 @@ export type Monthly = {
|
|
|
114
118
|
hourUTC: number;
|
|
115
119
|
/**
|
|
116
120
|
* 0-59, minute of hour. Remember to convert from your own time zone to UTC.
|
|
121
|
+
* If omitted, Convex picks a minute for you and spreads runs across the
|
|
122
|
+
* hour.
|
|
117
123
|
*/
|
|
118
|
-
minuteUTC
|
|
124
|
+
minuteUTC?: number;
|
|
119
125
|
};
|
|
120
126
|
/** @public */
|
|
121
127
|
export type Weekly = {
|
|
@@ -129,8 +135,10 @@ export type Weekly = {
|
|
|
129
135
|
hourUTC: number;
|
|
130
136
|
/**
|
|
131
137
|
* 0-59, minute of hour. Remember to convert from your own time zone to UTC.
|
|
138
|
+
* If omitted, Convex picks a minute for you and spreads runs across the
|
|
139
|
+
* hour.
|
|
132
140
|
*/
|
|
133
|
-
minuteUTC
|
|
141
|
+
minuteUTC?: number;
|
|
134
142
|
};
|
|
135
143
|
|
|
136
144
|
/** @public */
|
|
@@ -220,6 +228,26 @@ function validatedMinuteOfHour(n: number) {
|
|
|
220
228
|
return n;
|
|
221
229
|
}
|
|
222
230
|
|
|
231
|
+
// `minuteUTC` is optional: when omitted the backend picks a minute per job and
|
|
232
|
+
// spreads runs across the hour. Only validate when a minute was provided.
|
|
233
|
+
function validatedOptionalMinuteOfHour(n: number | undefined) {
|
|
234
|
+
return n === undefined ? undefined : validatedMinuteOfHour(n);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
// `crons.hourly()` lets the schedule object be omitted entirely. Tell the two
|
|
238
|
+
// call shapes apart by whether the second argument resolves to a function
|
|
239
|
+
// reference (the way the scheduler syscalls do) rather than a schedule object.
|
|
240
|
+
function isSchedulableFunctionReference(
|
|
241
|
+
arg: Hourly | SchedulableFunctionReference,
|
|
242
|
+
): arg is SchedulableFunctionReference {
|
|
243
|
+
try {
|
|
244
|
+
getFunctionAddress(arg);
|
|
245
|
+
return true;
|
|
246
|
+
} catch {
|
|
247
|
+
return false;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
|
|
223
251
|
function validatedCronString(s: string) {
|
|
224
252
|
return s;
|
|
225
253
|
}
|
|
@@ -323,22 +351,49 @@ export class Crons {
|
|
|
323
351
|
* ```
|
|
324
352
|
*
|
|
325
353
|
* @param cronIdentifier - A unique name for this scheduled job.
|
|
326
|
-
* @param schedule - What
|
|
354
|
+
* @param schedule - What minute (UTC) of each hour to run this function. May
|
|
355
|
+
* be omitted to let Convex pick a minute and spread runs across the hour.
|
|
327
356
|
* @param functionReference - A {@link FunctionReference} for the function
|
|
328
357
|
* to schedule.
|
|
329
358
|
* @param args - The arguments to the function.
|
|
330
359
|
*/
|
|
360
|
+
hourly<FuncRef extends SchedulableFunctionReference>(
|
|
361
|
+
cronIdentifier: string,
|
|
362
|
+
functionReference: FuncRef,
|
|
363
|
+
...args: OptionalRestArgs<FuncRef>
|
|
364
|
+
): void;
|
|
331
365
|
hourly<FuncRef extends SchedulableFunctionReference>(
|
|
332
366
|
cronIdentifier: string,
|
|
333
367
|
schedule: Hourly,
|
|
334
368
|
functionReference: FuncRef,
|
|
335
369
|
...args: OptionalRestArgs<FuncRef>
|
|
336
|
-
)
|
|
337
|
-
|
|
370
|
+
): void;
|
|
371
|
+
hourly<FuncRef extends SchedulableFunctionReference>(
|
|
372
|
+
cronIdentifier: string,
|
|
373
|
+
scheduleOrFunctionReference: Hourly | FuncRef,
|
|
374
|
+
functionReferenceOrArg?: FuncRef | Record<string, Value>,
|
|
375
|
+
...args: any[]
|
|
376
|
+
): void {
|
|
377
|
+
// The schedule object may be omitted, so the second argument is either the
|
|
378
|
+
// function reference (no schedule) or the schedule.
|
|
379
|
+
if (isSchedulableFunctionReference(scheduleOrFunctionReference)) {
|
|
380
|
+
this.schedule(
|
|
381
|
+
cronIdentifier,
|
|
382
|
+
{ type: "hourly" },
|
|
383
|
+
scheduleOrFunctionReference,
|
|
384
|
+
functionReferenceOrArg as Record<string, Value> | undefined,
|
|
385
|
+
);
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
const minuteUTC = validatedOptionalMinuteOfHour(
|
|
389
|
+
scheduleOrFunctionReference.minuteUTC,
|
|
390
|
+
);
|
|
338
391
|
this.schedule(
|
|
339
392
|
cronIdentifier,
|
|
340
|
-
|
|
341
|
-
|
|
393
|
+
minuteUTC === undefined
|
|
394
|
+
? { type: "hourly" }
|
|
395
|
+
: { minuteUTC, type: "hourly" },
|
|
396
|
+
functionReferenceOrArg as FuncRef,
|
|
342
397
|
...args,
|
|
343
398
|
);
|
|
344
399
|
}
|
|
@@ -370,10 +425,12 @@ export class Crons {
|
|
|
370
425
|
...args: OptionalRestArgs<FuncRef>
|
|
371
426
|
) {
|
|
372
427
|
const hourUTC = validatedHourOfDay(schedule.hourUTC);
|
|
373
|
-
const minuteUTC =
|
|
428
|
+
const minuteUTC = validatedOptionalMinuteOfHour(schedule.minuteUTC);
|
|
374
429
|
this.schedule(
|
|
375
430
|
cronIdentifier,
|
|
376
|
-
|
|
431
|
+
minuteUTC === undefined
|
|
432
|
+
? { hourUTC, type: "daily" }
|
|
433
|
+
: { hourUTC, minuteUTC, type: "daily" },
|
|
377
434
|
functionReference,
|
|
378
435
|
...args,
|
|
379
436
|
);
|
|
@@ -407,10 +464,12 @@ export class Crons {
|
|
|
407
464
|
) {
|
|
408
465
|
const dayOfWeek = validatedDayOfWeek(schedule.dayOfWeek);
|
|
409
466
|
const hourUTC = validatedHourOfDay(schedule.hourUTC);
|
|
410
|
-
const minuteUTC =
|
|
467
|
+
const minuteUTC = validatedOptionalMinuteOfHour(schedule.minuteUTC);
|
|
411
468
|
this.schedule(
|
|
412
469
|
cronIdentifier,
|
|
413
|
-
|
|
470
|
+
minuteUTC === undefined
|
|
471
|
+
? { dayOfWeek, hourUTC, type: "weekly" }
|
|
472
|
+
: { dayOfWeek, hourUTC, minuteUTC, type: "weekly" },
|
|
414
473
|
functionReference,
|
|
415
474
|
...args,
|
|
416
475
|
);
|
|
@@ -448,10 +507,12 @@ export class Crons {
|
|
|
448
507
|
) {
|
|
449
508
|
const day = validatedDayOfMonth(schedule.day);
|
|
450
509
|
const hourUTC = validatedHourOfDay(schedule.hourUTC);
|
|
451
|
-
const minuteUTC =
|
|
510
|
+
const minuteUTC = validatedOptionalMinuteOfHour(schedule.minuteUTC);
|
|
452
511
|
this.schedule(
|
|
453
512
|
cronIdentifier,
|
|
454
|
-
|
|
513
|
+
minuteUTC === undefined
|
|
514
|
+
? { day, hourUTC, type: "monthly" }
|
|
515
|
+
: { day, hourUTC, minuteUTC, type: "monthly" },
|
|
455
516
|
functionReference,
|
|
456
517
|
...args,
|
|
457
518
|
);
|
package/src/server/database.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { GenericId } from "../values/index.js";
|
|
2
|
+
import { CommitTsPlaceholder } from "../values/value.js";
|
|
2
3
|
import {
|
|
3
4
|
DocumentByName,
|
|
4
5
|
GenericDataModel,
|
|
@@ -370,6 +371,20 @@ export interface GenericDatabaseWriter<
|
|
|
370
371
|
* @param id - The {@link values.GenericId} of the document to remove.
|
|
371
372
|
*/
|
|
372
373
|
delete(id: GenericId<TableNamesInDataModel<DataModel>>): Promise<void>;
|
|
374
|
+
|
|
375
|
+
/**
|
|
376
|
+
* Values that are not known until the mutation commits.
|
|
377
|
+
*/
|
|
378
|
+
vars: {
|
|
379
|
+
/**
|
|
380
|
+
* The placeholder for the transaction's commit timestamp. Written into a
|
|
381
|
+
* document field via `db.insert`, it resolves at commit to an int64
|
|
382
|
+
* (`bigint`) ordered by commit order. Within the writing mutation,
|
|
383
|
+
* reading the field back yields the placeholder, which cannot be used as
|
|
384
|
+
* a number.
|
|
385
|
+
*/
|
|
386
|
+
commitTs: CommitTsPlaceholder;
|
|
387
|
+
};
|
|
373
388
|
}
|
|
374
389
|
|
|
375
390
|
/**
|
|
@@ -15,7 +15,7 @@ import { QueryInitializerImpl } from "./query_impl.js";
|
|
|
15
15
|
import { GenericDataModel, GenericDocument } from "../data_model.js";
|
|
16
16
|
import { validateArg } from "./validate.js";
|
|
17
17
|
import { version } from "../../index.js";
|
|
18
|
-
import { patchValueToJson } from "../../values/value.js";
|
|
18
|
+
import { commitTsPlaceholder, patchValueToJson } from "../../values/value.js";
|
|
19
19
|
|
|
20
20
|
async function get(
|
|
21
21
|
table: string | undefined,
|
|
@@ -164,6 +164,9 @@ export function setupWriter(): GenericDatabaseWriter<GenericDataModel> &
|
|
|
164
164
|
table: (tableName) => {
|
|
165
165
|
return new TableWriter(tableName, false);
|
|
166
166
|
},
|
|
167
|
+
vars: {
|
|
168
|
+
commitTs: commitTsPlaceholder,
|
|
169
|
+
},
|
|
167
170
|
};
|
|
168
171
|
}
|
|
169
172
|
|
package/src/server/log.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { audit } from "./audit_logging.js";
|
|
2
|
-
import { vars } from "./logVars.js";
|
|
2
|
+
import { internalVars, vars } from "./logVars.js";
|
|
3
3
|
|
|
4
4
|
// Type annotations are needed for the `unique symbol` types in `vars` to typecheck correctly
|
|
5
5
|
interface Log {
|
|
@@ -26,9 +26,12 @@ interface Log {
|
|
|
26
26
|
*/
|
|
27
27
|
audit: typeof audit;
|
|
28
28
|
vars: typeof vars;
|
|
29
|
+
/** @internal */
|
|
30
|
+
internalVars: typeof internalVars;
|
|
29
31
|
}
|
|
30
32
|
|
|
31
33
|
export const log: Log = {
|
|
32
34
|
audit,
|
|
33
35
|
vars,
|
|
36
|
+
internalVars,
|
|
34
37
|
};
|
package/src/server/logVars.ts
CHANGED
|
@@ -2,18 +2,21 @@ const REQUEST_ID = Symbol("var.requestId");
|
|
|
2
2
|
const IP = Symbol("var.ip");
|
|
3
3
|
const USER_AGENT = Symbol("var.userAgent");
|
|
4
4
|
const NOW = Symbol("var.now");
|
|
5
|
+
const CONVEX_ACTOR = Symbol("var.convexActor");
|
|
5
6
|
|
|
6
7
|
export type LogVar =
|
|
7
8
|
| typeof REQUEST_ID
|
|
8
9
|
| typeof IP
|
|
9
10
|
| typeof USER_AGENT
|
|
10
|
-
| typeof NOW
|
|
11
|
+
| typeof NOW
|
|
12
|
+
| typeof CONVEX_ACTOR;
|
|
11
13
|
|
|
12
14
|
export const varNames: Record<symbol, string> = {
|
|
13
15
|
[REQUEST_ID]: "requestId",
|
|
14
16
|
[IP]: "ip",
|
|
15
17
|
[USER_AGENT]: "userAgent",
|
|
16
18
|
[NOW]: "now",
|
|
19
|
+
[CONVEX_ACTOR]: "convexActor",
|
|
17
20
|
};
|
|
18
21
|
|
|
19
22
|
export const vars = {
|
|
@@ -29,3 +32,16 @@ export const vars = {
|
|
|
29
32
|
*/
|
|
30
33
|
now: NOW,
|
|
31
34
|
} as const;
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Internal-only log vars, surfaced via `log.internalVars`. These are kept out
|
|
38
|
+
* of the public `log.vars` surface.
|
|
39
|
+
*/
|
|
40
|
+
export const internalVars = {
|
|
41
|
+
/**
|
|
42
|
+
* If the function was invoked using admin auth (either directly or while
|
|
43
|
+
* acting as an end user, e.g. from the dashboard), resolved to information
|
|
44
|
+
* about the admin. Otherwise, resolved to `null`.
|
|
45
|
+
*/
|
|
46
|
+
convexActor: CONVEX_ACTOR,
|
|
47
|
+
} as const;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
2
|
-
import { GenericId } from "../values/index.js";
|
|
2
|
+
import { CommitTsPlaceholder, GenericId } from "../values/index.js";
|
|
3
3
|
import { describe, expect, test } from "vitest";
|
|
4
4
|
import { assert, Equals } from "../test/type_testing.js";
|
|
5
5
|
import { SystemIndexes } from "./system_fields.js";
|
|
@@ -27,6 +27,7 @@ describe("DataModelFromSchemaDefinition", () => {
|
|
|
27
27
|
number: v.number(),
|
|
28
28
|
float64: v.float64(),
|
|
29
29
|
int64: v.int64(),
|
|
30
|
+
commitTs: v.commitTs(),
|
|
30
31
|
boolean: v.boolean(),
|
|
31
32
|
string: v.string(),
|
|
32
33
|
bytes: v.bytes(),
|
|
@@ -43,6 +44,7 @@ describe("DataModelFromSchemaDefinition", () => {
|
|
|
43
44
|
number: number;
|
|
44
45
|
float64: number;
|
|
45
46
|
int64: bigint;
|
|
47
|
+
commitTs: bigint | CommitTsPlaceholder;
|
|
46
48
|
boolean: boolean;
|
|
47
49
|
string: string;
|
|
48
50
|
array: boolean[];
|
|
@@ -57,6 +59,7 @@ describe("DataModelFromSchemaDefinition", () => {
|
|
|
57
59
|
| "number"
|
|
58
60
|
| "float64"
|
|
59
61
|
| "int64"
|
|
62
|
+
| "commitTs"
|
|
60
63
|
| "boolean"
|
|
61
64
|
| "string"
|
|
62
65
|
| "bytes"
|
|
@@ -743,6 +746,7 @@ describe("JsonTypesFromSchema", () => {
|
|
|
743
746
|
numberField: v.number(),
|
|
744
747
|
float64Field: v.float64(),
|
|
745
748
|
int64Field: v.int64(),
|
|
749
|
+
commitTsField: v.commitTs(),
|
|
746
750
|
booleanField: v.boolean(),
|
|
747
751
|
stringField: v.string(),
|
|
748
752
|
bytesField: v.bytes(),
|
|
@@ -766,6 +770,7 @@ describe("JsonTypesFromSchema", () => {
|
|
|
766
770
|
numberField: { fieldType: { type: "number" }, optional: false },
|
|
767
771
|
float64Field: { fieldType: { type: "number" }, optional: false },
|
|
768
772
|
int64Field: { fieldType: { type: "bigint" }, optional: false },
|
|
773
|
+
commitTsField: { fieldType: { type: "commitTs" }, optional: false },
|
|
769
774
|
booleanField: { fieldType: { type: "boolean" }, optional: false },
|
|
770
775
|
stringField: { fieldType: { type: "string" }, optional: false },
|
|
771
776
|
bytesField: { fieldType: { type: "bytes" }, optional: false },
|
package/src/values/compare.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Value } from "./value.js";
|
|
1
|
+
import { CommitTsPlaceholder, MAX_INT64, Value } from "./value.js";
|
|
2
2
|
import { compareUTF8 } from "./compare_utf8.js";
|
|
3
3
|
|
|
4
4
|
export function compareValues(k1: Value | undefined, k2: Value | undefined) {
|
|
@@ -122,6 +122,9 @@ function makeComparable(v: Value | undefined): [number, any] {
|
|
|
122
122
|
if (typeof v === "bigint") {
|
|
123
123
|
return [2, v];
|
|
124
124
|
}
|
|
125
|
+
if (v instanceof CommitTsPlaceholder) {
|
|
126
|
+
return [2, MAX_INT64];
|
|
127
|
+
}
|
|
125
128
|
if (typeof v === "number") {
|
|
126
129
|
return [3, v];
|
|
127
130
|
}
|
|
@@ -140,5 +143,5 @@ function makeComparable(v: Value | undefined): [number, any] {
|
|
|
140
143
|
// Otherwise, it's an POJO.
|
|
141
144
|
const keys = Object.keys(v).sort();
|
|
142
145
|
const pojo: Value[] = keys.map((k) => [k, v[k]!]);
|
|
143
|
-
return [
|
|
146
|
+
return [9, pojo.map(makeComparable)];
|
|
144
147
|
}
|
package/src/values/index.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* @module
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
|
-
export { convexToJson, jsonToConvex } from "./value.js";
|
|
9
|
+
export { convexToJson, jsonToConvex, CommitTsPlaceholder } from "./value.js";
|
|
10
10
|
export type {
|
|
11
11
|
Id as GenericId,
|
|
12
12
|
JSONValue,
|
|
@@ -30,6 +30,7 @@ export type {
|
|
|
30
30
|
VId,
|
|
31
31
|
VFloat64,
|
|
32
32
|
VInt64,
|
|
33
|
+
VCommitTs,
|
|
33
34
|
VBoolean,
|
|
34
35
|
VBytes,
|
|
35
36
|
VString,
|
package/src/values/size.test.ts
CHANGED
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
SYSTEM_FIELD_CREATION_TIME_SIZE,
|
|
6
6
|
SYSTEM_FIELD_ID_ESTIMATE,
|
|
7
7
|
} from "./size.js";
|
|
8
|
+
import { commitTsPlaceholder } from "./value.js";
|
|
8
9
|
|
|
9
10
|
/**
|
|
10
11
|
* Tests for getConvexSize JS-specific behavior.
|
|
@@ -16,6 +17,10 @@ describe("getConvexSize", () => {
|
|
|
16
17
|
expect(getConvexSize(undefined)).toBe(0);
|
|
17
18
|
});
|
|
18
19
|
|
|
20
|
+
test("commit timestamp placeholder sized as resolved Int64", () => {
|
|
21
|
+
expect(getConvexSize(commitTsPlaceholder)).toBe(9);
|
|
22
|
+
});
|
|
23
|
+
|
|
19
24
|
test("long strings use TextEncoder path (>500 chars)", () => {
|
|
20
25
|
// This tests the JS-specific optimization for long strings
|
|
21
26
|
const longAscii = "a".repeat(1000);
|
package/src/values/size.ts
CHANGED
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* @module
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
|
-
import type
|
|
26
|
+
import { CommitTsPlaceholder, type Value } from "./value.js";
|
|
27
27
|
import { isSimpleObject } from "../common/index.js";
|
|
28
28
|
|
|
29
29
|
/**
|
|
@@ -51,6 +51,10 @@ export function getConvexSize(value: Value | undefined): number {
|
|
|
51
51
|
// Int64: 1 byte type marker + 8 bytes value
|
|
52
52
|
return 9;
|
|
53
53
|
}
|
|
54
|
+
if (value instanceof CommitTsPlaceholder) {
|
|
55
|
+
// Same as bigint
|
|
56
|
+
return 9;
|
|
57
|
+
}
|
|
54
58
|
if (typeof value === "number") {
|
|
55
59
|
// Float64: 1 byte type marker + 8 bytes value
|
|
56
60
|
return 9;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { GenericId } from "../values/index.js";
|
|
1
|
+
import { CommitTsPlaceholder, GenericId } from "../values/index.js";
|
|
2
2
|
import { describe, test, expect } from "vitest";
|
|
3
3
|
import { assert, Equals } from "../test/type_testing.js";
|
|
4
4
|
import { v, Infer } from "../values/validator.js";
|
|
@@ -56,6 +56,21 @@ describe("Validators", () => {
|
|
|
56
56
|
>();
|
|
57
57
|
});
|
|
58
58
|
|
|
59
|
+
test("commitTs validator", () => {
|
|
60
|
+
const commitTs = v.commitTs();
|
|
61
|
+
expect(commitTs.kind).toEqual("commitTs");
|
|
62
|
+
expect(commitTs.json).toEqual({ type: "commitTs" });
|
|
63
|
+
assert<Equals<Infer<typeof commitTs>, bigint | CommitTsPlaceholder>>();
|
|
64
|
+
|
|
65
|
+
const _optionalCommitTs = v.optional(v.commitTs());
|
|
66
|
+
assert<
|
|
67
|
+
Equals<
|
|
68
|
+
Infer<typeof _optionalCommitTs>,
|
|
69
|
+
bigint | CommitTsPlaceholder | undefined
|
|
70
|
+
>
|
|
71
|
+
>();
|
|
72
|
+
});
|
|
73
|
+
|
|
59
74
|
test("Most validators don't accept optional validators as children", () => {
|
|
60
75
|
const optional = v.optional(v.string());
|
|
61
76
|
const required = v.string();
|
package/src/values/validator.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
VBytes,
|
|
9
9
|
VFloat64,
|
|
10
10
|
VId,
|
|
11
|
+
VCommitTs,
|
|
11
12
|
VInt64,
|
|
12
13
|
VLiteral,
|
|
13
14
|
VNull,
|
|
@@ -206,6 +207,18 @@ export const v = {
|
|
|
206
207
|
return new VInt64({ isOptional: "required" });
|
|
207
208
|
},
|
|
208
209
|
|
|
210
|
+
/**
|
|
211
|
+
* Validates that the value is a commit timestamp: an int64 (`bigint`)
|
|
212
|
+
* assigned from the transaction's commit timestamp.
|
|
213
|
+
*
|
|
214
|
+
* An index on a field with this validator orders documents by commit order.
|
|
215
|
+
* Accepts any int64 value; write `db.vars.commitTs` to have the field
|
|
216
|
+
* resolve to the commit timestamp when the mutation commits.
|
|
217
|
+
*/
|
|
218
|
+
commitTs: () => {
|
|
219
|
+
return new VCommitTs({ isOptional: "required" });
|
|
220
|
+
},
|
|
221
|
+
|
|
209
222
|
/**
|
|
210
223
|
* Validates that the value is a `boolean`.
|
|
211
224
|
*/
|
package/src/values/validators.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { Expand } from "../type_utils.js";
|
|
2
2
|
import { GenericId } from "./index.js";
|
|
3
3
|
import { GenericValidator, ObjectType } from "./validator.js";
|
|
4
|
-
import { JSONValue, convexToJson } from "./value.js";
|
|
4
|
+
import { CommitTsPlaceholder, JSONValue, convexToJson } from "./value.js";
|
|
5
5
|
|
|
6
6
|
type TableNameFromType<T> =
|
|
7
7
|
T extends GenericId<infer TableName> ? TableName : string;
|
|
@@ -155,6 +155,30 @@ export class VInt64<
|
|
|
155
155
|
}
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
+
/**
|
|
159
|
+
* The type of the `v.commitTs()` validator.
|
|
160
|
+
*/
|
|
161
|
+
export class VCommitTs<
|
|
162
|
+
Type = bigint | CommitTsPlaceholder,
|
|
163
|
+
IsOptional extends OptionalProperty = "required",
|
|
164
|
+
> extends BaseValidator<Type, IsOptional> {
|
|
165
|
+
/**
|
|
166
|
+
* The kind of validator, `"commitTs"`.
|
|
167
|
+
*/
|
|
168
|
+
readonly kind = "commitTs" as const;
|
|
169
|
+
|
|
170
|
+
/** @internal */
|
|
171
|
+
get json(): ValidatorJSON {
|
|
172
|
+
return { type: this.kind };
|
|
173
|
+
}
|
|
174
|
+
/** @internal */
|
|
175
|
+
asOptional() {
|
|
176
|
+
return new VCommitTs<Type | undefined, "optional">({
|
|
177
|
+
isOptional: "optional",
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
|
|
158
182
|
/**
|
|
159
183
|
* The type of the `v.boolean()` validator.
|
|
160
184
|
*/
|
|
@@ -653,6 +677,8 @@ export type VOptional<T extends Validator<any, OptionalProperty, any>> =
|
|
|
653
677
|
? VFloat64<Type | undefined, "optional">
|
|
654
678
|
: T extends VInt64<infer Type, OptionalProperty>
|
|
655
679
|
? VInt64<Type | undefined, "optional">
|
|
680
|
+
: T extends VCommitTs<infer Type, OptionalProperty>
|
|
681
|
+
? VCommitTs<Type | undefined, "optional">
|
|
656
682
|
: T extends VBoolean<infer Type, OptionalProperty>
|
|
657
683
|
? VBoolean<Type | undefined, "optional">
|
|
658
684
|
: T extends VNull<infer Type, OptionalProperty>
|
|
@@ -712,6 +738,7 @@ export type Validator<
|
|
|
712
738
|
| VString<Type, IsOptional>
|
|
713
739
|
| VFloat64<Type, IsOptional>
|
|
714
740
|
| VInt64<Type, IsOptional>
|
|
741
|
+
| VCommitTs<Type, IsOptional>
|
|
715
742
|
| VBoolean<Type, IsOptional>
|
|
716
743
|
| VNull<Type, IsOptional>
|
|
717
744
|
| VAny<Type, IsOptional>
|
|
@@ -750,6 +777,7 @@ export type ValidatorJSON =
|
|
|
750
777
|
| { type: "null" }
|
|
751
778
|
| { type: "number" }
|
|
752
779
|
| { type: "bigint" }
|
|
780
|
+
| { type: "commitTs" }
|
|
753
781
|
| { type: "boolean" }
|
|
754
782
|
| { type: "string" }
|
|
755
783
|
| { type: "bytes" }
|
package/src/values/value.test.ts
CHANGED
|
@@ -8,6 +8,7 @@ import {
|
|
|
8
8
|
modernBigIntToBase64,
|
|
9
9
|
convexToJson,
|
|
10
10
|
jsonToConvex,
|
|
11
|
+
commitTsPlaceholder,
|
|
11
12
|
} from "./value.js";
|
|
12
13
|
import { compareValues } from "./compare.js";
|
|
13
14
|
|
|
@@ -88,6 +89,36 @@ describe("jsonToConvex", () => {
|
|
|
88
89
|
});
|
|
89
90
|
});
|
|
90
91
|
|
|
92
|
+
describe("commit timestamp sentinel", () => {
|
|
93
|
+
test("round trips through JSON as the singleton", () => {
|
|
94
|
+
const decoded = jsonToConvex({ property: { $commitTs: null } }) as any;
|
|
95
|
+
expect(decoded.property).toBe(commitTsPlaceholder);
|
|
96
|
+
expect(convexToJson({ property: commitTsPlaceholder as any })).toEqual({
|
|
97
|
+
property: { $commitTs: null },
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
|
|
101
|
+
test("rejects malformed tokens", () => {
|
|
102
|
+
expect(() => jsonToConvex({ $commitTs: 1 } as any)).toThrow(
|
|
103
|
+
/Malformed \$commitTs/,
|
|
104
|
+
);
|
|
105
|
+
// A `$commitTs` key alongside other fields is not the token; it's an
|
|
106
|
+
// invalid field name.
|
|
107
|
+
expect(() => jsonToConvex({ $commitTs: null, x: 1 })).toThrow(/reserved/);
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
test("throws on coercion", () => {
|
|
111
|
+
expect(() => Number(commitTsPlaceholder)).toThrow(/unresolved/);
|
|
112
|
+
expect(() => (commitTsPlaceholder as any) + 1n).toThrow(/unresolved/);
|
|
113
|
+
expect(() => JSON.stringify({ commitTs: commitTsPlaceholder })).toThrow(
|
|
114
|
+
/unresolved/,
|
|
115
|
+
);
|
|
116
|
+
expect(`${commitTsPlaceholder as any}`).toEqual(
|
|
117
|
+
"[unresolved commit timestamp]",
|
|
118
|
+
);
|
|
119
|
+
});
|
|
120
|
+
});
|
|
121
|
+
|
|
91
122
|
describe("bigints in Safari 14", () => {
|
|
92
123
|
test("roundtrips BigInt even in Safari 14", () => {
|
|
93
124
|
// https://caniuse.com/mdn-javascript_builtins_dataview_setbigint64
|
|
@@ -194,4 +225,8 @@ describe("compare", () => {
|
|
|
194
225
|
}
|
|
195
226
|
}
|
|
196
227
|
});
|
|
228
|
+
|
|
229
|
+
test("commit timestamp placeholders compare equal", () => {
|
|
230
|
+
expect(compareValues(commitTsPlaceholder, commitTsPlaceholder)).toEqual(0);
|
|
231
|
+
});
|
|
197
232
|
});
|