Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions packages/dart_firebase_admin/.firebaserc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"projects": {
"default": "dart-firebase-admin"
}
}
7 changes: 6 additions & 1 deletion packages/dart_firebase_admin/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,6 @@
service-account-key.json
service-account-key.json

# Test functions artifacts
test/functions/node_modules/
test/functions/lib/
test/functions/package-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module.exports = {
root: true,
env: {
es6: true,
node: true,
},
extends: [
"eslint:recommended",
"plugin:import/errors",
"plugin:import/warnings",
"plugin:import/typescript",
"google",
"plugin:@typescript-eslint/recommended",
],
parser: "@typescript-eslint/parser",
parserOptions: {
project: ["tsconfig.json", "tsconfig.dev.json"],
sourceType: "module",
},
ignorePatterns: [
"/lib/**/*", // Ignore built files.
"/generated/**/*", // Ignore generated files.
],
plugins: [
"@typescript-eslint",
"import",
],
rules: {
"quotes": ["error", "double"],
"import/no-unresolved": 0,
"indent": ["error", 2],
},
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Compiled JavaScript files
lib/**/*.js
lib/**/*.js.map

# TypeScript v1 declaration files
typings/

# Node.js dependency directory
node_modules/
*.local
package-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{
"name": "functions",
"scripts": {
"lint": "eslint --ext .js,.ts .",
"build": "tsc",
"build:watch": "tsc --watch",
"serve": "npm run build && firebase emulators:start --only functions",
"shell": "npm run build && firebase functions:shell",
"start": "npm run shell",
"deploy": "firebase deploy --only functions",
"logs": "firebase functions:log"
},
"engines": {
"node": "22"
},
"main": "lib/index.js",
"dependencies": {
"firebase-admin": "^12.6.0",
"firebase-functions": "^6.0.1"
},
"devDependencies": {
"@typescript-eslint/eslint-plugin": "^5.12.0",
"@typescript-eslint/parser": "^5.12.0",
"eslint": "^8.9.0",
"eslint-config-google": "^0.14.0",
"eslint-plugin-import": "^2.25.4",
"firebase-functions-test": "^3.1.0",
"typescript": "^4.9.0"
},
"private": true
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
/**
* Import function triggers from their respective submodules:
*
* import {onCall} from "firebase-functions/v2/https";
* import {onDocumentWritten} from "firebase-functions/v2/firestore";
*
* See a full list of supported triggers at https://firebase.google.com/docs/functions
*/

import {onTaskDispatched} from "firebase-functions/v2/tasks";

// Start writing functions
// https://firebase.google.com/docs/functions/typescript

export const helloWorld = onTaskDispatched(
{
retryConfig: {
maxAttempts: 5,
minBackoffSeconds: 60,
},
rateLimits: {
maxConcurrentDispatches: 6,
},
},
async (req) => {
console.log("Task received:", req.data);
}
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"include": [
".eslintrc.js"
]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
{
"compilerOptions": {
"module": "NodeNext",
"esModuleInterop": true,
"moduleResolution": "nodenext",
"noImplicitReturns": true,
"noUnusedLocals": true,
"outDir": "lib",
"sourceMap": true,
"strict": true,
"target": "es2017"
},
"compileOnSave": true,
"include": [
"src"
]
}
99 changes: 96 additions & 3 deletions packages/dart_firebase_admin/example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,23 +1,34 @@
import 'package:dart_firebase_admin/auth.dart';
import 'package:dart_firebase_admin/dart_firebase_admin.dart';
import 'package:dart_firebase_admin/firestore.dart';
import 'package:dart_firebase_admin/functions.dart';
import 'package:dart_firebase_admin/messaging.dart';

Future<void> main() async {
final admin = FirebaseApp.initializeApp();
await authExample(admin);
await firestoreExample(admin);
await projectConfigExample(admin);

// Uncomment to run auth example
// await authExample(admin);

// Uncomment to run firestore example
// await firestoreExample(admin);

// Uncomment to run project config example
// await projectConfigExample(admin);

// Uncomment to run tenant example (requires Identity Platform upgrade)
// await tenantExample(admin);

// Uncomment to run messaging example (requires valid fcm token)
// await messagingExample(admin);

// Uncomment to run functions example
// await functionsExample(admin);

await admin.close();
}

// ignore: unreachable_from_main
Future<void> authExample(FirebaseApp admin) async {
print('\n### Auth Example ###\n');

Expand Down Expand Up @@ -47,6 +58,7 @@ Future<void> authExample(FirebaseApp admin) async {
}
}

// ignore: unreachable_from_main
Future<void> firestoreExample(FirebaseApp admin) async {
print('\n### Firestore Example ###\n');

Expand All @@ -64,6 +76,7 @@ Future<void> firestoreExample(FirebaseApp admin) async {
}
}

// ignore: unreachable_from_main
Future<void> projectConfigExample(FirebaseApp admin) async {
print('\n### Project Config Example ###\n');

Expand Down Expand Up @@ -379,3 +392,83 @@ Future<void> messagingExample(FirebaseApp admin) async {
print('> Error sending platform-specific message: $e');
}
}

/// Functions example prerequisites:
/// 1) Run `npm run build` in `example_functions_ts` to generate `index.js`.
/// 2) From the example directory root (with `firebase.json` and `.firebaserc`),
/// start emulators with `firebase emulators:start`.
/// 3) Run `dart_firebase_admin/packages/dart_firebase_admin/example/run_with_emulator.sh`.
// ignore: unreachable_from_main
Future<void> functionsExample(FirebaseApp admin) async {
print('\n### Functions Example ###\n');

final functions = Functions(admin);

// Get a task queue reference
// The function name should match an existing Cloud Function or queue name
final taskQueue = functions.taskQueue('helloWorld');

// Example 1: Enqueue a simple task
try {
print('> Enqueuing a simple task...\n');
await taskQueue.enqueue({
'userId': 'user-123',
'action': 'sendWelcomeEmail',
'timestamp': DateTime.now().toIso8601String(),
});
print('Task enqueued successfully!\n');
} on FirebaseFunctionsAdminException catch (e) {
print('> Functions error: ${e.code} - ${e.message}\n');
} catch (e) {
print('> Error enqueuing task: $e\n');
}

// Example 2: Enqueue with delay (1 hour from now)
try {
print('> Enqueuing a delayed task...\n');
await taskQueue.enqueue(
{'action': 'cleanupTempFiles'},
TaskOptions(schedule: DelayDelivery(3600)), // 1 hour delay
);
print('Delayed task enqueued successfully!\n');
} on FirebaseFunctionsAdminException catch (e) {
print('> Functions error: ${e.code} - ${e.message}\n');
}

// Example 3: Enqueue at specific time
try {
print('> Enqueuing a scheduled task...\n');
final scheduledTime = DateTime.now().add(const Duration(minutes: 30));
await taskQueue.enqueue({
'action': 'sendReport',
}, TaskOptions(schedule: AbsoluteDelivery(scheduledTime)));
print('Scheduled task enqueued for: $scheduledTime\n');
} on FirebaseFunctionsAdminException catch (e) {
print('> Functions error: ${e.code} - ${e.message}\n');
}

// Example 4: Enqueue with custom task ID (for deduplication)
try {
print('> Enqueuing a task with custom ID...\n');
await taskQueue.enqueue({
'orderId': 'order-456',
'action': 'processPayment',
}, TaskOptions(id: 'payment-order-456'));
print('Task with custom ID enqueued!\n');
} on FirebaseFunctionsAdminException catch (e) {
if (e.errorCode == FunctionsClientErrorCode.taskAlreadyExists) {
print('> Task with this ID already exists (deduplication)\n');
} else {
print('> Functions error: ${e.code} - ${e.message}\n');
}
}

// Example 5: Delete a task
try {
print('> Deleting task...\n');
await taskQueue.delete('payment-order-456');
print('Task deleted successfully!\n');
} on FirebaseFunctionsAdminException catch (e) {
print('> Functions error: ${e.code} - ${e.message}\n');
}
}
1 change: 1 addition & 0 deletions packages/dart_firebase_admin/example/run_with_emulator.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# Set environment variables for emulator
export FIRESTORE_EMULATOR_HOST=localhost:8080
export FIREBASE_AUTH_EMULATOR_HOST=localhost:9099
export CLOUD_TASKS_EMULATOR_HOST=localhost:9499
export GOOGLE_CLOUD_PROJECT=dart-firebase-admin

# Run the example
Expand Down
32 changes: 32 additions & 0 deletions packages/dart_firebase_admin/firebase.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
{
"emulators": {
"auth": {
"port": 9099
},
"firestore": {
"port": 8080
},
"functions": {
"port": 5001
},
"tasks": {
"port": 9499
},
"ui": {
"enabled": true
},
"singleProjectMode": true
},
"functions": [
{
"source": "test/functions",
"codebase": "default",
"ignore": [
"node_modules",
".git",
"firebase-debug.log",
"*.local"
]
}
]
}
3 changes: 2 additions & 1 deletion packages/dart_firebase_admin/lib/dart_firebase_admin.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,5 @@ export 'src/app.dart'
EmulatorClient,
Environment,
FirebaseServiceType,
FirebaseService;
FirebaseService,
CloudTasksEmulatorClient;
1 change: 1 addition & 0 deletions packages/dart_firebase_admin/lib/functions.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'src/functions/functions.dart';
2 changes: 2 additions & 0 deletions packages/dart_firebase_admin/lib/src/app.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import 'dart:io';
import 'dart:typed_data';

import 'package:equatable/equatable.dart';
// import 'package:googleapis/cloudfunctions/v2.dart' as auth4;
import 'package:googleapis/identitytoolkit/v3.dart' as auth3;
import 'package:googleapis_auth/auth_io.dart' as googleapis_auth;
import 'package:googleapis_auth_utils/googleapis_auth_utils.dart'
Expand All @@ -16,6 +17,7 @@ import 'package:meta/meta.dart';
import '../app_check.dart';
import '../auth.dart';
import '../firestore.dart';
import '../functions.dart';
import '../messaging.dart';
import '../security_rules.dart';

Expand Down
Loading
Loading