File tree Expand file tree Collapse file tree 9 files changed +113
-43
lines changed Expand file tree Collapse file tree 9 files changed +113
-43
lines changed Original file line number Diff line number Diff line change @@ -82,24 +82,12 @@ pub fn is_valid_field_name(s: &str) -> bool {
82
82
}
83
83
84
84
fn check_valid_field_name_inner ( s : & str ) -> Result < ( ) , String > {
85
- let mut chars = s. chars ( ) ;
86
- match chars. next ( ) {
87
- Some ( '$' ) => {
88
- return Err ( format ! (
89
- "Field name {s} starts with '$', which is reserved."
90
- ) )
91
- } ,
92
- Some ( c) => {
93
- if !c. is_ascii ( ) || c. is_ascii_control ( ) {
94
- return Err ( format ! (
95
- "Field name {s} has invalid character '{c}': Field names can only contain \
96
- non-control ASCII characters"
97
- ) ) ;
98
- }
99
- } ,
100
- None => return Err ( format ! ( "Field name cannot be empty" ) ) ,
101
- } ;
102
- for c in chars {
85
+ if s. starts_with ( '$' ) {
86
+ return Err ( format ! (
87
+ "Field name {s} starts with '$', which is reserved."
88
+ ) ) ;
89
+ }
90
+ for c in s. chars ( ) {
103
91
if !c. is_ascii ( ) || c. is_ascii_control ( ) {
104
92
return Err ( format ! (
105
93
"Field name {s} has invalid character '{c}': Field names can only contain \
Original file line number Diff line number Diff line change @@ -31,6 +31,7 @@ mod source_maps;
31
31
mod system_udfs;
32
32
mod unicode;
33
33
mod user_error;
34
+ mod values;
34
35
mod vector_search;
35
36
36
37
pub fn assert_contains ( error : & impl Display , expected : & str ) {
Original file line number Diff line number Diff line change
1
+ use common:: {
2
+ assert_obj,
3
+ value:: ConvexValue ,
4
+ } ;
5
+ use must_let:: must_let;
6
+ use runtime:: testing:: TestRuntime ;
7
+ use value:: assert_val;
8
+
9
+ use crate :: test_helpers:: UdfTest ;
10
+
11
+ #[ convex_macro:: test_runtime]
12
+ async fn test_bigint ( rt : TestRuntime ) -> anyhow:: Result < ( ) > {
13
+ let t = UdfTest :: default ( rt) . await ?;
14
+ let value = t. query ( "values:intQuery" , assert_obj ! ( ) ) . await ?;
15
+ must_let ! ( let ConvexValue :: Int64 ( v) = value) ;
16
+ assert_eq ! ( v, 1 ) ;
17
+ Ok ( ( ) )
18
+ }
19
+
20
+ #[ convex_macro:: test_runtime]
21
+ async fn test_empty_key ( rt : TestRuntime ) -> anyhow:: Result < ( ) > {
22
+ // Check that an object with an empty key round trips through mutation and
23
+ // query.
24
+ let t = UdfTest :: default ( rt) . await ?;
25
+ let id = t
26
+ . mutation ( "values:insertObject" , assert_obj ! ( "obj" => { "" => "hi" } ) )
27
+ . await ?;
28
+ let value = t. query ( "values:getObject" , assert_obj ! ( "id" => id) ) . await ?;
29
+ must_let ! ( let ConvexValue :: Object ( o) = value) ;
30
+ assert_eq ! ( o. len( ) , 3 ) ;
31
+ assert_eq ! ( o. get( "" ) . unwrap( ) . clone( ) , assert_val!( "hi" ) ) ;
32
+ Ok ( ( ) )
33
+ }
Original file line number Diff line number Diff line change @@ -471,7 +471,7 @@ mod tests {
471
471
http_format_tester (
472
472
rt,
473
473
"/api/query" ,
474
- "bigint :intQuery" ,
474
+ "values :intQuery" ,
475
475
json ! ( { } ) ,
476
476
None ,
477
477
Err ( "RequiresFormatParam" ) ,
@@ -484,7 +484,7 @@ mod tests {
484
484
http_format_tester (
485
485
rt,
486
486
"/api/query" ,
487
- "bigint :intQuery" ,
487
+ "values :intQuery" ,
488
488
json ! ( { } ) ,
489
489
Some ( "json" ) ,
490
490
Ok ( json ! ( "1" ) ) ,
@@ -497,7 +497,7 @@ mod tests {
497
497
http_format_tester (
498
498
rt,
499
499
"/api/mutation" ,
500
- "bigint :intMutation" ,
500
+ "values :intMutation" ,
501
501
json ! ( { } ) ,
502
502
None ,
503
503
Err ( "RequiresFormatParam" ) ,
@@ -510,7 +510,7 @@ mod tests {
510
510
http_format_tester (
511
511
rt,
512
512
"/api/mutation" ,
513
- "bigint :intMutation" ,
513
+ "values :intMutation" ,
514
514
json ! ( { } ) ,
515
515
Some ( "json" ) ,
516
516
Ok ( json ! ( "1" ) ) ,
@@ -523,7 +523,7 @@ mod tests {
523
523
http_format_tester (
524
524
rt,
525
525
"/api/action" ,
526
- "bigint :intAction" ,
526
+ "values :intAction" ,
527
527
json ! ( { } ) ,
528
528
None ,
529
529
Err ( "RequiresFormatParam" ) ,
@@ -536,7 +536,7 @@ mod tests {
536
536
http_format_tester (
537
537
rt,
538
538
"/api/action" ,
539
- "bigint :intAction" ,
539
+ "values :intAction" ,
540
540
json ! ( { } ) ,
541
541
Some ( "json" ) ,
542
542
Ok ( json ! ( "1" ) ) ,
Original file line number Diff line number Diff line change 1
- use std:: mem;
1
+ use std:: {
2
+ mem,
3
+ ops:: Deref ,
4
+ } ;
2
5
3
6
use crate :: {
4
7
assert_obj,
8
+ obj,
5
9
ConvexObject ,
6
10
ConvexValue ,
7
11
InternalId ,
@@ -130,3 +134,35 @@ fn test_shallow_merge() -> anyhow::Result<()> {
130
134
131
135
Ok ( ( ) )
132
136
}
137
+
138
+ #[ test]
139
+ fn test_object_keys ( ) -> anyhow:: Result < ( ) > {
140
+ let obj = assert_obj ! (
141
+ "name" => "me" ,
142
+ ) ;
143
+ assert_eq ! (
144
+ obj. keys( ) . map( Deref :: deref) . collect:: <Vec <_>>( ) ,
145
+ vec![ "name" ]
146
+ ) ;
147
+ let empty_string_key = assert_obj ! (
148
+ "" => "empty" ,
149
+ ) ;
150
+ assert_eq ! (
151
+ empty_string_key
152
+ . keys( )
153
+ . map( Deref :: deref)
154
+ . collect:: <Vec <_>>( ) ,
155
+ vec![ "" ]
156
+ ) ;
157
+ let control_char_key: anyhow:: Result < _ > = try { obj ! ( "\t " => "tab" ) ? } ;
158
+ assert ! ( control_char_key
159
+ . unwrap_err( )
160
+ . to_string( )
161
+ . contains( "Field names can only contain non-control ASCII characters" ) ) ;
162
+ let dollar_sign_key: anyhow:: Result < _ > = try { obj ! ( "$id" => "tab" ) ? } ;
163
+ assert ! ( dollar_sign_key
164
+ . unwrap_err( )
165
+ . to_string( )
166
+ . contains( "Field name $id starts with '$', which is reserved" ) ) ;
167
+ Ok ( ( ) )
168
+ }
Original file line number Diff line number Diff line change @@ -153,9 +153,6 @@ export const base64ToBigInt = (DataView.prototype as any).getBigInt64
153
153
const MAX_IDENTIFIER_LEN = 1024 ;
154
154
155
155
function validateObjectField ( k : string ) {
156
- if ( k . length === 0 ) {
157
- throw new Error ( "Empty field names are disallowed." ) ;
158
- }
159
156
if ( k . length > MAX_IDENTIFIER_LEN ) {
160
157
throw new Error (
161
158
`Field name ${ k } exceeds maximum field name length ${ MAX_IDENTIFIER_LEN } .` ,
Original file line number Diff line number Diff line change @@ -22,7 +22,6 @@ import type * as asyncTests from "../asyncTests.js";
22
22
import type * as auth from "../auth.js" ;
23
23
import type * as basic from "../basic.js" ;
24
24
import type * as benches from "../benches.js" ;
25
- import type * as bigint from "../bigint.js" ;
26
25
import type * as creationTime from "../creationTime.js" ;
27
26
import type * as crons from "../crons.js" ;
28
27
import type * as crons_error from "../crons_error.js" ;
@@ -74,6 +73,7 @@ import type * as sourceMaps from "../sourceMaps.js";
74
73
import type * as sync from "../sync.js" ;
75
74
import type * as unicode from "../unicode.js" ;
76
75
import type * as userError from "../userError.js" ;
76
+ import type * as values from "../values.js" ;
77
77
import type * as vector_search from "../vector_search.js" ;
78
78
79
79
/**
@@ -93,7 +93,6 @@ declare const fullApi: ApiFromModules<{
93
93
auth : typeof auth ;
94
94
basic : typeof basic ;
95
95
benches : typeof benches ;
96
- bigint : typeof bigint ;
97
96
creationTime : typeof creationTime ;
98
97
crons : typeof crons ;
99
98
crons_error : typeof crons_error ;
@@ -145,6 +144,7 @@ declare const fullApi: ApiFromModules<{
145
144
sync : typeof sync ;
146
145
unicode : typeof unicode ;
147
146
userError : typeof userError ;
147
+ values : typeof values ;
148
148
vector_search : typeof vector_search ;
149
149
} > ;
150
150
export declare const api : FilterApi <
Load Diff This file was deleted.
Original file line number Diff line number Diff line change
1
+ import { mutation , query , action } from "./_generated/server" ;
2
+ import { v } from "convex/values" ;
3
+
4
+ export const intQuery = query ( async ( ) => {
5
+ return 1n ;
6
+ } ) ;
7
+
8
+ export const intMutation = mutation ( async ( ) => {
9
+ return 1n ;
10
+ } ) ;
11
+
12
+ export const intAction = action ( async ( ) => {
13
+ return 1n ;
14
+ } ) ;
15
+
16
+ export const insertObject = mutation ( {
17
+ args : { obj : v . any ( ) } ,
18
+ handler : async ( ctx , { obj } ) => {
19
+ return ctx . db . insert ( "test" , obj ) ;
20
+ } ,
21
+ } ) ;
22
+
23
+ export const getObject = query ( {
24
+ args : { id : v . id ( "test" ) } ,
25
+ handler : async ( ctx , { id } ) => {
26
+ return ctx . db . get ( id ) ;
27
+ } ,
28
+ } ) ;
You can’t perform that action at this time.
0 commit comments