Documentation Index Fetch the complete documentation index at: https://mintlify.com/cloudflare/workerd/llms.txt
Use this file to discover all available pages before exploring further.
The API layer provides JavaScript runtime APIs to worker code. These implementations bridge Web Standards, Node.js compatibility, and Cloudflare-specific features.
Overview
The API layer is located in src/workerd/api/ and contains:
Core Web APIs (HTTP, streams, crypto, encoding)
Node.js compatibility layer
Cloudflare-specific APIs
TypeScript type definitions
Directory structure
src/workerd/api/
├── crypto/ # Web Crypto API
├── streams/ # Streams API (842-line README)
├── node/ # Node.js compatibility (C++)
├── tests/ # Runtime API tests
└── *.{h,c++} # Core API implementations
src/node/ # Node.js compatibility (TypeScript)
src/cloudflare/ # Cloudflare-specific APIs (TypeScript)
Core API patterns
Basic API structure
Most APIs follow this pattern:
// my-api.h
#pragma once
#include <workerd/jsg/jsg.h>
namespace workerd :: api {
class MyAPI : public jsg :: Object {
public:
// Constructor
static jsg :: Ref < MyAPI > constructor ( jsg :: Lock & js );
// Methods
kj :: String doSomething ();
jsg :: Promise < int > doAsync ( jsg :: Lock & js );
// Properties
kj :: String getName () { return name; }
void setName ( kj :: String newName ) { name = kj :: mv (newName); }
JSG_RESOURCE_TYPE ( MyAPI ) {
JSG_METHOD (constructor);
JSG_METHOD (doSomething);
JSG_METHOD (doAsync);
JSG_PROTOTYPE_PROPERTY (name, getName, setName);
}
void visitForGc ( jsg :: GcVisitor & visitor ) {
// Visit any GC-tracked fields
}
private:
kj ::String name;
};
} // namespace workerd::api
Implementation file
// my-api.c++
#include "my-api.h"
namespace workerd :: api {
jsg :: Ref < MyAPI > MyAPI :: constructor ( jsg :: Lock & js ) {
return jsg :: alloc < MyAPI >();
}
kj :: String MyAPI :: doSomething () {
return kj :: str ( "result" );
}
jsg :: Promise < int > MyAPI :: doAsync ( jsg :: Lock & js ) {
auto & context = IoContext :: current ();
auto promise = context . someAsyncOperation ();
return context . awaitIo (js, kj :: mv (promise),
[]( jsg :: Lock & js , Result result ) {
return processResult (result);
});
}
} // namespace workerd::api
HTTP APIs
Request and Response
class Request : public jsg :: Object {
static jsg :: Ref < Request > constructor (
jsg :: Lock & js ,
kj :: String url ,
jsg :: Optional < RequestInit > init );
// Properties
kj :: String getUrl () { return url; }
kj :: String getMethod () { return method; }
jsg :: Ref < Headers > getHeaders () { return headers; }
// Body methods
jsg :: Promise < kj :: String > getText ( jsg :: Lock & js );
jsg :: Promise < jsg :: JsValue > getJson ( jsg :: Lock & js );
jsg :: Promise < kj :: Array < byte >> getArrayBuffer ( jsg :: Lock & js );
JSG_RESOURCE_TYPE ( Request ) {
JSG_METHOD (constructor);
JSG_READONLY_PROTOTYPE_PROPERTY (url, getUrl);
JSG_READONLY_PROTOTYPE_PROPERTY (method, getMethod);
JSG_READONLY_PROTOTYPE_PROPERTY (headers, getHeaders);
JSG_METHOD_NAMED (text, getText);
JSG_METHOD_NAMED (json, getJson);
JSG_METHOD_NAMED (arrayBuffer, getArrayBuffer);
}
};
fetch() implementation
jsg :: Promise < jsg :: Ref < Response >> fetch (
jsg :: Lock & js ,
kj :: OneOf < jsg :: Ref < Request >, kj :: String > requestOrUrl ,
jsg :: Optional < RequestInit > init ) {
// Parse request
auto request = parseRequest (requestOrUrl, init);
// Get HTTP client from IoContext
auto & context = IoContext :: current ();
auto & client = context . getHttpClient ();
// Make request
auto promise = client . request (
request . method ,
request . url ,
request . headers ,
kj :: mv ( request . body ));
// Bridge to JavaScript
return context . awaitIo (js, kj :: mv (promise),
[]( jsg :: Lock & js , HttpResponse response ) {
return jsg :: alloc < Response >( kj :: mv (response));
});
}
Streams API
The streams implementation is complex. See src/workerd/api/streams/README.md for details.
Key classes:
class ReadableStream : public jsg :: Object {
// Standard stream interface
jsg :: Ref < ReadableStreamDefaultReader > getReader ();
jsg :: Promise < void > cancel ( jsg :: Lock & js , jsg :: Optional < jsg :: JsValue > reason );
// Internal implementation
class Impl ;
};
class WritableStream : public jsg :: Object {
jsg :: Ref < WritableStreamDefaultWriter > getWriter ();
jsg :: Promise < void > abort ( jsg :: Lock & js , jsg :: Optional < jsg :: JsValue > reason );
};
class TransformStream : public jsg :: Object {
jsg :: Ref < ReadableStream > getReadable ();
jsg :: Ref < WritableStream > getWritable ();
};
Crypto API
Implemented in src/workerd/api/crypto/:
class SubtleCrypto : public jsg :: Object {
jsg :: Promise < kj :: Array < byte >> digest (
jsg :: Lock & js ,
kj :: String algorithm ,
jsg :: BufferSource data );
jsg :: Promise < jsg :: Ref < CryptoKey >> generateKey (
jsg :: Lock & js ,
KeyAlgorithm algorithm ,
bool extractable ,
kj :: Array < kj :: String > keyUsages );
jsg :: Promise < kj :: Array < byte >> encrypt (
jsg :: Lock & js ,
EncryptAlgorithm algorithm ,
jsg :: Ref < CryptoKey > key ,
jsg :: BufferSource data );
JSG_RESOURCE_TYPE ( SubtleCrypto ) {
JSG_METHOD (digest);
JSG_METHOD (generateKey);
JSG_METHOD (encrypt);
// ...
}
};
Node.js compatibility
The Node.js compatibility layer has two parts:
C++ layer (src/workerd/api/node/)
Native modules implemented in C++:
namespace workerd :: api :: node {
class CryptoImpl : public jsg :: Object {
// Node.js crypto implementations
kj :: Array < byte > randomBytes ( int size );
void randomFill ( jsg :: BufferSource buffer );
JSG_RESOURCE_TYPE ( CryptoImpl ) {
JSG_METHOD (randomBytes);
JSG_METHOD (randomFill);
}
};
} // namespace workerd::api::node
Register in src/workerd/api/node/node.h:
#define NODEJS_MODULES ( V ) \
V (buffer) \
V (crypto) \
V (util) \
// ...
TypeScript layer (src/node/)
JavaScript/TypeScript implementations:
// src/node/buffer.ts
import { BufferImpl } from 'node-internal:buffer' ;
export class Buffer extends Uint8Array {
static from ( value : any ) : Buffer {
return BufferImpl . from ( value );
}
static alloc ( size : number ) : Buffer {
return BufferImpl . alloc ( size );
}
}
Module types:
BUILTIN - Runtime modules (node:*, cloudflare:*)
INTERNAL - Only importable by builtins (node-internal:*)
BUNDLE - User code
Cloudflare-specific APIs
Implemented in src/cloudflare/:
// src/cloudflare/workers-types.ts
export interface Fetcher {
fetch ( request : Request | string ) : Promise < Response >;
}
export interface DurableObjectStub {
fetch ( request : Request | string ) : Promise < Response >;
id : DurableObjectId ;
}
export interface DurableObjectStorage {
get < T = unknown >( key : string ) : Promise < T | undefined >;
put < T = unknown >( key : string , value : T ) : Promise < void >;
delete ( key : string ) : Promise < boolean >;
list < T = unknown >( options ?: ListOptions ) : Promise < Map < string , T >>;
}
TypeScript definitions
Generated from C++ using JSG RTTI system:
class Response : public jsg :: Object {
JSG_RESOURCE_TYPE ( Response ) {
JSG_TS_ROOT (); // Mark as root for generation
JSG_TS_OVERRIDE (type Response = {
json < T = any >(): Promise < T > ;
});
JSG_METHOD (constructor);
// ...
}
};
Generate types:
Output: types/defines/
Compatibility flags
Conditionally enable features:
JSG_RESOURCE_TYPE (MyAPI, CompatibilityFlags ::Reader flags) {
JSG_METHOD (standardMethod);
if ( flags . getExperimentalFeature ()) {
JSG_METHOD (experimentalMethod);
}
}
Flags defined in src/workerd/io/compatibility-date.capnp:
struct CompatibilityFlags @0x... {
experimentalFeature @0 :Bool;
# Enabled by default on 2024-01-15
}
Testing APIs
Test in .wd-test files:
# my-api-test.wd-test
using Workerd = import "/workerd/workerd.capnp";
const unitTests :Workerd.Config = (
services = [(
name = "my-api-test",
worker = (
modules = [(name = "worker", esModule = embed "my-api-test.js")],
compatibilityDate = "2024-01-01",
),
)],
);
// my-api-test.js
import { strictEqual } from 'node:assert' ;
export default {
async test () {
const api = new MyAPI ();
const result = api . doSomething ();
strictEqual ( result , 'expected' );
}
} ;
Best practices
Follow Web Standards
The project has a high bar for non-standard APIs. Prefer implementing existing standards.
// GOOD: Implement standard API
class TextEncoder : public jsg :: Object {
// Match MDN/WHATWG specification
};
// AVOID: Custom non-standard API
class CustomEncoder : public jsg :: Object {
// Cloudflare-specific behavior
};
Handle errors correctly
// GOOD: Use appropriate error types
JSG_REQUIRE (value > 0 , RangeError, "Value must be positive" );
JSG_REQUIRE (key != nullptr , TypeError, "Key must be a string" );
JSG_FAIL_REQUIRE (DOMInvalidStateError, "Cannot read after closed" );
// BAD: Generic error
JSG_REQUIRE (condition, Error, "Something went wrong" );
Document behavior
class MyAPI : public jsg :: Object {
// Processes the input data and returns the result.
// Throws TypeError if data is not a string or ArrayBuffer.
// Throws RangeError if data exceeds maximum size.
jsg :: Promise < kj :: Array < byte >> process (
jsg :: Lock & js ,
kj :: OneOf < kj :: String , kj :: Array < byte >> data );
};
Use appropriate types
// GOOD: Union type for flexible input
void send ( kj :: OneOf < kj :: String , kj :: Array < byte >> data );
// GOOD: Optional parameter
void fetch ( kj :: String url , jsg :: Optional < FetchOptions > options );
// GOOD: Return promise for async
jsg :: Promise < Response > fetchAsync ( jsg :: Lock & js , kj :: String url );
Adding a new API
Discuss first - File an issue or discussion before coding
Choose location - api/ for standard APIs, api/node/ for Node.js
Implement - Follow patterns from existing APIs
Add tests - Create .wd-test file with test cases
Update docs - Add TypeScript definitions if needed
Register - Add to module registry or global scope
See docs/api-updates.md for detailed guidelines.
Next steps
Contributing overview Review contribution guidelines
Code style Learn about code style requirements