Skip to content
Merged
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
9 changes: 6 additions & 3 deletions src/components/TypeScriptExample.astro
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ const props = z
filename: z.string().optional(),
playground: z.boolean().default(false),
code: z.custom<ComponentProps<typeof Code>>().optional(),
omitTabs: z.boolean().default(false),
})
.strict();

const { filename, playground, code } = props.parse(Astro.props);
const { filename, playground, code, omitTabs } = props.parse(Astro.props);

const slot = await Astro.slots.render("default");

Expand All @@ -41,9 +42,11 @@ if (!raw) {
raw = raw.replace(/\u007f/g, "\n");

const js = await format(tsBlankSpace(raw), { parser: "babel", useTabs: true });

const Wrapper = omitTabs ? Fragment : Tabs;
---

<Tabs syncKey="workersExamples">
<Wrapper syncKey="workersExamples">
<TabItem label="JavaScript" icon="seti:javascript">
<Code
{...code}
Expand All @@ -56,4 +59,4 @@ const js = await format(tsBlankSpace(raw), { parser: "babel", useTabs: true });
<TabItem label="TypeScript" icon="seti:typescript">
<Code {...code} lang="ts" code={raw} title={filename} />
</TabItem>
</Tabs>
</Wrapper>
104 changes: 99 additions & 5 deletions src/content/docs/durable-objects/get-started.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,9 @@ If you do not use JavaScript or TypeScript, you will need a [shim](https://devel

Your `MyDurableObject` class will have a constructor with two parameters. The first parameter, `ctx`, passed to the class constructor contains state specific to the Durable Object, including methods for accessing storage. The second parameter, `env`, contains any bindings you have associated with the Worker when you uploaded it.

<TypeScriptExample>
<Tabs syncKey="workersExamples">

<TypeScriptExample omitTabs={true}>
```ts
export class MyDurableObject extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
Expand All @@ -83,19 +85,35 @@ export class MyDurableObject extends DurableObject<Env> {
```
</TypeScriptExample>

<TabItem label="Python" icon="seti:python">

```python
from workers import DurableObject

class MyDurableObject(DurableObject):
def __init__(self, ctx, env):
super().__init__(ctx, env)
```

</TabItem>

</Tabs>

Workers communicate with a Durable Object using [remote-procedure call](/workers/runtime-apis/rpc/#_top). Public methods on a Durable Object class are exposed as [RPC methods](/durable-objects/best-practices/create-durable-object-stubs-and-send-requests/) to be called by another Worker.

Your file should now look like:

<TypeScriptExample>
<Tabs syncKey="workersExamples">

<TypeScriptExample omitTabs={true}>
```ts
export class MyDurableObject extends DurableObject<Env> {
constructor(ctx: DurableObjectState, env: Env) {
// Required, as we're extending the base class.
super(ctx, env)
}

async sayHello():Promise<string> {
async sayHello(): Promise<string> {
let result = this.ctx.storage.sql
.exec("SELECT 'Hello, World!' as greeting")
.one();
Expand All @@ -105,6 +123,27 @@ export class MyDurableObject extends DurableObject<Env> {
```
</TypeScriptExample>

<TabItem label="Python" icon="seti:python">

```python
from workers import DurableObject

class MyDurableObject(DurableObject):
def __init__(self, ctx, env):
super().__init__(ctx, env)

async def say_hello(self):
result = self.ctx.storage.sql \
.exec("SELECT 'Hello, World!' as greeting") \
.one()

return result.greeting
```

</TabItem>

</Tabs>

In the code above, you have:

1. Defined a RPC method, `sayHello()`, that can be called by a Worker to communicate with a Durable Object.
Expand All @@ -124,7 +163,10 @@ A Worker is used to [access Durable Objects](/durable-objects/best-practices/cre

To communicate with a Durable Object, the Worker's fetch handler should look like the following:

<TypeScriptExample>

<Tabs syncKey="workersExamples">

<TypeScriptExample omitTabs={true}>
```ts
export default {
async fetch(request, env, ctx): Promise<Response> {
Expand All @@ -140,6 +182,25 @@ export default {
```
</TypeScriptExample>

<TabItem label="Python" icon="seti:python">

```python
from workers import handler, Response
from urllib.parse import urlparse

@handler
async def on_fetch(request, env, ctx):
url = urlparse(request.url)
id = env.MY_DURABLE_OBJECT.idFromName(url.path)
stub = env.MY_DURABLE_OBJECT.get(id)
greeting = await stub.say_hello()
return Response(greeting)
```

</TabItem>

</Tabs>

In the code above, you have:

1. Exported your Worker's main event handlers, such as the `fetch()` handler for receiving HTTP requests.
Expand Down Expand Up @@ -217,7 +278,10 @@ Preview your Durable Object Worker at `<YOUR_WORKER>.<YOUR_SUBDOMAIN>.workers.de

Your final code should look like this:

<TypeScriptExample>

<Tabs syncKey="workersExamples">

<TypeScriptExample omitTabs={true}>
```ts title="index.ts"
import { DurableObject } from "cloudflare:workers";
export class MyDurableObject extends DurableObject<Env> {
Expand Down Expand Up @@ -247,6 +311,36 @@ export default {
```
</TypeScriptExample>

<TabItem label="Python" icon="seti:python">

```python
from workers import DurableObject, handler, Response
from urllib.parse import urlparse

class MyDurableObject(DurableObject):
def __init__(self, ctx, env):
super().__init__(ctx, env)

async def say_hello(self):
result = self.ctx.storage.sql \
.exec("SELECT 'Hello, World!' as greeting") \
.one()

return result.greeting

@handler
async def on_fetch(request, env, ctx):
url = urlparse(request.url)
id = env.MY_DURABLE_OBJECT.idFromName(url.path)
stub = env.MY_DURABLE_OBJECT.get(id)
greeting = await stub.say_hello()
return Response(greeting)
```

</TabItem>

</Tabs>

By finishing this tutorial, you have:

- Successfully created a Durable Object
Expand Down
Loading