Dart Function Dependencies
Declare pub.dev packages your Dart Function needs via pubspec.yaml. Koolbase resolves dependencies at deploy time, caches the result, and runs your Function against the resolved package environment.
Why this exists
Production Dart Functions need access to real cryptography, HTTP clients, JWT libraries, payment SDKs, webhook signature verifiers, and other ecosystem packages. Koolbase supports per-function dependency declaration so you can use any pub.dev package — not just dart:* core libraries.
Each function version locks in its resolved dependency set. Redeploying with a different pubspec.yaml creates a new function version with its own dependency context. Existing versions continue running against the dependencies they were deployed with.
Declaring dependencies
Send a pubspec field alongside your function code at deploy time. The minimum shape requires name and environment.sdk:
name: my_function
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
crypto: ^3.0.0
cryptography: ^2.7.0
http: ^1.0.0Required fields
name— any valid pub.dev package name; doesn't need to match the function nameenvironment.sdk— Dart SDK constraint;'>=3.0.0 <4.0.0'is a good default
Constraints
- Maximum
pubspec.yamlsize: 64KB - Only the Dart runtime supports
pubspec.yaml— sending it with a Deno function returns 400 - Functions with no
pubspec.yamlstill work but can only usedart:*core libraries
How resolution works
On deploy, Koolbase runs dart pub get against your pubspec.yaml:
- Computes a SHA-256 hash of your
pubspec.yamlcontent - If a cached resolution exists for that hash, reuses it instantly (cache hit)
- Otherwise, runs
dart pub get, persists the resolved package set, and generatespubspec.lock(cache miss — first deploy with this pubspec takes 30–90 seconds) - Stores
pubspec.yaml,pubspec.lock, and the resolution hash on the function version
Subsequent deploys with the same dependency set are near-instant. The locked pubspec.lock guarantees the same dependency tree every time your function runs.
Failure modes
Dependency errors block deployment. Nothing partial gets persisted — if resolution fails, the function is not created and no disk state is written:
pubspec invalid YAMLMalformed YAML syntax
pubspec missing required field: nameNo `name` field declared
pubspec missing required field: environment.sdkNo SDK constraint declared
pubspec resolution failed: ...A package version conflict, unavailable package, or SDK incompatibility. The exact `dart pub get` error appears in the response body.
pubspec resolution timed out (3 min)Dependency resolution took longer than 3 minutes — usually means deep version conflicts or registry slowness
pubspec exceeds 64KB limitYour pubspec.yaml is too large
Example: SHA-256 hashing
Use package:crypto for SHA-256 digests:
name: hash_function
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
crypto: ^3.0.0import 'dart:convert';
import 'package:crypto/crypto.dart';
Future<Map<String, dynamic>> handler(Map<String, dynamic> ctx) async {
final body = ctx['request']['body'] as Map<String, dynamic>;
final input = body['data'] as String;
final digest = sha256.convert(utf8.encode(input));
return {
'algorithm': 'SHA-256',
'hash': digest.toString(),
};
}Example: AES-GCM encryption
Use package:cryptography for authenticated encryption:
name: encrypt_function
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
cryptography: ^2.7.0import 'dart:convert';
import 'package:cryptography/cryptography.dart';
Future<Map<String, dynamic>> handler(Map<String, dynamic> ctx) async {
final body = ctx['request']['body'] as Map<String, dynamic>;
final plaintext = body['plaintext'] as String;
final algo = AesGcm.with256bits();
final secretKey = await algo.newSecretKey();
final keyBytes = await secretKey.extractBytes();
final encrypted = await algo.encrypt(
utf8.encode(plaintext),
secretKey: secretKey,
);
return {
'algorithm': 'AES-256-GCM',
'key': base64Encode(keyBytes),
'nonce': base64Encode(encrypted.nonce),
'ciphertext': base64Encode(encrypted.cipherText),
'mac': base64Encode(encrypted.mac.bytes),
};
}Production note
Example: Webhook signature verification
A common pattern: verifying incoming webhooks (Stripe, GitHub, etc.) using HMAC-SHA256:
name: webhook_handler
environment:
sdk: '>=3.0.0 <4.0.0'
dependencies:
crypto: ^3.0.0import 'dart:convert';
import 'package:crypto/crypto.dart';
Future<Map<String, dynamic>> handler(Map<String, dynamic> ctx) async {
final request = ctx['request'] as Map<String, dynamic>;
final headers = request['headers'] as Map<String, dynamic>;
final body = request['body'] as Map<String, dynamic>;
// Webhook signing secret stored as a function secret
final env = ctx['env'] as Map<String, dynamic>;
final secret = env['WEBHOOK_SIGNING_SECRET'] as String;
// The incoming signature from the provider
final receivedSig = headers['x-webhook-signature'] as String?;
if (receivedSig == null) {
return {'verified': false, 'reason': 'missing signature'};
}
// Compute HMAC of the raw body
final hmac = Hmac(sha256, utf8.encode(secret));
final payload = jsonEncode(body);
final expectedSig = hmac.convert(utf8.encode(payload)).toString();
if (receivedSig != expectedSig) {
return {'verified': false, 'reason': 'signature mismatch'};
}
// ... process webhook event
return {'verified': true, 'event': body};
}Function versions and dependencies
Each function deploy produces a new version with its own locked dependency context:
- Function version 1 with
crypto: ^3.0.0always runs against thecryptoresolved at version 1 deploy time - Deploying version 2 with
crypto: ^3.1.0creates a new resolution; version 1 continues running against the old resolution - Triggered functions, cron functions, and retries all use the dependency context of the function version they were dispatched against
A redeploy that breaks a dependency doesn't affect functions already in flight. Existing retries finish against the version they originally fired with.
Deploying via API
The SDK deploy endpoint requires a secret key (sk_*). Publishable keys (pk_*) are restricted to client-side surfaces and cannot deploy code.
curl -X POST https://api.koolbase.com/v1/sdk/functions/deploy \
-H "Content-Type: application/json" \
-H "x-api-key: sk_test_..." \
-d '{
"runtime": "dart",
"name": "my_function",
"code": "Future<Map<String, dynamic>> handler(...) async { ... }",
"pubspec": "name: my_function\nenvironment:\n sdk: \">=3.0.0 <4.0.0\"\ndependencies:\n crypto: ^3.0.0",
"timeout_ms": 10000
}'