Build A Temporal Application From Scratch in TypeScript - Learn Temporal
Build A Temporal Application From Scratch in TypeScript - Learn Temporal
TUTORIAL INFORMATION
Level: ⭐ Temporal beginner
Time: ⏱️ ~15 minutes
Goals: 🙌
Set up, build, and test a Temporal application project from scratch using the
TypeScript SDK.
Identify the four parts of a Temporal Workflow application.
Describe how the Temporal Server gets information to the Worker.
Introduction
Creating reliable applications is a difficult task. Temporal lets you create fault-tolerant, resilient
applications using programming languages you already know, so you can build complex
applications that execute reliably and recover from failures.
In this tutorial, you will build your first Temporal Application from scratch using the Temporal
TypeScript SDK. The app will consist of four pieces:
1. A Workflow: Workflows are functions that define the overall flow of the application.
https://learn.temporal.io/getting_started/typescript/hello_world_in_typescript/ 1/13
02/08/2023, 06:50 Build a Temporal Application from scratch in TypeScript | Learn Temporal
2. An Activity: Activities are functions called by Workflows, and they contain any logic that
might fail or behave differently at different times. The Workflow you'll create executes a
single Activity that takes a string as input and returns a formatted version of this string to
the Workflow.
3. A Worker: Workers host the Activity and Workflow code and executes the code piece by
piece.
4. An initiator: To start a Workflow, you need to create a Client instance and call the
.start() method. You'll write a separate script to do this.
When you're done, you'll have a basic application and a clear understanding of how to build out
the components you'll need in future Temporal applications.
All of the code in this tutorial is available in the hello-world directory of the
temporalio/samples-typescript repository.
Prerequisites
Before starting this tutorial:
Set up a local development environment for developing Temporal applications using
Node.js and TypeScript
The TypeScript SDK requires Node.js 14 or later.
INFO
This is a step by step guide that shows you how to create a project from scratch, and the
goal is for you to better understand the structure of a Temporal application by creating
the files on your own.
This project exists in its entirety in the Temporal TypeScript samples repo. To skip these
manual steps and get the project running locally, use the package initializer command
npx @temporalio/create@latest hello-world --sample hello-world
To build an app with the Temporal TypeScript SDK, you'll create a new directory and use npm
to initialize it as a Node.js project. Then you'll add the Temporal SDK packages and other
dependencies to your project.
https://learn.temporal.io/getting_started/typescript/hello_world_in_typescript/ 2/13
02/08/2023, 06:50 Build a Temporal Application from scratch in TypeScript | Learn Temporal
Create the package.json file in the root of your project and add the following code to the file
that defines the project, sets up scripts, and defines the dependencies this project requires:
package.json
{
"name": "temporal-hello-world",
"version": "0.1.0",
"private": true,
"scripts": {
"build": "tsc --build",
"build.watch": "tsc --build --watch",
"lint": "eslint .",
"start": "ts-node src/worker.ts",
"start.watch": "nodemon src/worker.ts",
"workflow": "ts-node src/client.ts"
},
"nodemonConfig": {
"execMap": {
"ts": "ts-node"
},
"ext": "ts",
"watch": [
"src"
]
},
"dependencies": {
"@temporalio/activity": "^1.5.2",
"@temporalio/client": "^1.5.2",
"@temporalio/worker": "^1.5.2",
"@temporalio/workflow": "^1.5.2",
"nanoid": "3.x"
},
"devDependencies": {
"@tsconfig/node16": "^1.0.0",
https://learn.temporal.io/getting_started/typescript/hello_world_in_typescript/ 3/13
02/08/2023, 06:50 Build a Temporal Application from scratch in TypeScript | Learn Temporal
"@types/node": "^16.11.43",
"@typescript-eslint/eslint-plugin": "^5.0.0",
"@typescript-eslint/parser": "^5.0.0",
"eslint": "^7.32.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-deprecation": "^1.2.1",
"nodemon": "^2.0.12",
"ts-node": "^10.8.1",
"typescript": "^4.4.2"
}
}
You should check out a few parts of the package.json , and the first is the scripts section.
These are the npm commands you'll use to build, lint, and start your application code.
Next, take a look at the packages listed as dependencies. These are the packages that
compose the Temporal TypeScript SDK, and each package maps to the four parts of a
Temporal application: an Activity, Client, Worker, and Workflow. There is also Nanoid, an npm
package which you'll use to generate a unique identifier for your Workflow.
Finally, look through the devDependencies section. These are the packages that let you set
up a Node.js project with Nodemon (a tool that automatically restarts your application when it
detects a change in your code), TypeScript, ESLint, and ts-node.
Save the file, then download the dependencies specified in the package.json file with the
command:
$ npm install
Downloading the dependencies can take a few minutes to complete. Once the download is
done, you will have new a package-lock.json file and a node_modules directory.
Your project workspace is configured, so you're ready to create your first Temporal Activity and
Workflow. You'll start with the Workflow.
Create a Workflow
Workflows are where you configure and organize the execution of Activities. You define a
Workflow by writing a Workflow Definition using one of the Temporal SDKs. You can learn more
in the Develop Workflows section of the Temporal documentation.
https://learn.temporal.io/getting_started/typescript/hello_world_in_typescript/ 4/13
02/08/2023, 06:50 Build a Temporal Application from scratch in TypeScript | Learn Temporal
In this code, the variable greet is assigned the value of proxyActivites , which is a method
from the Temporal TypeScript SDK that lets you configure the Activity with different options. In
this example, you have specified that the Start-to-Close Timeout for your Activity will be one
minute, meaning that your Activity has one minute to begin before it times out. Of all the
Temporal timeout options, startToCloseTimeOut is the one you should always set.
The example function executes an Activity called greet , and the function returns the result
of the Activity. You'll create the greet function in the next section.
https://learn.temporal.io/getting_started/typescript/hello_world_in_typescript/ 5/13
02/08/2023, 06:50 Build a Temporal Application from scratch in TypeScript | Learn Temporal
TIP
No matter how many inputs you pass to a Workflow, it's a best practice to use an object.
There are some JSON restrictions that you should be aware of, and you can learn more
about the kinds of inputs you can pass to a Workflow in the Workflow parameters section
of the Temporal documentation.
Next, you'll define the Activity that your Workflow will execute.
Create an Activity
You use Activities in your Temporal Applications to execute non-deterministic code or perform
operations that may fail.
For this tutorial, your Activity won't be complex; you'll create an Activity that takes a string as
input and uses it to create a new string as output, which is then returned to the Workflow. This
will let you see how Workflows and Activities work together without building something
complicated.
With the Temporal TypeScript SDK, you define Activities similarly to how you define Workflows:
using an exportable TypeScript module.
Your Activity Definition can accept input parameters. Review the Activity parameters section of
the Temporal documentation for more details, as there are some limitations you'll want to be
aware of when running more complex applications.
Create the file activities.ts in the src directory:
Add the following code to define a greet function:
hello-world/src/activities.ts
TypeScript JavaScript
https://learn.temporal.io/getting_started/typescript/hello_world_in_typescript/ 6/13
02/08/2023, 06:50 Build a Temporal Application from scratch in TypeScript | Learn Temporal
You've completed the logic for the application; you have a Workflow and an Activity defined.
Next, you'll write code to configure and launch a Worker.
run().catch((err) => {
console.error(err);
https://learn.temporal.io/getting_started/typescript/hello_world_in_typescript/ 7/13
02/08/2023, 06:50 Build a Temporal Application from scratch in TypeScript | Learn Temporal
process.exit(1);
});
In the code, you create and call an async function named run . It creates and runs a Worker. It
configures the Worker with a workflowsPath (the location of your workflow file), your Activity
functions, and the name of the Task Queue. In this example, you name the Task Queue hello-
world .
Now you will use an npm script to start your Worker using Nodemon, which will reload
whenever it detects changes in your file, hence the command name start.watch . Run the
command:
$ npm run start.watch
taskQueue: 'hello-world',
shutdownGraceTimeMs: 10000,
stickyQueueScheduleToStartTimeoutMs: 10000,
isolateExecutionTimeoutMs: 5000,
maxHeartbeatThrottleIntervalMs: 60000,
defaultHeartbeatThrottleIntervalMs: 30000,
loadedDataConverter: {
payloadConverter: [DefaultPayloadConverter],
failureConverter: [DefaultFailureConverter],
payloadCodecs: []
}
}
}
2022-11-22T04:38:13.298Z [INFO] asset workflow-bundle-
d624b57670e912aab581.js 695 KiB [emitted] [immutable] (name: main)
2022-11-22T04:38:13.298Z [INFO] runtime modules 937 bytes 4 modules
2022-11-22T04:38:13.298Z [INFO] modules by path
./node_modules/@temporalio/ 209 KiB
2022-11-22T04:38:13.298Z [INFO] modules by path
./node_modules/@temporalio/common/ 111 KiB 19 modules
2022-11-22T04:38:13.298Z [INFO] modules by path
./node_modules/@temporalio/workflow/ 95.2 KiB
2022-11-22T04:38:13.298Z [INFO]
./node_modules/@temporalio/workflow/lib/worker-interface.js 11.8 KiB
[built] [code generated]
2022-11-22T04:38:13.299Z [INFO]
./node_modules/@temporalio/workflow/lib/alea.js 2.87 KiB [built] [code
generated]
2022-11-22T04:38:13.299Z [INFO] + 11 modules
2022-11-22T04:38:13.299Z [INFO]
./node_modules/@temporalio/worker/lib/workflow-log-interceptor.js 2.25
KiB [built] [code generated]
2022-11-22T04:38:13.299Z [INFO] modules by path ./src/ 784 bytes
2022-11-22T04:38:13.299Z [INFO] ./src/workflows-autogenerated-
entrypoint.js 540 bytes [built] [code generated]
2022-11-22T04:38:13.299Z [INFO] ./src/workflows.ts 244 bytes [built]
[code generated]
2022-11-22T04:38:13.299Z [INFO] __temporal_custom_payload_converter
(ignored) 15 bytes [built] [code generated]
2022-11-22T04:38:13.299Z [INFO] __temporal_custom_failure_converter
(ignored) 15 bytes [built] [code generated]
2022-11-22T04:38:13.299Z [INFO] ./node_modules/ms/index.js 2.95 KiB
[built] [code generated]
2022-11-22T04:38:13.299Z [INFO] webpack 5.75.0 compiled successfully in
540 ms
2022-11-22T04:38:13.303Z [INFO] Workflow bundle created { size:
'0.68MB' }
https://learn.temporal.io/getting_started/typescript/hello_world_in_typescript/ 9/13
02/08/2023, 06:50 Build a Temporal Application from scratch in TypeScript | Learn Temporal
In the output, you will see the Worker options and their values, the Webpack bundling output,
and timestamps from Nodemon describing which programs have been invoked.
Now that you have your Worker running, it's time for you to start a Workflow Execution.
Open a new tab in your terminal, create a client.ts file in the src directory, and add the
following code to your file to create a client that will kick off your Workflow Execution:
hello-world/src/client.ts
TypeScript JavaScript
run().catch((err) => {
console.error(err);
process.exit(1);
});
In the client.ts file, the run function sets up a connection to your Temporal Server, invokes
your Workflow, passes in an argument for the name parameter (in this example, the name is
Temporal) and assigns the Workflow a unique identifier with Nanoid. The client dispatches the
Workflow on the same hello-world Task Queue that the Worker is polling on.
SPECIFY A WORKFLOW ID
A Workflow Id is unique in a namespace and is used for deduplication. Using an identifier
that reflects some business process or entity is a good practice. For example, you might
use a customer identifier as part of the Workflow Id if you run one Workflow per customer.
This would make it easier to find all of the Workflow Executions related to that customer
later.
https://learn.temporal.io/getting_started/typescript/hello_world_in_typescript/ 11/13
02/08/2023, 06:50 Build a Temporal Application from scratch in TypeScript | Learn Temporal
Now that your client code is written, it's time for you to use this code to start your Workflow
Execution.
The "Hello, Temporal!" output is generated as the result of a few steps. First, client.ts
passes Temporal as an argument to the Workflow. Next, the Workflow passes the argument
to the Activity, and finally the Activity returns Hello, ${name}! .
You have successfully built a Temporal application from scratch!
Conclusion
You now know how to build a basic Temporal application using the TypeScript SDK.
Review
Answer the following questions to see whether you remember some of the important concepts
from this tutorial:
What are the four parts of a Temporal Workflow application?
https://learn.temporal.io/getting_started/typescript/hello_world_in_typescript/ 13/13