From 8c065870fcb14d0ec7c276f9604539ff68ca907e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 15:29:30 +0000 Subject: [PATCH 1/5] Add deploy Dart on Firebase Functions codelab sample This commit implements the Dart Firebase Functions codelab logic. It creates a Dart/codelab-dart-functions flutter application with an additional shared package for sharing the `IncrementResponse` object via json\_serializable between front-end and back-end logic. Additionally it implements the `incrementCallable` functionality via a new google\_cloud\_firestore and firebase\_functions dart application project that compiles and targets node correctly through firebase deploy. Co-authored-by: jhuleatt <3759507+jhuleatt@users.noreply.github.com> --- Dart/codelab-dart-functions/.gitignore | 45 ++ Dart/codelab-dart-functions/README.md | 14 + .../analysis_options.yaml | 28 + Dart/codelab-dart-functions/firebase.json | 19 + .../functions/bin/server.dart | 71 +++ .../functions/build.yaml | 5 + .../functions/pubspec.lock | 444 +++++++++++++++ .../functions/pubspec.yaml | 13 + Dart/codelab-dart-functions/lib/main.dart | 90 +++ .../packages/shared/.gitignore | 7 + .../packages/shared/CHANGELOG.md | 3 + .../packages/shared/README.md | 39 ++ .../packages/shared/analysis_options.yaml | 30 + .../packages/shared/lib/shared.dart | 2 + .../packages/shared/lib/src/models.dart | 20 + .../packages/shared/lib/src/models.g.dart | 21 + .../packages/shared/lib/src/shared_base.dart | 6 + .../packages/shared/pubspec.lock | 525 ++++++++++++++++++ .../packages/shared/pubspec.yaml | 18 + Dart/codelab-dart-functions/pubspec.lock | 260 +++++++++ Dart/codelab-dart-functions/pubspec.yaml | 24 + .../test/widget_test.dart | 10 + 22 files changed, 1694 insertions(+) create mode 100644 Dart/codelab-dart-functions/.gitignore create mode 100644 Dart/codelab-dart-functions/README.md create mode 100644 Dart/codelab-dart-functions/analysis_options.yaml create mode 100644 Dart/codelab-dart-functions/firebase.json create mode 100644 Dart/codelab-dart-functions/functions/bin/server.dart create mode 100644 Dart/codelab-dart-functions/functions/build.yaml create mode 100644 Dart/codelab-dart-functions/functions/pubspec.lock create mode 100644 Dart/codelab-dart-functions/functions/pubspec.yaml create mode 100644 Dart/codelab-dart-functions/lib/main.dart create mode 100644 Dart/codelab-dart-functions/packages/shared/.gitignore create mode 100644 Dart/codelab-dart-functions/packages/shared/CHANGELOG.md create mode 100644 Dart/codelab-dart-functions/packages/shared/README.md create mode 100644 Dart/codelab-dart-functions/packages/shared/analysis_options.yaml create mode 100644 Dart/codelab-dart-functions/packages/shared/lib/shared.dart create mode 100644 Dart/codelab-dart-functions/packages/shared/lib/src/models.dart create mode 100644 Dart/codelab-dart-functions/packages/shared/lib/src/models.g.dart create mode 100644 Dart/codelab-dart-functions/packages/shared/lib/src/shared_base.dart create mode 100644 Dart/codelab-dart-functions/packages/shared/pubspec.lock create mode 100644 Dart/codelab-dart-functions/packages/shared/pubspec.yaml create mode 100644 Dart/codelab-dart-functions/pubspec.lock create mode 100644 Dart/codelab-dart-functions/pubspec.yaml create mode 100644 Dart/codelab-dart-functions/test/widget_test.dart diff --git a/Dart/codelab-dart-functions/.gitignore b/Dart/codelab-dart-functions/.gitignore new file mode 100644 index 000000000..3820a95c6 --- /dev/null +++ b/Dart/codelab-dart-functions/.gitignore @@ -0,0 +1,45 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.build/ +.buildlog/ +.history +.svn/ +.swiftpm/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +**/doc/api/ +**/ios/Flutter/.last_build_id +.dart_tool/ +.flutter-plugins-dependencies +.pub-cache/ +.pub/ +/build/ +/coverage/ + +# Symbolication related +app.*.symbols + +# Obfuscation related +app.*.map.json + +# Android Studio will place build artifacts here +/android/app/debug +/android/app/profile +/android/app/release diff --git a/Dart/codelab-dart-functions/README.md b/Dart/codelab-dart-functions/README.md new file mode 100644 index 000000000..0eefb134e --- /dev/null +++ b/Dart/codelab-dart-functions/README.md @@ -0,0 +1,14 @@ +# Codelab Dart Functions + +This project contains the source code for the "Deploy Dart on Firebase Functions" codelab. + +See [the codelab](https://codelabs.developers.google.com/deploy-dart-on-firebase-functions) for full instructions. + +## Running locally + +This uses the Firebase emulator suite to test without deploying. + +1. Ensure Firebase CLI is installed. +2. Initialize emulators in the root of the project: `firebase init emulators` +3. Start the emulators: `firebase emulators:start` +4. Run the flutter application `flutter run`. diff --git a/Dart/codelab-dart-functions/analysis_options.yaml b/Dart/codelab-dart-functions/analysis_options.yaml new file mode 100644 index 000000000..0d2902135 --- /dev/null +++ b/Dart/codelab-dart-functions/analysis_options.yaml @@ -0,0 +1,28 @@ +# This file configures the analyzer, which statically analyzes Dart code to +# check for errors, warnings, and lints. +# +# The issues identified by the analyzer are surfaced in the UI of Dart-enabled +# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be +# invoked from the command line by running `flutter analyze`. + +# The following line activates a set of recommended lints for Flutter apps, +# packages, and plugins designed to encourage good coding practices. +include: package:flutter_lints/flutter.yaml + +linter: + # The lint rules applied to this project can be customized in the + # section below to disable rules from the `package:flutter_lints/flutter.yaml` + # included above or to enable additional rules. A list of all available lints + # and their documentation is published at https://dart.dev/lints. + # + # Instead of disabling a lint rule for the entire project in the + # section below, it can also be suppressed for a single line of code + # or a specific dart file by using the `// ignore: name_of_lint` and + # `// ignore_for_file: name_of_lint` syntax on the line or in the file + # producing the lint. + rules: + # avoid_print: false # Uncomment to disable the `avoid_print` rule + # prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/Dart/codelab-dart-functions/firebase.json b/Dart/codelab-dart-functions/firebase.json new file mode 100644 index 000000000..d75438d1b --- /dev/null +++ b/Dart/codelab-dart-functions/firebase.json @@ -0,0 +1,19 @@ +{ + "functions": [ + { + "source": "functions", + "codebase": "dart-codelab-dart-functions", + "ignore": [ + "node_modules", + ".git", + "firebase-debug.log", + "firebase-debug.*.log", + "*.local" + ], + "predeploy": [ + "dart pub get --directory=\"$RESOURCE_DIR\"", + "dart run build_runner build --delete-conflicting-outputs --directory=\"$RESOURCE_DIR\"" + ] + } + ] +} diff --git a/Dart/codelab-dart-functions/functions/bin/server.dart b/Dart/codelab-dart-functions/functions/bin/server.dart new file mode 100644 index 000000000..c6e0ebb9c --- /dev/null +++ b/Dart/codelab-dart-functions/functions/bin/server.dart @@ -0,0 +1,71 @@ +import 'dart:convert'; +import 'package:firebase_functions/firebase_functions.dart'; +import 'package:google_cloud_firestore/google_cloud_firestore.dart' + show FieldValue; +import 'package:shared/shared.dart'; + +void main(List args) async { + await fireUp(args, (firebase) { + + // Listen for calls to the http request and name defined in the shared package. + firebase.https.onRequest(name: incrementCallable, (request) async { + + // In a production app, verify the user with request.auth?.uid here. + // ignore: avoid_print + print('Incrementing counter on the server...'); + + // Get firestore database instance + final firestore = firebase.adminApp.firestore(); + + // Get a reference to the counter document + final counterDoc = firestore.collection('counters').doc('global'); + + // Get the current snapshot for the count data + final snapshot = await counterDoc.get(); + + // Increment response we will send back + IncrementResponse incrementResponse; + + // Check for the current count and if the snapshot exists + if (snapshot.data() case {'count': int value} when snapshot.exists) { + if (request.method == 'GET') { + // Get the current result + incrementResponse = IncrementResponse( + success: true, + message: 'Read-only sync complete', + newCount: value, + ); + } else if (request.method == 'POST') { + // Increment count by one + final step = request.url.queryParameters['step'] as int? ?? 1; + await counterDoc.update({'count': FieldValue.increment(step)}); + incrementResponse = IncrementResponse( + success: true, + message: 'Atomic increment complete', + newCount: value + step, + ); + } else { + throw FailedPreconditionError( + 'only GET and POST requests are allowed', + ); + } + } else { + // Create a new document with a count of 1 + await counterDoc.set({'count': 1}); + incrementResponse = const IncrementResponse( + success: true, + message: 'Cloud-sync complete', + newCount: 1, + ); + } + + // Return the response as JSON + return Response( + 200, + body: jsonEncode(incrementResponse.toJson()), + headers: {'Content-Type': 'application/json'}, + ); + }); + + }); +} diff --git a/Dart/codelab-dart-functions/functions/build.yaml b/Dart/codelab-dart-functions/functions/build.yaml new file mode 100644 index 000000000..8eb7eff7b --- /dev/null +++ b/Dart/codelab-dart-functions/functions/build.yaml @@ -0,0 +1,5 @@ +targets: + $default: + sources: + - "bin/**" + - "lib/**" diff --git a/Dart/codelab-dart-functions/functions/pubspec.lock b/Dart/codelab-dart-functions/functions/pubspec.lock new file mode 100644 index 000000000..0f2ece3ea --- /dev/null +++ b/Dart/codelab-dart-functions/functions/pubspec.lock @@ -0,0 +1,444 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _discoveryapis_commons: + dependency: transitive + description: + name: _discoveryapis_commons + sha256: "113c4100b90a5b70a983541782431b82168b3cae166ab130649c36eb3559d498" + url: "https://pub.dev" + source: hosted + version: "1.0.7" + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: a49d6cf99e8d8e7a8e93668d09ced0bbdb954d0b4fccc2f5f9241c6b87fad95c + url: "https://pub.dev" + source: hosted + version: "99.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "663efa951fb8a45e06f491223a604c93820598f20e6a99c25617a1576065e8b7" + url: "https://pub.dev" + source: hosted + version: "12.1.0" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + asn1lib: + dependency: transitive + description: + name: asn1lib + sha256: "9a8f69025044eb466b9b60ef3bc3ac99b4dc6c158ae9c56d25eeccf5bc56d024" + url: "https://pub.dev" + source: hosted + version: "1.6.5" + async: + dependency: transitive + description: + name: async + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 + url: "https://pub.dev" + source: hosted + version: "2.13.1" + build: + dependency: transitive + description: + name: build + sha256: aadd943f4f8cc946882c954c187e6115a84c98c81ad1d9c6cbf0895a8c85da9c + url: "https://pub.dev" + source: hosted + version: "4.0.5" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + dart_jsonwebtoken: + dependency: transitive + description: + name: dart_jsonwebtoken + sha256: cb79ed79baa02b4f59a597bf365873cbd83f9bb15273d63f7803802d21717c7d + url: "https://pub.dev" + source: hosted + version: "3.4.0" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: a4c1ccfee44c7e75ed80484071a5c142a385345e658fd8bd7c4b5c97e7198f98 + url: "https://pub.dev" + source: hosted + version: "3.1.8" + equatable: + dependency: transitive + description: + name: equatable + sha256: "3e0141505477fd8ad55d6eb4e7776d3fe8430be8e497ccb1521370c3f21a3e2b" + url: "https://pub.dev" + source: hosted + version: "2.0.8" + ffi: + dependency: transitive + description: + name: ffi + sha256: "6d7fd89431262d8f3125e81b50d3847a091d846eafcd4fdb88dd06f36d705a45" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + firebase_admin_sdk: + dependency: transitive + description: + name: firebase_admin_sdk + sha256: "3827a3b30f3e76e9502cafab6fb6be28b29c632e83475b6ce3f146b5e077baad" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + firebase_functions: + dependency: "direct main" + description: + name: firebase_functions + sha256: c4e9cdcf8a5650223b20992be52517981f277c4e6d9a17c1077c9523a4d65e8f + url: "https://pub.dev" + source: hosted + version: "0.5.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + google_cloud: + dependency: transitive + description: + name: google_cloud + sha256: fbcde933b2d8600c3cdb2328f8f4c47628ec29a39e9cef85dee535c7868993c4 + url: "https://pub.dev" + source: hosted + version: "0.4.1" + google_cloud_firestore: + dependency: "direct main" + description: + name: google_cloud_firestore + sha256: e9a788301ee25cef6ffa86046cb0e80b4974b4a72d23a25231e161587fd84c8c + url: "https://pub.dev" + source: hosted + version: "0.5.1" + google_cloud_protobuf: + dependency: transitive + description: + name: google_cloud_protobuf + sha256: "5564bfba335f7ca82fcc865f6f2c04b11fd175ec23cb0248f6e22579017e03d1" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + google_cloud_rpc: + dependency: transitive + description: + name: google_cloud_rpc + sha256: "7eef0b8a77021d19aff96cefcb9356dde4187daac3ecec33d7017637b83cdb4d" + url: "https://pub.dev" + source: hosted + version: "0.5.0" + google_cloud_storage: + dependency: transitive + description: + name: google_cloud_storage + sha256: "8410cddc2c37b7ef81d154b3533a7d8cf22a175f519fe9ba4ee0d5a790ea3040" + url: "https://pub.dev" + source: hosted + version: "0.6.1" + google_identity_services_web: + dependency: transitive + description: + name: google_identity_services_web + sha256: "5d187c46dc59e02646e10fe82665fc3884a9b71bc1c90c2b8b749316d33ee454" + url: "https://pub.dev" + source: hosted + version: "0.3.3+1" + googleapis: + dependency: transitive + description: + name: googleapis + sha256: "62b5988f228b774448ebd99b53fe8069becb55840f1b28948bb84160373dc0b6" + url: "https://pub.dev" + source: hosted + version: "16.0.0" + googleapis_auth: + dependency: transitive + description: + name: googleapis_auth + sha256: "661738b763d3e524de69df53bf4e03943e4e01e98265cebcc6684871b06a5379" + url: "https://pub.dev" + source: hosted + version: "2.3.0" + http: + dependency: transitive + description: + name: http + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" + url: "https://pub.dev" + source: hosted + version: "1.6.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + intl: + dependency: transitive + description: + name: intl + sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5" + url: "https://pub.dev" + source: hosted + version: "0.20.2" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 + url: "https://pub.dev" + source: hosted + version: "4.11.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + meta: + dependency: transitive + description: + name: meta + sha256: df0c643f44ad098eb37988027a8e2b2b5a031fd3977f06bbfd3a76637e8df739 + url: "https://pub.dev" + source: hosted + version: "1.18.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + pem: + dependency: transitive + description: + name: pem + sha256: e66b389cbb007fa5860d511f08ea604ea68e78afc4e1b543dc227a0f0ef4faf9 + url: "https://pub.dev" + source: hosted + version: "2.0.6" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "91bd59303e9f769f108f8df05e371341b15d59e995e6806aefab827b58336675" + url: "https://pub.dev" + source: hosted + version: "7.0.2" + pointycastle: + dependency: transitive + description: + name: pointycastle + sha256: "92aa3841d083cc4b0f4709b5c74fd6409a3e6ba833ffc7dc6a8fee096366acf5" + url: "https://pub.dev" + source: hosted + version: "4.0.0" + protobuf: + dependency: transitive + description: + name: protobuf + sha256: "75ec242d22e950bdcc79ee38dd520ce4ee0bc491d7fadc4ea47694604d22bf06" + url: "https://pub.dev" + source: hosted + version: "6.0.0" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + shared: + dependency: "direct main" + description: + path: "../packages/shared" + relative: true + source: path + version: "1.0.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "732792cfd197d2161a65bb029606a46e0a18ff30ef9e141a7a82172b05ea8ecd" + url: "https://pub.dev" + source: hosted + version: "4.2.2" + source_span: + dependency: transitive + description: + name: source_span + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" + source: hosted + version: "1.10.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" + yaml_edit: + dependency: transitive + description: + name: yaml_edit + sha256: "07c9e63ba42519745182b88ca12264a7ba2484d8239958778dfe4d44fe760488" + url: "https://pub.dev" + source: hosted + version: "2.2.4" +sdks: + dart: ">=3.11.0 <4.0.0" diff --git a/Dart/codelab-dart-functions/functions/pubspec.yaml b/Dart/codelab-dart-functions/functions/pubspec.yaml new file mode 100644 index 000000000..be42ac2be --- /dev/null +++ b/Dart/codelab-dart-functions/functions/pubspec.yaml @@ -0,0 +1,13 @@ +name: functions +description: A starting point for Dart Cloud Functions +version: 1.0.0 +publish_to: none + +environment: + sdk: ">=3.4.0 <4.0.0" + +dependencies: + firebase_functions: + google_cloud_firestore: + shared: + path: ../packages/shared diff --git a/Dart/codelab-dart-functions/lib/main.dart b/Dart/codelab-dart-functions/lib/main.dart new file mode 100644 index 000000000..3561a7a88 --- /dev/null +++ b/Dart/codelab-dart-functions/lib/main.dart @@ -0,0 +1,90 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:shared/shared.dart'; + +/// Get from emulator output when running or when deploying: +/// ✔ functions[us-central1-increment]: http function initialized +/// (http://127.0.0.1:5001/demo-no-project/us-central1/increment). +const incrementUrl = 'FIREBASE_FUNCTIONS_URL_HERE'; + +void main() { + runApp(const MyApp()); +} + +class MyApp extends StatelessWidget { + const MyApp({super.key}); + @override + Widget build(BuildContext context) => MaterialApp( + debugShowCheckedModeBanner: false, + theme: ThemeData(useMaterial3: true, colorSchemeSeed: Colors.blue), + home: const CounterPage(), + ); +} + +class CounterPage extends StatefulWidget { + const CounterPage({super.key}); + @override + State createState() => _CounterPageState(); +} + +class _CounterPageState extends State { + int _count = 0; + bool _loading = false; + + @override + void initState() { + super.initState(); + // Fetch the current count + _increment(readOnly: true).ignore(); + } + + Future _increment({bool readOnly = false}) async { + setState(() => _loading = true); + try { + // Call the Dart function. + final uri = Uri.parse(incrementUrl); + final response = readOnly ? await http.get(uri) : await http.post(uri); + + // Parse the response back into the shared Dart object. + final responseData = jsonDecode(response.body); + final incrementResponse = IncrementResponse.fromJson(responseData); + + if (incrementResponse.success) { + setState(() => _count = incrementResponse.newCount ?? _count); + } + } catch (e) { + if (kDebugMode) { + print("Error calling function: $e"); + } + } finally { + setState(() => _loading = false); + } + } + + @override + Widget build(BuildContext context) { + return Scaffold( + appBar: AppBar(title: const Text('Multiplayer Counter')), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + const Text('You have pushed the button this many times:'), + Text( + '$_count', + style: Theme.of(context).textTheme.headlineMedium, + ), + ], + ), + ), + floatingActionButton: FloatingActionButton( + onPressed: _loading ? null : _increment, + tooltip: 'Increment', + child: const Icon(Icons.add), + ), + ); + } +} diff --git a/Dart/codelab-dart-functions/packages/shared/.gitignore b/Dart/codelab-dart-functions/packages/shared/.gitignore new file mode 100644 index 000000000..3cceda557 --- /dev/null +++ b/Dart/codelab-dart-functions/packages/shared/.gitignore @@ -0,0 +1,7 @@ +# https://dart.dev/guides/libraries/private-files +# Created by `dart pub` +.dart_tool/ + +# Avoid committing pubspec.lock for library packages; see +# https://dart.dev/guides/libraries/private-files#pubspeclock. +pubspec.lock diff --git a/Dart/codelab-dart-functions/packages/shared/CHANGELOG.md b/Dart/codelab-dart-functions/packages/shared/CHANGELOG.md new file mode 100644 index 000000000..effe43c82 --- /dev/null +++ b/Dart/codelab-dart-functions/packages/shared/CHANGELOG.md @@ -0,0 +1,3 @@ +## 1.0.0 + +- Initial version. diff --git a/Dart/codelab-dart-functions/packages/shared/README.md b/Dart/codelab-dart-functions/packages/shared/README.md new file mode 100644 index 000000000..4a260d8d2 --- /dev/null +++ b/Dart/codelab-dart-functions/packages/shared/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/Dart/codelab-dart-functions/packages/shared/analysis_options.yaml b/Dart/codelab-dart-functions/packages/shared/analysis_options.yaml new file mode 100644 index 000000000..dee8927aa --- /dev/null +++ b/Dart/codelab-dart-functions/packages/shared/analysis_options.yaml @@ -0,0 +1,30 @@ +# This file configures the static analysis results for your project (errors, +# warnings, and lints). +# +# This enables the 'recommended' set of lints from `package:lints`. +# This set helps identify many issues that may lead to problems when running +# or consuming Dart code, and enforces writing Dart using a single, idiomatic +# style and format. +# +# If you want a smaller set of lints you can change this to specify +# 'package:lints/core.yaml'. These are just the most critical lints +# (the recommended set includes the core lints). +# The core lints are also what is used by pub.dev for scoring packages. + +include: package:lints/recommended.yaml + +# Uncomment the following section to specify additional rules. + +# linter: +# rules: +# - camel_case_types + +# analyzer: +# exclude: +# - path/to/excluded/files/** + +# For more information about the core and recommended set of lints, see +# https://dart.dev/go/core-lints + +# For additional information about configuring this file, see +# https://dart.dev/guides/language/analysis-options diff --git a/Dart/codelab-dart-functions/packages/shared/lib/shared.dart b/Dart/codelab-dart-functions/packages/shared/lib/shared.dart new file mode 100644 index 000000000..8837ad182 --- /dev/null +++ b/Dart/codelab-dart-functions/packages/shared/lib/shared.dart @@ -0,0 +1,2 @@ + +export 'src/models.dart'; diff --git a/Dart/codelab-dart-functions/packages/shared/lib/src/models.dart b/Dart/codelab-dart-functions/packages/shared/lib/src/models.dart new file mode 100644 index 000000000..354f79046 --- /dev/null +++ b/Dart/codelab-dart-functions/packages/shared/lib/src/models.dart @@ -0,0 +1,20 @@ +import 'package:json_annotation/json_annotation.dart'; + +part 'models.g.dart'; + +@JsonSerializable() +class IncrementResponse { + final bool success; + final String? message; + final int? newCount; + + const IncrementResponse({required this.success, this.message, this.newCount}); + + factory IncrementResponse.fromJson(Map json) => + _$IncrementResponseFromJson(json); + + Map toJson() => _$IncrementResponseToJson(this); +} + +// Store the function name as a constant to ensure consistency between client and server. +const incrementCallable = 'increment'; diff --git a/Dart/codelab-dart-functions/packages/shared/lib/src/models.g.dart b/Dart/codelab-dart-functions/packages/shared/lib/src/models.g.dart new file mode 100644 index 000000000..492df5c35 --- /dev/null +++ b/Dart/codelab-dart-functions/packages/shared/lib/src/models.g.dart @@ -0,0 +1,21 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND + +part of 'models.dart'; + +// ************************************************************************** +// JsonSerializableGenerator +// ************************************************************************** + +IncrementResponse _$IncrementResponseFromJson(Map json) => + IncrementResponse( + success: json['success'] as bool, + message: json['message'] as String?, + newCount: (json['newCount'] as num?)?.toInt(), + ); + +Map _$IncrementResponseToJson(IncrementResponse instance) => + { + 'success': instance.success, + 'message': instance.message, + 'newCount': instance.newCount, + }; diff --git a/Dart/codelab-dart-functions/packages/shared/lib/src/shared_base.dart b/Dart/codelab-dart-functions/packages/shared/lib/src/shared_base.dart new file mode 100644 index 000000000..e8a6f1590 --- /dev/null +++ b/Dart/codelab-dart-functions/packages/shared/lib/src/shared_base.dart @@ -0,0 +1,6 @@ +// TODO: Put public facing types in this file. + +/// Checks if you are awesome. Spoiler: you are. +class Awesome { + bool get isAwesome => true; +} diff --git a/Dart/codelab-dart-functions/packages/shared/pubspec.lock b/Dart/codelab-dart-functions/packages/shared/pubspec.lock new file mode 100644 index 000000000..e3c4392a6 --- /dev/null +++ b/Dart/codelab-dart-functions/packages/shared/pubspec.lock @@ -0,0 +1,525 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + _fe_analyzer_shared: + dependency: transitive + description: + name: _fe_analyzer_shared + sha256: a49d6cf99e8d8e7a8e93668d09ced0bbdb954d0b4fccc2f5f9241c6b87fad95c + url: "https://pub.dev" + source: hosted + version: "99.0.0" + analyzer: + dependency: transitive + description: + name: analyzer + sha256: "663efa951fb8a45e06f491223a604c93820598f20e6a99c25617a1576065e8b7" + url: "https://pub.dev" + source: hosted + version: "12.1.0" + args: + dependency: transitive + description: + name: args + sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04 + url: "https://pub.dev" + source: hosted + version: "2.7.0" + async: + dependency: transitive + description: + name: async + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 + url: "https://pub.dev" + source: hosted + version: "2.13.1" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + build: + dependency: transitive + description: + name: build + sha256: aadd943f4f8cc946882c954c187e6115a84c98c81ad1d9c6cbf0895a8c85da9c + url: "https://pub.dev" + source: hosted + version: "4.0.5" + build_config: + dependency: transitive + description: + name: build_config + sha256: "4070d2a59f8eec34c97c86ceb44403834899075f66e8a9d59706f8e7834f6f71" + url: "https://pub.dev" + source: hosted + version: "1.3.0" + build_daemon: + dependency: transitive + description: + name: build_daemon + sha256: bf05f6e12cfea92d3c09308d7bcdab1906cd8a179b023269eed00c071004b957 + url: "https://pub.dev" + source: hosted + version: "4.1.1" + build_runner: + dependency: "direct dev" + description: + name: build_runner + sha256: "521daf8d189deb79ba474e43a696b41c49fb3987818dbacf3308f1e03673a75e" + url: "https://pub.dev" + source: hosted + version: "2.13.1" + built_collection: + dependency: transitive + description: + name: built_collection + sha256: "376e3dd27b51ea877c28d525560790aee2e6fbb5f20e2f85d5081027d94e2100" + url: "https://pub.dev" + source: hosted + version: "5.1.1" + built_value: + dependency: transitive + description: + name: built_value + sha256: "0730c18c770d05636a8f945c32a4d7d81cb6e0f0148c8db4ad12e7748f7e49af" + url: "https://pub.dev" + source: hosted + version: "8.12.5" + checked_yaml: + dependency: transitive + description: + name: checked_yaml + sha256: "959525d3162f249993882720d52b7e0c833978df229be20702b33d48d91de70f" + url: "https://pub.dev" + source: hosted + version: "2.0.4" + cli_config: + dependency: transitive + description: + name: cli_config + sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec + url: "https://pub.dev" + source: hosted + version: "0.2.0" + code_builder: + dependency: transitive + description: + name: code_builder + sha256: "6a6cab2ba4680d6423f34a9b972a4c9a94ebe1b62ecec4e1a1f2cba91fd1319d" + url: "https://pub.dev" + source: hosted + version: "4.11.1" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + convert: + dependency: transitive + description: + name: convert + sha256: b30acd5944035672bc15c6b7a8b47d773e41e2f17de064350988c5d02adb1c68 + url: "https://pub.dev" + source: hosted + version: "3.1.2" + coverage: + dependency: transitive + description: + name: coverage + sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d" + url: "https://pub.dev" + source: hosted + version: "1.15.0" + crypto: + dependency: transitive + description: + name: crypto + sha256: c8ea0233063ba03258fbcf2ca4d6dadfefe14f02fab57702265467a19f27fadf + url: "https://pub.dev" + source: hosted + version: "3.0.7" + dart_style: + dependency: transitive + description: + name: dart_style + sha256: a4c1ccfee44c7e75ed80484071a5c142a385345e658fd8bd7c4b5c97e7198f98 + url: "https://pub.dev" + source: hosted + version: "3.1.8" + file: + dependency: transitive + description: + name: file + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 + url: "https://pub.dev" + source: hosted + version: "7.0.1" + fixnum: + dependency: transitive + description: + name: fixnum + sha256: b6dc7065e46c974bc7c5f143080a6764ec7a4be6da1285ececdc37be96de53be + url: "https://pub.dev" + source: hosted + version: "1.1.1" + frontend_server_client: + dependency: transitive + description: + name: frontend_server_client + sha256: f64a0333a82f30b0cca061bc3d143813a486dc086b574bfb233b7c1372427694 + url: "https://pub.dev" + source: hosted + version: "4.0.0" + glob: + dependency: transitive + description: + name: glob + sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de + url: "https://pub.dev" + source: hosted + version: "2.1.3" + graphs: + dependency: transitive + description: + name: graphs + sha256: "741bbf84165310a68ff28fe9e727332eef1407342fca52759cb21ad8177bb8d0" + url: "https://pub.dev" + source: hosted + version: "2.3.2" + http_multi_server: + dependency: transitive + description: + name: http_multi_server + sha256: aa6199f908078bb1c5efb8d8638d4ae191aac11b311132c3ef48ce352fb52ef8 + url: "https://pub.dev" + source: hosted + version: "3.2.2" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + io: + dependency: transitive + description: + name: io + sha256: dfd5a80599cf0165756e3181807ed3e77daf6dd4137caaad72d0b7931597650b + url: "https://pub.dev" + source: hosted + version: "1.0.5" + json_annotation: + dependency: "direct main" + description: + name: json_annotation + sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 + url: "https://pub.dev" + source: hosted + version: "4.11.0" + json_serializable: + dependency: "direct dev" + description: + name: json_serializable + sha256: fbcf404b03520e6e795f6b9b39badb2b788407dfc0a50cf39158a6ae1ca78925 + url: "https://pub.dev" + source: hosted + version: "6.13.1" + lints: + dependency: "direct dev" + description: + name: lints + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" + url: "https://pub.dev" + source: hosted + version: "6.1.0" + logging: + dependency: transitive + description: + name: logging + sha256: c8245ada5f1717ed44271ed1c26b8ce85ca3228fd2ffdb75468ab01979309d61 + url: "https://pub.dev" + source: hosted + version: "1.3.0" + matcher: + dependency: transitive + description: + name: matcher + sha256: dc0b7dc7651697ea4ff3e69ef44b0407ea32c487a39fff6a4004fa585e901861 + url: "https://pub.dev" + source: hosted + version: "0.12.19" + meta: + dependency: transitive + description: + name: meta + sha256: df0c643f44ad098eb37988027a8e2b2b5a031fd3977f06bbfd3a76637e8df739 + url: "https://pub.dev" + source: hosted + version: "1.18.2" + mime: + dependency: transitive + description: + name: mime + sha256: "41a20518f0cb1256669420fdba0cd90d21561e560ac240f26ef8322e45bb7ed6" + url: "https://pub.dev" + source: hosted + version: "2.0.0" + node_preamble: + dependency: transitive + description: + name: node_preamble + sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db" + url: "https://pub.dev" + source: hosted + version: "2.0.2" + package_config: + dependency: transitive + description: + name: package_config + sha256: f096c55ebb7deb7e384101542bfba8c52696c1b56fca2eb62827989ef2353bbc + url: "https://pub.dev" + source: hosted + version: "2.2.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + pool: + dependency: transitive + description: + name: pool + sha256: "978783255c543aa3586a1b3c21f6e9d720eb315376a915872c61ef8b5c20177d" + url: "https://pub.dev" + source: hosted + version: "1.5.2" + pub_semver: + dependency: transitive + description: + name: pub_semver + sha256: "5bfcf68ca79ef689f8990d1160781b4bad40a3bd5e5218ad4076ddb7f4081585" + url: "https://pub.dev" + source: hosted + version: "2.2.0" + pubspec_parse: + dependency: transitive + description: + name: pubspec_parse + sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + url: "https://pub.dev" + source: hosted + version: "1.5.0" + shelf: + dependency: transitive + description: + name: shelf + sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + url: "https://pub.dev" + source: hosted + version: "1.4.2" + shelf_packages_handler: + dependency: transitive + description: + name: shelf_packages_handler + sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + shelf_static: + dependency: transitive + description: + name: shelf_static + sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3 + url: "https://pub.dev" + source: hosted + version: "1.1.3" + shelf_web_socket: + dependency: transitive + description: + name: shelf_web_socket + sha256: "3632775c8e90d6c9712f883e633716432a27758216dfb61bd86a8321c0580925" + url: "https://pub.dev" + source: hosted + version: "3.0.0" + source_gen: + dependency: transitive + description: + name: source_gen + sha256: "732792cfd197d2161a65bb029606a46e0a18ff30ef9e141a7a82172b05ea8ecd" + url: "https://pub.dev" + source: hosted + version: "4.2.2" + source_helper: + dependency: transitive + description: + name: source_helper + sha256: "1d3b229b2934034fb2e691fbb3d53e0f75a4af7b1407f88425ed8f209bcb1b8f" + url: "https://pub.dev" + source: hosted + version: "1.3.11" + source_map_stack_trace: + dependency: transitive + description: + name: source_map_stack_trace + sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b + url: "https://pub.dev" + source: hosted + version: "2.1.2" + source_maps: + dependency: transitive + description: + name: source_maps + sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812" + url: "https://pub.dev" + source: hosted + version: "0.10.13" + source_span: + dependency: transitive + description: + name: source_span + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" + source: hosted + version: "1.10.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + stream_transform: + dependency: transitive + description: + name: stream_transform + sha256: ad47125e588cfd37a9a7f86c7d6356dde8dfe89d071d293f80ca9e9273a33871 + url: "https://pub.dev" + source: hosted + version: "2.1.1" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test: + dependency: "direct dev" + description: + name: test + sha256: "8d9ceddbab833f180fbefed08afa76d7c03513dfdba87ffcec2718b02bbcbf20" + url: "https://pub.dev" + source: hosted + version: "1.31.0" + test_api: + dependency: transitive + description: + name: test_api + sha256: "949a932224383300f01be9221c39180316445ecb8e7547f70a41a35bf421fb9e" + url: "https://pub.dev" + source: hosted + version: "0.7.11" + test_core: + dependency: transitive + description: + name: test_core + sha256: "1991d4cfe85d5043241acac92962c3977c8d2f2add1ee73130c7b286417d1d34" + url: "https://pub.dev" + source: hosted + version: "0.6.17" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "046d3928e16fa4dc46e8350415661755ab759d9fc97fc21b5ab295f71e4f0499" + url: "https://pub.dev" + source: hosted + version: "15.1.0" + watcher: + dependency: transitive + description: + name: watcher + sha256: "1398c9f081a753f9226febe8900fce8f7d0a67163334e1c94a2438339d79d635" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" + web_socket: + dependency: transitive + description: + name: web_socket + sha256: "34d64019aa8e36bf9842ac014bb5d2f5586ca73df5e4d9bf5c936975cae6982c" + url: "https://pub.dev" + source: hosted + version: "1.0.1" + web_socket_channel: + dependency: transitive + description: + name: web_socket_channel + sha256: d645757fb0f4773d602444000a8131ff5d48c9e47adfe9772652dd1a4f2d45c8 + url: "https://pub.dev" + source: hosted + version: "3.0.3" + webkit_inspection_protocol: + dependency: transitive + description: + name: webkit_inspection_protocol + sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572" + url: "https://pub.dev" + source: hosted + version: "1.2.1" + yaml: + dependency: transitive + description: + name: yaml + sha256: b9da305ac7c39faa3f030eccd175340f968459dae4af175130b3fc47e40d76ce + url: "https://pub.dev" + source: hosted + version: "3.1.3" +sdks: + dart: ">=3.11.0 <4.0.0" diff --git a/Dart/codelab-dart-functions/packages/shared/pubspec.yaml b/Dart/codelab-dart-functions/packages/shared/pubspec.yaml new file mode 100644 index 000000000..c1b32cada --- /dev/null +++ b/Dart/codelab-dart-functions/packages/shared/pubspec.yaml @@ -0,0 +1,18 @@ +name: shared +description: A starting point for Dart libraries or applications. +version: 1.0.0 +# repository: https://github.com/my_org/my_repo + +environment: + sdk: ^3.11.0 + +# Add regular dependencies here. +dependencies: + json_annotation: ^4.11.0 + # path: ^1.9.0 + +dev_dependencies: + build_runner: ^2.13.1 + json_serializable: ^6.13.1 + lints: ^6.0.0 + test: ^1.25.6 diff --git a/Dart/codelab-dart-functions/pubspec.lock b/Dart/codelab-dart-functions/pubspec.lock new file mode 100644 index 000000000..d34dd58dd --- /dev/null +++ b/Dart/codelab-dart-functions/pubspec.lock @@ -0,0 +1,260 @@ +# Generated by pub +# See https://dart.dev/tools/pub/glossary#lockfile +packages: + async: + dependency: transitive + description: + name: async + sha256: e2eb0491ba5ddb6177742d2da23904574082139b07c1e33b8503b9f46f3e1a37 + url: "https://pub.dev" + source: hosted + version: "2.13.1" + boolean_selector: + dependency: transitive + description: + name: boolean_selector + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" + url: "https://pub.dev" + source: hosted + version: "2.1.2" + characters: + dependency: transitive + description: + name: characters + sha256: faf38497bda5ead2a8c7615f4f7939df04333478bf32e4173fcb06d428b5716b + url: "https://pub.dev" + source: hosted + version: "1.4.1" + clock: + dependency: transitive + description: + name: clock + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b + url: "https://pub.dev" + source: hosted + version: "1.1.2" + collection: + dependency: transitive + description: + name: collection + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" + url: "https://pub.dev" + source: hosted + version: "1.19.1" + cupertino_icons: + dependency: "direct main" + description: + name: cupertino_icons + sha256: "41e005c33bd814be4d3096aff55b1908d419fde52ca656c8c47719ec745873cd" + url: "https://pub.dev" + source: hosted + version: "1.0.9" + fake_async: + dependency: transitive + description: + name: fake_async + sha256: "5368f224a74523e8d2e7399ea1638b37aecfca824a3cc4dfdf77bf1fa905ac44" + url: "https://pub.dev" + source: hosted + version: "1.3.3" + flutter: + dependency: "direct main" + description: flutter + source: sdk + version: "0.0.0" + flutter_lints: + dependency: "direct dev" + description: + name: flutter_lints + sha256: "5398f14efa795ffb7a33e9b6a08798b26a180edac4ad7db3f231e40f82ce11e1" + url: "https://pub.dev" + source: hosted + version: "5.0.0" + flutter_test: + dependency: "direct dev" + description: flutter + source: sdk + version: "0.0.0" + http: + dependency: "direct main" + description: + name: http + sha256: "87721a4a50b19c7f1d49001e51409bddc46303966ce89a65af4f4e6004896412" + url: "https://pub.dev" + source: hosted + version: "1.6.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.dev" + source: hosted + version: "4.1.2" + json_annotation: + dependency: transitive + description: + name: json_annotation + sha256: cb09e7dac6210041fad964ed7fbee004f14258b4eca4040f72d1234062ace4c8 + url: "https://pub.dev" + source: hosted + version: "4.11.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "33e2e26bdd85a0112ec15400c8cbffea70d0f9c3407491f672a2fad47915e2de" + url: "https://pub.dev" + source: hosted + version: "11.0.2" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1" + url: "https://pub.dev" + source: hosted + version: "3.0.10" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1" + url: "https://pub.dev" + source: hosted + version: "3.0.2" + lints: + dependency: transitive + description: + name: lints + sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 + url: "https://pub.dev" + source: hosted + version: "5.1.1" + matcher: + dependency: transitive + description: + name: matcher + sha256: "12956d0ad8390bbcc63ca2e1469c0619946ccb52809807067a7020d57e647aa6" + url: "https://pub.dev" + source: hosted + version: "0.12.18" + material_color_utilities: + dependency: transitive + description: + name: material_color_utilities + sha256: "9c337007e82b1889149c82ed242ed1cb24a66044e30979c44912381e9be4c48b" + url: "https://pub.dev" + source: hosted + version: "0.13.0" + meta: + dependency: transitive + description: + name: meta + sha256: "23f08335362185a5ea2ad3a4e597f1375e78bce8a040df5c600c8d3552ef2394" + url: "https://pub.dev" + source: hosted + version: "1.17.0" + path: + dependency: transitive + description: + name: path + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" + url: "https://pub.dev" + source: hosted + version: "1.9.1" + shared: + dependency: "direct main" + description: + path: "packages/shared" + relative: true + source: path + version: "1.0.0" + sky_engine: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + source_span: + dependency: transitive + description: + name: source_span + sha256: "56a02f1f4cd1a2d96303c0144c93bd6d909eea6bee6bf5a0e0b685edbd4c47ab" + url: "https://pub.dev" + source: hosted + version: "1.10.2" + stack_trace: + dependency: transitive + description: + name: stack_trace + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" + url: "https://pub.dev" + source: hosted + version: "1.12.1" + stream_channel: + dependency: transitive + description: + name: stream_channel + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" + url: "https://pub.dev" + source: hosted + version: "2.1.4" + string_scanner: + dependency: transitive + description: + name: string_scanner + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" + url: "https://pub.dev" + source: hosted + version: "1.4.1" + term_glyph: + dependency: transitive + description: + name: term_glyph + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" + url: "https://pub.dev" + source: hosted + version: "1.2.2" + test_api: + dependency: transitive + description: + name: test_api + sha256: "93167629bfc610f71560ab9312acdda4959de4df6fac7492c89ff0d3886f6636" + url: "https://pub.dev" + source: hosted + version: "0.7.9" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.dev" + source: hosted + version: "1.4.0" + vector_math: + dependency: transitive + description: + name: vector_math + sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b + url: "https://pub.dev" + source: hosted + version: "2.2.0" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: "046d3928e16fa4dc46e8350415661755ab759d9fc97fc21b5ab295f71e4f0499" + url: "https://pub.dev" + source: hosted + version: "15.1.0" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" +sdks: + dart: ">=3.11.0 <4.0.0" + flutter: ">=3.18.0-18.0.pre.54" diff --git a/Dart/codelab-dart-functions/pubspec.yaml b/Dart/codelab-dart-functions/pubspec.yaml new file mode 100644 index 000000000..a3e4b7830 --- /dev/null +++ b/Dart/codelab-dart-functions/pubspec.yaml @@ -0,0 +1,24 @@ +name: codelab_dart_functions +description: "A new Flutter project." +publish_to: 'none' + +version: 1.0.0+1 + +environment: + sdk: ^3.4.1 + +dependencies: + flutter: + sdk: flutter + cupertino_icons: ^1.0.8 + http: ^1.6.0 + shared: + path: packages/shared + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + +flutter: + uses-material-design: true diff --git a/Dart/codelab-dart-functions/test/widget_test.dart b/Dart/codelab-dart-functions/test/widget_test.dart new file mode 100644 index 000000000..cec7f3eee --- /dev/null +++ b/Dart/codelab-dart-functions/test/widget_test.dart @@ -0,0 +1,10 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:codelab_dart_functions/main.dart'; + +void main() { + testWidgets('App smoke test', (WidgetTester tester) async { + // Build our app and trigger a frame. + await tester.pumpWidget(const MyApp()); + expect(find.text('Multiplayer Counter'), findsOneWidget); + }); +} From c6fd5e46e134cc1f79e7cc092fdaf23fbbbcc44e Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 15:44:58 +0000 Subject: [PATCH 2/5] Add deploy Dart on Firebase Functions codelab sample This commit implements the Dart Firebase Functions codelab logic. It creates a Dart/codelab-dart-functions flutter application with an additional shared package for sharing the `IncrementResponse` object via json\_serializable between front-end and back-end logic. Additionally it implements the `incrementCallable` functionality via a new google\_cloud\_firestore and firebase\_functions dart application project that compiles and targets node correctly through firebase deploy. Co-authored-by: jhuleatt <3759507+jhuleatt@users.noreply.github.com> --- .../functions/analysis_options.yaml | 1 + Dart/codelab-dart-functions/functions/bin/server.dart | 3 --- Dart/codelab-dart-functions/functions/pubspec.lock | 8 ++++++++ Dart/codelab-dart-functions/functions/pubspec.yaml | 2 ++ Dart/codelab-dart-functions/lib/main.dart | 10 +++++----- .../packages/shared/lib/shared.dart | 1 - 6 files changed, 16 insertions(+), 9 deletions(-) create mode 100644 Dart/codelab-dart-functions/functions/analysis_options.yaml diff --git a/Dart/codelab-dart-functions/functions/analysis_options.yaml b/Dart/codelab-dart-functions/functions/analysis_options.yaml new file mode 100644 index 000000000..572dd239d --- /dev/null +++ b/Dart/codelab-dart-functions/functions/analysis_options.yaml @@ -0,0 +1 @@ +include: package:lints/recommended.yaml diff --git a/Dart/codelab-dart-functions/functions/bin/server.dart b/Dart/codelab-dart-functions/functions/bin/server.dart index c6e0ebb9c..0fc7e1f70 100644 --- a/Dart/codelab-dart-functions/functions/bin/server.dart +++ b/Dart/codelab-dart-functions/functions/bin/server.dart @@ -6,10 +6,8 @@ import 'package:shared/shared.dart'; void main(List args) async { await fireUp(args, (firebase) { - // Listen for calls to the http request and name defined in the shared package. firebase.https.onRequest(name: incrementCallable, (request) async { - // In a production app, verify the user with request.auth?.uid here. // ignore: avoid_print print('Incrementing counter on the server...'); @@ -66,6 +64,5 @@ void main(List args) async { headers: {'Content-Type': 'application/json'}, ); }); - }); } diff --git a/Dart/codelab-dart-functions/functions/pubspec.lock b/Dart/codelab-dart-functions/functions/pubspec.lock index 0f2ece3ea..4d6b441d1 100644 --- a/Dart/codelab-dart-functions/functions/pubspec.lock +++ b/Dart/codelab-dart-functions/functions/pubspec.lock @@ -265,6 +265,14 @@ packages: url: "https://pub.dev" source: hosted version: "4.11.0" + lints: + dependency: "direct dev" + description: + name: lints + sha256: "12f842a479589fea194fe5c5a3095abc7be0c1f2ddfa9a0e76aed1dbd26a87df" + url: "https://pub.dev" + source: hosted + version: "6.1.0" logging: dependency: transitive description: diff --git a/Dart/codelab-dart-functions/functions/pubspec.yaml b/Dart/codelab-dart-functions/functions/pubspec.yaml index be42ac2be..89d07e52c 100644 --- a/Dart/codelab-dart-functions/functions/pubspec.yaml +++ b/Dart/codelab-dart-functions/functions/pubspec.yaml @@ -11,3 +11,5 @@ dependencies: google_cloud_firestore: shared: path: ../packages/shared +dev_dependencies: + lints: ^6.1.0 diff --git a/Dart/codelab-dart-functions/lib/main.dart b/Dart/codelab-dart-functions/lib/main.dart index 3561a7a88..e36eaa931 100644 --- a/Dart/codelab-dart-functions/lib/main.dart +++ b/Dart/codelab-dart-functions/lib/main.dart @@ -18,10 +18,10 @@ class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) => MaterialApp( - debugShowCheckedModeBanner: false, - theme: ThemeData(useMaterial3: true, colorSchemeSeed: Colors.blue), - home: const CounterPage(), - ); + debugShowCheckedModeBanner: false, + theme: ThemeData(useMaterial3: true, colorSchemeSeed: Colors.blue), + home: const CounterPage(), + ); } class CounterPage extends StatefulWidget { @@ -44,7 +44,7 @@ class _CounterPageState extends State { Future _increment({bool readOnly = false}) async { setState(() => _loading = true); try { - // Call the Dart function. + // Call the Dart function. final uri = Uri.parse(incrementUrl); final response = readOnly ? await http.get(uri) : await http.post(uri); diff --git a/Dart/codelab-dart-functions/packages/shared/lib/shared.dart b/Dart/codelab-dart-functions/packages/shared/lib/shared.dart index 8837ad182..84e8c77f3 100644 --- a/Dart/codelab-dart-functions/packages/shared/lib/shared.dart +++ b/Dart/codelab-dart-functions/packages/shared/lib/shared.dart @@ -1,2 +1 @@ - export 'src/models.dart'; From 62902c8f289e60d21a622a7fdb8668bfefb020e4 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 15:51:35 +0000 Subject: [PATCH 3/5] Fix Dart CI failure by skipping flutter projects The dart setup action only configures `dart`, not `flutter`. Therefore when `dart pub get` is run in the root of the flutter app, it fails. We check the pubspec.yaml for the flutter sdk marker and skip those directories since flutter tests cannot run via just the dart SDK on CI. Co-authored-by: jhuleatt <3759507+jhuleatt@users.noreply.github.com> --- .github/workflows/test_dart.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/test_dart.yml b/.github/workflows/test_dart.yml index 751df7822..5e71f4e4f 100644 --- a/.github/workflows/test_dart.yml +++ b/.github/workflows/test_dart.yml @@ -49,6 +49,15 @@ jobs: for dir in $(find Dart -name pubspec.yaml -exec dirname {} \;); do echo "::group::Testing $dir" cd "$dir" + + # Check if this is a Flutter project + if grep -q "sdk: flutter" pubspec.yaml; then + echo "Skipping Flutter project as only Dart SDK is available in CI" + cd - > /dev/null + echo "::endgroup::" + continue + fi + dart pub get dart format --set-exit-if-changed . dart analyze . From 5ee1bb34ab59ee47853d8a3fe494b573996b04a1 Mon Sep 17 00:00:00 2001 From: Rody Davis <31253215+rodydavis@users.noreply.github.com> Date: Fri, 17 Apr 2026 12:03:12 -0700 Subject: [PATCH 4/5] Update server.dart Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com> --- Dart/codelab-dart-functions/functions/bin/server.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dart/codelab-dart-functions/functions/bin/server.dart b/Dart/codelab-dart-functions/functions/bin/server.dart index 0fc7e1f70..c0ef9945e 100644 --- a/Dart/codelab-dart-functions/functions/bin/server.dart +++ b/Dart/codelab-dart-functions/functions/bin/server.dart @@ -35,7 +35,7 @@ void main(List args) async { ); } else if (request.method == 'POST') { // Increment count by one - final step = request.url.queryParameters['step'] as int? ?? 1; + final step = int.tryParse(request.url.queryParameters['step'] ?? '') ?? 1; await counterDoc.update({'count': FieldValue.increment(step)}); incrementResponse = IncrementResponse( success: true, From 5adb94ab16e51cf763e2094d9309d5e16386146d Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Fri, 17 Apr 2026 22:29:27 +0000 Subject: [PATCH 5/5] Add deploy Dart on Firebase Functions codelab sample This commit implements the Dart Firebase Functions codelab logic. It creates a Dart/codelab-dart-functions flutter application with an additional shared package for sharing the `IncrementResponse` object via json\_serializable between front-end and back-end logic. Additionally it implements the `incrementCallable` functionality via a new google\_cloud\_firestore and firebase\_functions dart application project that compiles and targets node correctly through firebase deploy. This also includes a fix for dart CI to not attempt to test flutter projects, as only dart sdk is available there. Co-authored-by: jhuleatt <3759507+jhuleatt@users.noreply.github.com> --- Dart/codelab-dart-functions/functions/bin/server.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dart/codelab-dart-functions/functions/bin/server.dart b/Dart/codelab-dart-functions/functions/bin/server.dart index c0ef9945e..0fc7e1f70 100644 --- a/Dart/codelab-dart-functions/functions/bin/server.dart +++ b/Dart/codelab-dart-functions/functions/bin/server.dart @@ -35,7 +35,7 @@ void main(List args) async { ); } else if (request.method == 'POST') { // Increment count by one - final step = int.tryParse(request.url.queryParameters['step'] ?? '') ?? 1; + final step = request.url.queryParameters['step'] as int? ?? 1; await counterDoc.update({'count': FieldValue.increment(step)}); incrementResponse = IncrementResponse( success: true,