@@ -34,6 +34,75 @@ final isProduction = defineBoolean(
3434
3535void main (List <String > args) {
3636 fireUp (args, (firebase) {
37+ // ==========================================================================
38+ // HTTPS Callable Functions (onCall / onCallWithData)
39+ // ==========================================================================
40+
41+ // Basic callable function - untyped data
42+ firebase.https.onCall (
43+ name: 'greet' ,
44+ (request, response) async {
45+ final data = request.data as Map <String , dynamic >? ;
46+ final name = data? ['name' ] ?? 'World' ;
47+ return CallableResult ({'message' : 'Hello, $name !' });
48+ },
49+ );
50+
51+ // Callable function with typed data using fromJson
52+ firebase.https.onCallWithData <GreetRequest , GreetResponse >(
53+ name: 'greetTyped' ,
54+ fromJson: GreetRequest .fromJson,
55+ (request, response) async {
56+ return GreetResponse (message: 'Hello, ${request .data .name }!' );
57+ },
58+ );
59+
60+ // Callable function demonstrating error handling
61+ firebase.https.onCall (
62+ name: 'divide' ,
63+ (request, response) async {
64+ final data = request.data as Map <String , dynamic >? ;
65+ final a = (data? ['a' ] as num ? )? .toDouble ();
66+ final b = (data? ['b' ] as num ? )? .toDouble ();
67+
68+ if (a == null || b == null ) {
69+ throw InvalidArgumentError ('Both "a" and "b" are required' );
70+ }
71+
72+ if (b == 0 ) {
73+ throw FailedPreconditionError ('Cannot divide by zero' );
74+ }
75+
76+ return CallableResult ({'result' : a / b});
77+ },
78+ );
79+
80+ // Callable function with streaming support
81+ firebase.https.onCall (
82+ name: 'countdown' ,
83+ options: const CallableOptions (
84+ heartBeatIntervalSeconds: HeartBeatIntervalSeconds (5 ),
85+ ),
86+ (request, response) async {
87+ final data = request.data as Map <String , dynamic >? ;
88+ final start = (data? ['start' ] as num ? )? .toInt () ?? 10 ;
89+
90+ // Stream countdown if client supports it
91+ if (request.acceptsStreaming) {
92+ for (var i = start; i >= 0 ; i-- ) {
93+ await response.sendChunk ({'count' : i});
94+ await Future <void >.delayed (const Duration (milliseconds: 100 ));
95+ }
96+ }
97+
98+ return CallableResult ({'message' : 'Countdown complete!' });
99+ },
100+ );
101+
102+ // ==========================================================================
103+ // HTTPS onRequest Functions
104+ // ==========================================================================
105+
37106 // HTTPS onRequest example - using parameterized configuration
38107 firebase.https.onRequest (
39108 name: 'helloWorld' ,
@@ -251,3 +320,29 @@ void main(List<String> args) {
251320 print ('Functions registered successfully!' );
252321 });
253322}
323+
324+ // =============================================================================
325+ // Data classes for typed callable functions
326+ // =============================================================================
327+
328+ /// Request data for the greetTyped callable function.
329+ class GreetRequest {
330+ GreetRequest ({required this .name});
331+
332+ factory GreetRequest .fromJson (Map <String , dynamic > json) {
333+ return GreetRequest (name: json['name' ] as String ? ?? 'World' );
334+ }
335+
336+ final String name;
337+
338+ Map <String , dynamic > toJson () => {'name' : name};
339+ }
340+
341+ /// Response data for the greetTyped callable function.
342+ class GreetResponse {
343+ GreetResponse ({required this .message});
344+
345+ final String message;
346+
347+ Map <String , dynamic > toJson () => {'message' : message};
348+ }
0 commit comments