### Shell: Volta Installation and Node.js Setup Source: https://volta.sh/ This snippet provides a sequence of shell commands to get started with Volta. It includes the command to install Volta itself, followed by using Volta to install a specific version of Node.js, and finally, a command to demonstrate starting the Node.js runtime. ```Shell # install Volta curl https://get.volta.sh | bash # install Node volta install node # start using Node node ``` -------------------------------- ### Install Next.js Frontend Dependencies Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This command installs all required Node.js packages and dependencies for the Next.js frontend application, as specified in its `package.json` file. ```Shell npm install ``` -------------------------------- ### Install Project Dependencies Source: https://github.com/craigsdennis/twilio-cloudflare-workflow This command installs all required Node.js packages for the project, as specified in the `package.json` file. It's a standard initial step for setting up any Node.js-based application. ```Shell npm install ``` -------------------------------- ### Install Project Dependencies with npm Source: https://github.com/craigsdennis/twilio-cloudflare-workflow This command installs all necessary project dependencies defined in the `package.json` file. It should be executed in the root directory of your project to prepare the environment for development or deployment. ```shell npm install ``` -------------------------------- ### Example GraphQL Query Variables (JSON) Source: https://context7_llms This JSON object provides example values for the variables used in the GraphQL queries, including `accountTag`, `datetimeStart`, `datetimeEnd`, `workflowName`, and `instanceId`. These values can be used to test or execute the provided GraphQL queries. ```json { "accountTag": "fedfa729a5b0ecfd623bca1f9000f0a22", "datetimeStart": "2024-10-20T00:00:00Z", "datetimeEnd": "2024-10-29T00:00:00Z", "workflowName": "shoppingCart", "instanceId": "ecc48200-11c4-22a3-b05f-88a3c1c1db81" } ``` -------------------------------- ### Navigate to Next.js Frontend Directory Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This command changes the current directory to `nextjs-workflow-frontend`, which is the root of the Next.js application. This is a prerequisite for installing frontend dependencies. ```Shell cd nextjs-workflow-frontend ``` -------------------------------- ### Create Cloudflare D1 Database with Wrangler Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This command initializes a new D1 database named `workflow-demo` using the Cloudflare Wrangler CLI. The output of this command should be used to update `wrangler.jsonc`. ```Shell npx wrangler d1 create workflow-demo ``` -------------------------------- ### Deploy Cloudflare Workflow with npm Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This command initiates the deployment of the Cloudflare Workflow project, likely configured via `package.json` scripts to use Wrangler. The deployment URL should be saved for frontend configuration. ```Shell npm run deploy ``` -------------------------------- ### Clone Cloudflare docs-examples Repository (No Checkout) Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This command clones the `docs-examples` Git repository from GitHub without checking out any files, which is useful for large repositories where you only need specific subdirectories. It then changes the current directory into the newly cloned repository. ```shell git clone --filter=blob:none --no-checkout https://github.com/cloudflare/docs-examples.git cd docs-examples ``` -------------------------------- ### Example Cloudflare Workflow Definition in TypeScript Source: https://context7_llms This TypeScript code defines a basic Cloudflare Workflow, `MyWorkflow`, extending `WorkflowEntrypoint`. It illustrates how to define environment variables and input parameters, and implements the `run` method with multiple asynchronous steps using `step.do`. The example showcases fetching data, making external API calls, introducing delays with `step.sleep`, and implementing a robust retry strategy with exponential backoff for potentially failing operations. ```ts import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers'; type Env = { // Add your bindings here, e.g. Workers KV, D1, Workers AI, etc. MY_WORKFLOW: Workflow; }; // User-defined params passed to your workflow type Params = { email: string; metadata: Record; }; export class MyWorkflow extends WorkflowEntrypoint { async run(event: WorkflowEvent, step: WorkflowStep) { // Can access bindings on `this.env` // Can access params on `event.payload` const files = await step.do('my first step', async () => { // Fetch a list of files from $SOME_SERVICE return { files: [ 'doc_7392_rev3.pdf', 'report_x29_final.pdf', 'memo_2024_05_12.pdf', 'file_089_update.pdf', 'proj_alpha_v2.pdf', 'data_analysis_q2.pdf', 'notes_meeting_52.pdf', 'summary_fy24_draft.pdf', ], }; }); const apiResponse = await step.do('some other step', async () => { let resp = await fetch('https://api.cloudflare.com/client/v4/ips'); return await resp.json(); }); await step.sleep('wait on something', '1 minute'); await step.do( 'make a call to write that could maybe, just might, fail', // Define a retry strategy { retries: { limit: 5, delay: '5 second', backoff: 'exponential', }, timeout: '15 minutes', }, async () => { // Do stuff here, with access to the state from our previous steps if (Math.random() > 0.5) { throw new Error('API call to $STORAGE_SYSTEM failed'); } }, ); } } ``` -------------------------------- ### Create a batch of Workflow instances (TypeScript) Source: https://context7_llms This TypeScript example demonstrates how to use the `createBatch` method to initiate multiple Workflow instances. It shows how to provide a list of instance configurations, each with a unique ID and initial parameters. ```TypeScript // Create a new batch of 3 Workflow instances, each with its own ID and pass params to the Workflow instances const listOfInstances = [ { id: "id-abc123", params: { "hello": "world-0" } }, { id: "id-def456", params: { "hello": "world-1" } }, { id: "id-ghi789", params: { "hello": "world-2" } } ]; let instances = await env.MY_WORKFLOW.createBatch(listOfInstances); ``` -------------------------------- ### Create Granular Workflow Steps in TypeScript (Good Example) Source: https://context7_llms This TypeScript example illustrates the best practice of making workflow steps granular and self-contained. By separating unrelated API calls into individual `step.do` operations, the workflow becomes more durable against failures in third-party APIs or network errors. This approach also allows for independent retry and timeout policies for each distinct operation. ```TypeScript export class MyWorkflow extends WorkflowEntrypoint { async run(event: WorkflowEvent, step: WorkflowStep) { // ✅ Good: Unrelated API/Binding calls are self-contained, so that in case one of them fails // it can retry them individually. It also has an extra advantage: you can control retry or // timeout policies for each granular step - you might not to want to overload http.cat in // case of it being down. const httpCat = await step.do("get cutest cat from KV", async () => { return await env.KV.get("cutest-http-cat"); }); const image = await step.do("fetch cat image from http.cat", async () => { return await fetch(`https://http.cat/${httpCat}`); }); } } ``` -------------------------------- ### Apply D1 Database Schema using Wrangler Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This command executes a SQL schema file (`db.sql`) against the `workflows-waitforevent-d1` D1 database remotely. It's typically run from the `/workflow` folder. ```Shell npx wrangler d1 execute workflows-waitforevent-d1 --remote --file=./db.sql ``` -------------------------------- ### Checkout Main Branch in Git Repository Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This Git command switches the current working branch to `main`. It ensures that the user is on the correct branch for subsequent deployment steps, typically the stable or primary development branch. ```shell git checkout main ``` -------------------------------- ### Deploy Application to Cloudflare Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This command initiates the deployment process for your application to Cloudflare. It executes the 'deploy' script defined in your project's `package.json`, typically handling build and upload steps. The deployment URL will be provided near the end of your terminal output. ```Shell npm run deploy ``` -------------------------------- ### Deploy Cloudflare Worker Application Source: https://github.com/craigsdennis/twilio-cloudflare-workflow This command initiates the deployment process for the Cloudflare Worker application. It typically compiles the project and uploads it to the Cloudflare global network, making it accessible via a unique URL. ```Shell npm run deploy ``` -------------------------------- ### Cloudflare Workflows: Implementing the run Method with State Return Source: https://context7_llms Example implementation of the `run` method within a `WorkflowEntrypoint` class. It demonstrates how to use `step.do` to execute workflow steps and optionally return a computed state, which can then be queried externally. ```TypeScript export class MyWorkflow extends WorkflowEntrypoint { async run(event: WorkflowEvent, step: WorkflowStep) { // Steps here let someComputedState = step.do("my step", async () => { }) // Optional: return state from our run() method return someComputedState } }; ``` -------------------------------- ### Change Directory to Workflow Folder Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This shell command navigates the terminal into the `workflow` subdirectory. This is a prerequisite step before executing commands specific to the workflow project, such as deployment or configuration. ```shell cd workflow ``` -------------------------------- ### Configure Git Sparse Checkout for Workflow Folder Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This command configures Git's sparse-checkout feature to only include the `workflows/waitForEvent` directory. This is useful for cloning large repositories while only needing specific subdirectories, reducing local repository size. ```shell git sparse-checkout set workflows/waitForEvent ``` -------------------------------- ### Fetch a Workflow instance by ID (TypeScript) Source: https://context7_llms This TypeScript example illustrates how to fetch an existing Workflow instance using its ID. It includes error handling for cases where the instance ID is invalid or does not exist, and demonstrates accessing instance details. ```TypeScript // Fetch an existing Workflow instance by ID: try { let instance = await env.MY_WORKFLOW.get(id) return Response.json({ id: instance.id, details: await instance.status(), }); } catch (e: any) { // Handle errors // .get will throw an exception if the ID doesn't exist or is invalid. const msg = `failed to get instance ${id}: ${e.message}` console.error(msg) return Response.json({error: msg}, { status: 400 }) } ``` -------------------------------- ### Upgrade to Wrangler v3 and Start Local Development Source: https://blog.cloudflare.com/wrangler3/ Instructions to upgrade your project's Wrangler CLI to version 3 and then initiate the local development server. This process leverages Miniflare v3 and the open-source Workers runtime to provide an enhanced local development experience. ```Shell npm install --save-dev wrangler@3 npx wrangler dev ``` -------------------------------- ### `get` method for Workflow instances Source: https://context7_llms API signature for retrieving a specific Workflow instance by its unique identifier. This method returns a `WorkflowInstance` object if found, or throws an exception if the ID does not exist. ```APIDOC get(id: string): Promise id: the ID of the Workflow instance. ``` -------------------------------- ### Example: Waiting for an Event in a Workflow Source: https://context7_llms Demonstrates how to use `step.waitForEvent` within a TypeScript `WorkflowEntrypoint` class to pause workflow execution until a specific event, such as an incoming Stripe webhook, is received. ```ts export class MyWorkflow extends WorkflowEntrypoint { async run(event: WorkflowEvent, step: WorkflowStep) { // Other steps in your Workflow let event = await step.waitForEvent("receive invoice paid webhook from Stripe", { type: "stripe-webhook", timeout: "1 hour" }) // Rest of your Workflow } } ``` -------------------------------- ### Enable Git Sparse Checkout Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent After cloning a repository without checking out files, this command initializes Git sparse checkout in cone mode. This allows you to selectively check out specific directories or files from the repository, improving performance and reducing local disk space usage. ```shell git sparse-checkout init --cone ``` -------------------------------- ### Avoid Non-Granular Workflow Steps in TypeScript (Bad Example) Source: https://context7_llms This TypeScript example demonstrates an anti-pattern where multiple separate service calls are combined within a single workflow step. This can lead to issues such as redundant calls to the first service if the second one fails, and can compromise the idempotency of the step. It's recommended to separate unrelated operations into distinct granular steps. ```TypeScript export class MyWorkflow extends WorkflowEntrypoint { async run(event: WorkflowEvent, step: WorkflowStep) { // ⭕️ Bad: you are calling two separate services from within the same step. This might cause // some extra calls to the first service in case the second one fails, and in some cases, makes // the step non-idempotent altogether const image = await step.do("get cutest cat from KV", async () => { const httpCat = await env.KV.get("cutest-http-cat"); return fetch(`https://http.cat/${httpCat}`); }); } } ``` -------------------------------- ### Start Cloudflare Workflows Local Development Session Source: https://context7_llms This snippet shows how to initiate a local development server for Cloudflare Workflows using `npx wrangler dev`. It provides an emulated environment for testing workflows before deployment, along with the expected console output indicating the server is ready and bindings are active. ```sh npx wrangler dev ``` ```sh ------------------ Your worker has access to the following bindings: - Workflows: - MY_WORKFLOW: MyWorkflow ⎔ Starting local server... [wrangler:inf] Ready on http://127.0.0.1:8787/ ``` -------------------------------- ### Deploy Cloudflare Workflow application using npm Source: https://github.com/craigsdennis/twilio-cloudflare-workflow This command initiates the deployment process for the Cloudflare Workflow application. It executes the 'deploy' script defined in the project's package.json, typically uploading the application to Cloudflare's infrastructure. After execution, a URL for the deployed application will be provided. ```Shell npm run deploy ``` -------------------------------- ### Minimal `package.json` for Cloudflare Worker Project Source: https://context7_llms This `package.json` file outlines the essential development and runtime dependencies for a Cloudflare Worker project. It includes `wrangler` for local development and deployment, and `mimetext` as a runtime dependency, showcasing a typical setup for a Workers application. ```JSON { "devDependencies": { "wrangler": "^3.83.0" }, "dependencies": { "mimetext": "^3.0.24" } } ``` -------------------------------- ### Manage Cloudflare Workflows with Wrangler CLI Source: https://context7_llms Provides examples of Wrangler CLI commands used to manage and inspect Workflows and their instances. This includes listing Workflows, inspecting instances by name, and viewing the detailed state of a running or completed Workflow instance. ```sh # List Workflows wrangler workflows list # Inspect the instances of a Workflow wrangler workflows instances list YOUR_WORKFLOW_NAME # View the state of a running Workflow instance by its ID wrangler workflows instances describe YOUR_WORKFLOW_NAME WORKFLOW_ID npx wrangler@latest workflows instances describe workflows-starter latest # Or by ID: # npx wrangler@latest workflows instances describe workflows-starter 12dc179f-9f77-4a37-b973-709dca4189ba ``` -------------------------------- ### Create Cloudflare Workflow Instance with Custom ID and Parameters Source: https://context7_llms This TypeScript example demonstrates how to use the `create` method of a bound `Workflow` object to initiate a new Workflow instance. It shows how to provide a custom ID and pass a JSON object as `params` to the Workflow instance. ```ts // Create a new Workflow instance with your own ID and pass params to the Workflow instance let instance = await env.MY_WORKFLOW.create({ id: myIdDefinedFromOtherSystem, params: { "hello": "world" } }) return Response.json({ id: instance.id, details: await instance.status(), }); ``` -------------------------------- ### Manage Cloudflare Workflows from a Worker Source: https://context7_llms This example demonstrates how a Cloudflare Worker can interact with Workflows. It shows how to retrieve the status of an existing Workflow instance by its ID and how to create (trigger) a new Workflow instance, returning its ID and initial status. ```TypeScript interface Env { MY_WORKFLOW: Workflow; } export default { async fetch(req: Request, env: Env) { // Get instanceId from query parameters const instanceId = new URL(req.url).searchParams.get("instanceId") // If an ?instanceId= query parameter is provided, fetch the status // of an existing Workflow by its ID. if (instanceId) { let instance = await env.MY_WORKFLOW.get(instanceId); return Response.json({ status: await instance.status(), }); } // Else, create a new instance of our Workflow, passing in any (optional) // params and return the ID. const newId = await crypto.randomUUID(); let instance = await env.MY_WORKFLOW.create({ id: newId }); return Response.json({ id: instance.id, details: await instance.status(), }); return Response.json({ result }); }, }; ``` -------------------------------- ### Check Wrangler CLI Version for Workflows Source: https://context7_llms This snippet demonstrates how to verify the installed version of Wrangler, the Cloudflare Workers command-line interface, to ensure it meets the minimum requirements (v3.89.0+) for local Workflows development. It includes both the command and its typical output. ```sh npx wrangler --version ``` ```sh ⛅️ wrangler 3.89.0 ``` -------------------------------- ### Create Cloudflare R2 Storage Bucket Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This command uses `wrangler`, the Cloudflare Workers CLI, to create a new R2 bucket named `workflow-demo-bucket`. R2 is Cloudflare's S3-compatible object storage, often used for storing assets or data for Workers applications. The output of this command might be needed to update `wrangler.jsonc`. ```shell npx wrangler r2 bucket create workflow-demo-bucket ``` -------------------------------- ### Workerd Configuration for a Cloudflare Worker Source: https://blog.cloudflare.com/wrangler3/ This Cap'n Proto configuration file (`worker.capnp`) demonstrates how to set up `workerd` to run a simple 'Hello World' Cloudflare Worker. It defines a service named 'hello-worker' and a socket 'hello-socket' listening on port 8080, routing HTTP requests to the embedded JavaScript Worker. This is the foundational setup for local Worker development with `workerd`. ```Cap'n Proto using Workerd = import "/workerd/workerd.capnp"; const helloConfig :Workerd.Config = ( services = [ ( name = "hello-worker", worker = .helloWorker ) ], sockets = [ ( name = "hello-socket", address = "*:8080", http = (), service = "hello-worker" ) ] ); const helloWorker :Workerd.Worker = ( modules = [ ( name = "worker.mjs", esModule = `export default { ` async fetch(request, env, ctx) { ` return new Response("Hello from workerd! 👋"); ` } `} ) ], compatibilityDate = "2023-04-04", ); ``` -------------------------------- ### Cloudflare Workflows: Correct State Management with Step Returns Source: https://context7_llms This example demonstrates the correct way to manage state in Cloudflare Workflows. By building top-level state exclusively from the returns of `step.do` calls, the state is persisted across multiple engine lifetimes, even after hibernation. This ensures that data remains available for subsequent steps, preventing unexpected failures. ```TypeScript function getRandomInt(min, max) { const minCeiled = Math.ceil(min); const maxFloored = Math.floor(max); return Math.floor(Math.random() * (maxFloored - minCeiled) + minCeiled); // The maximum is exclusive and the minimum is inclusive } export class MyWorkflow extends WorkflowEntrypoint { async run(event: WorkflowEvent, step: WorkflowStep) { // ✅ Good: imageList state is exclusively comprised of step returns - this means that in the event of // multiple engine lifetimes, imageList will be built accordingly const imageList: string[] = await Promise.all([ step.do("get first cutest cat from KV", async () => { return await env.KV.get("cutest-http-cat-1"); }), step.do("get second cutest cat from KV", async () => { return await env.KV.get("cutest-http-cat-2"); }), ]); // A long sleep can (and probably will) hibernate the engine which means that the first engine lifetime ends here await step.sleep("💤💤💤💤", "3 hours"); // When this runs, it will be on the second engine lifetime - but this time, imageList will contain // the two most cutest cats await step.do( "choose a random cat from the list and download it", async () => { const randomCat = imageList.at(getRandomInt(0, imageList.length)); // this will eventually succeed since `randomCat` is defined return await fetch(`https://http.cat/${randomCat}`); }, ); } } ``` -------------------------------- ### Define Cloudflare Workflow Steps in TypeScript Source: https://context7_llms This TypeScript example demonstrates how to create a Cloudflare Workflow by extending `WorkflowEntrypoint`. It shows the `run` method where individual `step.do` calls encapsulate retriable logic. Each step can optionally return state that persists across the workflow, enabling robust error handling and avoiding redundant operations. ```typescript // Import the Workflow definition import { WorkflowEntrypoint, WorkflowEvent, WorkflowStep } from "cloudflare:workers" type Params = {} // Create your own class that implements a Workflow export class MyWorkflow extends WorkflowEntrypoint { // Define a run() method async run(event: WorkflowEvent, step: WorkflowStep) { // Define one or more steps that optionally return state. let state = step.do("my first step", async () => { }) step.do("my second step", async () => { }) } } ``` -------------------------------- ### TypeScript Worker Interacting with Cloudflare Workflow Source: https://context7_llms An example TypeScript Worker script demonstrating how to import Workflow definitions, define an environment binding, and interact with a Workflow instance. It shows how to retrieve the status of an existing instance or spawn a new one based on request parameters. ```ts // Import the Workflow definition import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent} from 'cloudflare:workers'; interface Env { // Matches the binding definition in your Wrangler configuration file MY_WORKFLOW: Workflow; } export default { async fetch(req: Request, env: Env): Promise { let id = new URL(req.url).searchParams.get('instanceId'); // Get the status of an existing instance, if provided if (id) { let instance = await env.MY_WORKFLOW.get(id); return Response.json({ status: await instance.status(), }); } // Spawn a new instance and return the ID and status let instance = await env.MY_WORKFLOW.create(); return Response.json({ id: instance.id, details: await instance.status(), }); }, }; ``` -------------------------------- ### Send an event to a Workflow instance (TypeScript) Source: https://context7_llms This TypeScript example demonstrates how to send a custom event to a running Workflow instance. It fetches an instance by ID and then uses `sendEvent` to deliver a webhook payload, allowing the Workflow to progress based on the event type. ```TypeScript export default { async fetch(req: Request, env: Env) { const instanceId = new URL(req.url).searchParams.get("instanceId") const webhookPayload = await req.json() let instance = await env.MY_WORKFLOW.get(instanceId); // Send our event, with `type` matching the event type defined in // our step.waitForEvent call await instance.sendEvent({type: "stripe-webhook", payload: webhookPayload}) return Response.json({ status: await instance.status(), }); }, }; ``` -------------------------------- ### Defining and Using a Generic Class in TypeScript Source: https://www.typescriptlang.org/docs/handbook/2/generics.html This example illustrates the syntax for creating a generic class in TypeScript. Generic classes have a type parameter list following the class name, allowing properties and methods to operate on a generic type. The snippet shows how to define such a class and instantiate it with a specific type. ```ts class GenericNumber { zeroValue: NumType; add: (x: NumType, y: NumType) => NumType; } let myGenericNumber = new GenericNumber(); myGenericNumber.zeroValue = 0; myGenericNumber.add = function (x, y) { return x + y; }; ``` -------------------------------- ### Cloudflare Workflows: Correct Promise.race() Usage for Consistent Caching Source: https://context7_llms This example demonstrates the recommended way to use `Promise.race()` or `Promise.any()` within Cloudflare Workflows. By surrounding these methods with a `step.do()`, developers can ensure deterministic caching behavior and consistency across multiple workflow passages, preventing unexpected results from concurrent operations. ```TypeScript // helper sleep method const sleep = (ms: number) => new Promise((r) => setTimeout(r, ms)); export class MyWorkflow extends WorkflowEntrypoint { async run(event: WorkflowEvent, step: WorkflowStep) { // ✅ Good: The `Promise.race` is surrounded by a `step.do`, ensuring deterministic caching behavior. const race_return = await step.do( 'Promise step', async () => { return await Promise.race( [ step.do( 'Promise first race', async () => { await sleep(1000); return "first"; } ), step.do( 'Promise second race', async () => { return "second"; } ), ] ); } ); await step.sleep("Sleep step", "2 hours"); return await step.do( 'Another step', async () => { // This step will return `second` because the `Promise.race` was surround by the `step.do` method. return race_return; }, ); } } ``` -------------------------------- ### Creating Instances with Generic Class Types in TypeScript Source: https://www.typescriptlang.org/docs/handbook/2/generics.html This example illustrates how to use constructor functions as generic type parameters to create new instances of a class. The `c: { new (): Type }` syntax specifies that `c` must be a constructor that returns an instance of `Type`, enabling generic factory functions. ```typescript function create(c: { new (): Type }): Type { return new c(); } ``` -------------------------------- ### Create Workflow Instance in Cloudflare Worker via HTTP Fetch (TypeScript) Source: https://context7_llms This TypeScript example shows a Cloudflare Worker's `fetch` handler that creates a new Workflow instance for each incoming HTTP request. It uses the `env.MY_WORKFLOW.create` method to initiate the workflow, passing a payload, and then returns the instance ID and status as a JSON response. ```typescript // This is in the same file as your Workflow definition export default { async fetch(req: Request, env: Env): Promise { let instance = await env.MY_WORKFLOW.create({ params: payload }); return Response.json({ id: instance.id, details: await instance.status(), }); }, }; ``` -------------------------------- ### Create Cloudflare Workflow Instance with Typed Parameters Source: https://context7_llms This TypeScript example illustrates how to pass a custom type (e.g., `User`) as a type argument to the `Workflow` definition in the `Env` interface. This ensures type safety when providing parameters to the Workflow instance via the `create` method. ```ts interface User { email: string; createdTimestamp: number; } interface Env { // Pass our User type as the type parameter to the Workflow definition MY_WORKFLOW: Workflow; } export default { async fetch(request, env, ctx) { // More likely to come from your database or via the request body! const user: User = { email: "user@example.com", createdTimestamp: Date.now() } let instance = await env.MY_WORKFLOW.create({ // params expects the type User params: user }) return Response.json({ id: instance.id, details: await instance.status(), }); } } ``` -------------------------------- ### Trigger Workflow with Parameters from a Worker Source: https://context7_llms This TypeScript example demonstrates how to trigger a Cloudflare Workflow from a Worker's `fetch` handler. It shows how to create a Workflow instance, pass a JSON-serializable event object as parameters using the `create` method of a Workflow binding, and return the instance details. ```TypeScript export default { async fetch(req: Request, env: Env) { let someEvent = { url: req.url, createdTimestamp: Date.now() } // Trigger our Workflow // Pass our event as the second parameter to the `create` method // on our Workflow binding. let instance = await env.MY_WORKFLOW.create({ id: await crypto.randomUUID(), params: someEvent }); return Response.json({ id: instance.id, details: await instance.status(), }); }, }; ``` -------------------------------- ### Configure API Base URL for Cloudflare Workflow Source: https://github.com/cloudflare/docs-examples/tree/main/workflows/waitForEvent This snippet defines the `API_BASE_URL` constant, which should be set to your Cloudflare Workflow's URL. It is crucial to ensure there is no trailing slash at the end of the URL to prevent potential errors in API calls. This constant is typically found in `constants.ts`. ```TypeScript export const API_BASE_URL = '<your-workflow-url-NO-TRAILING-SLASH>'; ``` -------------------------------- ### Expose Workflow Method in Cloudflare Worker via Service Binding (TypeScript) Source: https://context7_llms This TypeScript example shows a Cloudflare Worker entrypoint (`WorkflowsService`) designed to be called via a Service Binding. It exposes an asynchronous `createInstance` method that accepts a custom `Payload` and interacts with the `MY_WORKFLOW` binding to create a new Workflow instance, returning its ID and status details. ```typescript import { WorkerEntrypoint } from "cloudflare:workers"; interface Env { MY_WORKFLOW: Workflow; } type Payload = { hello: string; } export default class WorkflowsService extends WorkerEntrypoint { // Currently, entrypoints without a named handler are not supported async fetch() { return new Response(null, {status: 404}); } async createInstance(payload: Payload) { let instance = await this.env.MY_WORKFLOW.create({ params: payload }); return Response.json({ id: instance.id, details: await instance.status(), }); } } ``` -------------------------------- ### JavaScript Global Environment and WebSocket Setup Source: https://discord.cloudflare.com/ This JavaScript snippet initializes a global `window.GLOBAL_ENV` object with various application-specific configurations, including API endpoints, CDN hosts, and third-party service keys. It also defines flags for overlay and billing standalone modes. Following this, it attempts to establish a WebSocket connection to a specified gateway, dynamically adjusting the connection parameters (like encoding and compression) based on the browser's capabilities to optimize data transfer. ```JavaScript window.GLOBAL_ENV = {"NODE_ENV":"production","BUILT_AT":"1750663265038","HTML_TIMESTAMP":Date.now(),"BUILD_NUMBER":"411537","PROJECT_ENV":"production","RELEASE_CHANNEL":"stable","VERSION_HASH":"debc7e1ee80fb7e6482986949dd32293ec21502e","PRIMARY_DOMAIN":"discord.com","SENTRY_TAGS":{"buildId":"debc7e1ee80fb7e6482986949dd32293ec21502e","buildType":"normal"},"SENTRY_RELEASE":"2025-06-23-debc7e1ee80fb7e6482986949dd32293ec21502e-discord_web","PUBLIC_PATH":"/assets/","LOCATION":"history","API_VERSION":9,"API_PROTOCOL":"https:","API_ENDPOINT":"//discord.com/api","GATEWAY_ENDPOINT":"wss://gateway.discord.gg","STATIC_ENDPOINT":"","ASSET_ENDPOINT":"//discord.com","MEDIA_PROXY_ENDPOINT":"//media.discordapp.net","IMAGE_PROXY_ENDPOINTS":"//images-ext-1.discordapp.net,//images-ext-2.discordapp.net","CDN_HOST":"cdn.discordapp.com","DEVELOPERS_ENDPOINT":"//discord.com","MARKETING_ENDPOINT":"//discord.com","WEBAPP_ENDPOINT":"//discord.com","WIDGET_ENDPOINT":"//discord.com/widget","SEO_ENDPOINT":"undefined","NETWORKING_ENDPOINT":"//router.discordapp.net","REMOTE_AUTH_ENDPOINT":"//remote-auth-gateway.discord.gg","RTC_LATENCY_ENDPOINT":"//latency.discord.media/rtc","INVITE_HOST":"discord.gg","GUILD_TEMPLATE_HOST":"discord.new","GIFT_CODE_HOST":"discord.gift","ACTIVITY_APPLICATION_HOST":"discordsays.com","MIGRATION_SOURCE_ORIGIN":"https://discordapp.com","MIGRATION_DESTINATION_ORIGIN":"https://discord.com","STRIPE_KEY":"pk_live_CUQtlpQUF0vufWpnpUmQvcdi","ADYEN_KEY":"live_E3OQ33V6GVGTXOVQZEAFQJ6DJIDVG6SY","BRAINTREE_KEY":"production_ktzp8hfp_49pp2rp4phym7387","DEV_SESSION_KEY":"undefined"} !function(){if(null!=window.WebSocket&&function(n){try{var o=localStorage.getItem(n);if(null==o)return null;return JSON.parse(o)}catch(e){return null}}("token")&&!window.__OVERLAY__){var n=null!=window.DiscordNative||null!=window.require?"etf":"json",o=window.GLOBAL_ENV.GATEWAY_ENDPOINT+"/?encoding="+n+"&v="+window.GLOBAL_ENV.API_VERSION;null!=window.DiscordNative&&void 0!==window.Uint8Array&&void 0!==window.TextDecoder?o+="&compress=zstd-stream":void 0!==window.Uint8Array&&(o+="&compress=zlib-stream"),console.log("[FAST CONNECT] "+o+", encoding: "+n+", version: "+window.GLOBAL_ENV.API_VERSION);var e=new WebSocket(o);e.binaryType="arraybuffer";var i=Date.now(),r={open:!1,identify:!1,gateway:o,messages:[]};e.onopen=function(){console.log("[FAST CONNECT] connected in "+(Date.now()-i)+"ms"),r.open=!0},e.onclose=e.onerror=function(){window._ws=null},e.onmessage=function(n){r.messages.push(n)},window._ws={ws:e,state:r}}}(); window.__OVERLAY__ = /overlay/.test(location.pathname); window.__BILLING_STANDALONE__ = /^\\/billing/.test(location.pathname); ``` -------------------------------- ### Initialize Cloudflare Workflow Project with C3 CLI Source: https://context7_llms This command uses the `npm create cloudflare` (C3) CLI tool to scaffold a new Cloudflare Workflow project. It specifies the `workflows-starter` template, creating a new directory with the basic project structure ready for development. ```sh npm create cloudflare@latest workflows-starter -- --template "cloudflare/workflows-starter" ``` -------------------------------- ### Defining a Generic Class in TypeScript Source: https://www.typescriptlang.org/docs/handbook/2/generics.html This snippet demonstrates how to create a generic class, `GenericNumber`, where the type parameter ensures all properties and methods operate on the same type. It shows an example of using it with strings for concatenation. ```TypeScript let stringNumeric = new GenericNumber(); stringNumeric.zeroValue = ""; stringNumeric.add = function (x, y) { return x + y; }; console.log(stringNumeric.add(stringNumeric.zeroValue, "test")); ``` -------------------------------- ### Generic Constraint Violation (Type Mismatch Error) Source: https://www.typescriptlang.org/docs/handbook/2/generics.html This example demonstrates the effect of a generic constraint. Attempting to call the `loggingIdentity` function with a `number` (which does not satisfy the `Lengthwise` interface) results in a TypeScript compiler error, enforcing type safety. ```TypeScript loggingIdentity(3); Argument of type 'number' is not assignable to parameter of type 'Lengthwise'.2345Argument of type 'number' is not assignable to parameter of type 'Lengthwise'. ``` -------------------------------- ### TypeScript Identity Function with `any` Type Source: https://www.typescriptlang.org/docs/handbook/2/generics.html This example shows an identity function using the `any` type, allowing it to accept and return values of any type. However, this approach sacrifices type safety as it loses information about the original type when the function returns. ```typescript function identity(arg: any): any { return arg; } ``` -------------------------------- ### Create Cloudflare Workflow Project with C3 CLI Source: https://context7_llms This command uses the `npm create cloudflare` (C3) CLI tool to initialize a new Cloudflare Workers project with the Workflows starter template. It sets up the basic project structure, including `src/index.ts` for Workflow definition and `wrangler.jsonc` for configuration. ```sh npm create cloudflare@latest workflows-starter -- --template "cloudflare/workflows-starter" ``` -------------------------------- ### Upload Twilio Account SID Secret to Cloudflare Workers Source: https://github.com/craigsdennis/twilio-cloudflare-workflow This command uses the Wrangler CLI to securely upload your Twilio Account SID as an environment secret to your Cloudflare Worker. This secret is essential for authenticating API requests to Twilio from your Worker. ```shell npx wrangler secret put TWILIO_ACCOUNT_SID ``` -------------------------------- ### Creating a Generic Interface with a Call Signature in TypeScript Source: https://www.typescriptlang.org/docs/handbook/2/generics.html This example introduces the concept of generic interfaces by extracting a generic function's call signature into an interface definition. This allows for reusable type definitions for generic functions, promoting cleaner and more organized code. ```ts interface GenericIdentityFn { (arg: Type): Type; } function identity(arg: Type): Type { return arg; } let myIdentity: GenericIdentityFn = identity; ``` -------------------------------- ### Define a Cloudflare Workflow Entrypoint in TypeScript Source: https://context7_llms This TypeScript code defines a `MyWorkflow` class extending `WorkflowEntrypoint`, demonstrating a basic Cloudflare Workflow. It includes type definitions for environment variables and workflow parameters, shows how to define sequential steps using `step.do`, implement retry strategies, and interact with external APIs. It also illustrates how to bind the Workflow to a Worker's `fetch` handler for creation and status retrieval. ```ts import { WorkflowEntrypoint, WorkflowStep, WorkflowEvent } from 'cloudflare:workers'; type Env = { // Add your bindings here, e.g. Workers KV, D1, Workers AI, etc. MY_WORKFLOW: Workflow; }; // User-defined params passed to your workflow type Params = { email: string; metadata: Record; }; export class MyWorkflow extends WorkflowEntrypoint { async run(event: WorkflowEvent, step: WorkflowStep) { // Can access bindings on `this.env` // Can access params on `event.payload` const files = await step.do('my first step', async () => { // Fetch a list of files from $SOME_SERVICE return { files: [ 'doc_7392_rev3.pdf', 'report_x29_final.pdf', 'memo_2024_05_12.pdf', 'file_089_update.pdf', 'proj_alpha_v2.pdf', 'data_analysis_q2.pdf', 'notes_meeting_52.pdf', 'summary_fy24_draft.pdf', ], }; }); const apiResponse = await step.do('some other step', async () => { let resp = await fetch('https://api.cloudflare.com/client/v4/ips'); return await resp.json(); }); await step.sleep('wait on something', '1 minute'); await step.do( 'make a call to write that could maybe, just might, fail', // Define a retry strategy { retries: { limit: 5, delay: '5 second', backoff: 'exponential', }, timeout: '15 minutes', }, async () => { // Do stuff here, with access to the state from our previous steps if (Math.random() > 0.5) { throw new Error('API call to $STORAGE_SYSTEM failed'); } }, ); } } export default { async fetch(req: Request, env: Env): Promise { let id = new URL(req.url).searchParams.get('instanceId'); // Get the status of an existing instance, if provided if (id) { let instance = await env.MY_WORKFLOW.get(id); return Response.json({ status: await instance.status(), }); } // Spawn a new instance and return the ID and status let instance = await env.MY_WORKFLOW.create(); return Response.json({ id: instance.id, details: await instance.status(), }); }, }; ``` -------------------------------- ### Calling Generic Function with Explicit Type Argument (TypeScript) Source: https://www.typescriptlang.org/docs/handbook/2/generics.html This example demonstrates how to call a generic function by explicitly providing the type argument. The type `string` is passed to the `identity` function using angle brackets (`<>`), ensuring the output is strongly typed as a string. ```TypeScript let output = identity("myString"); ```