Skip to content
Merged
Show file tree
Hide file tree
Changes from 5 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
64 changes: 32 additions & 32 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"dependencies": {
"@changesets/changelog-github": "^0.4.8",
"@changesets/cli": "^2.29.4",
"@cloudflare/workers-types": "^4.20250724.0"
"@cloudflare/workers-types": "^4.20250826.0"
},
"name": "workers-rs",
"version": "0.0.12",
Expand All @@ -15,7 +15,7 @@
"homepage": "https://github.com/cloudflare/workers-rs#readme",
"devDependencies": {
"@types/node": "^24.0.1",
"miniflare": "^4.20250712.2",
"miniflare": "^4.20250823.0",
"typescript": "^5.8.3",
"undici": "^7.12.0",
"uuid": "^11.1.0",
Expand Down
34 changes: 34 additions & 0 deletions worker-sandbox/src/durable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -277,3 +277,37 @@ pub async fn handle_basic_test(

Response::ok("ok")
}

#[worker::send]
pub async fn handle_get_by_name(
_req: Request,
env: Env,
_data: crate::SomeSharedData,
) -> Result<Response> {
let namespace = env.durable_object("MY_CLASS")?;
let name = "my-durable-object";

// Using the new get_by_name method - this is equivalent to:
// let id = namespace.id_from_name(name)?;
// let stub = id.get_stub()?;
let stub = namespace.get_by_name(name)?;

stub.fetch_with_str(&format!("https://fake-host/hello?name={name}"))
.await
}

#[worker::send]
pub async fn handle_get_by_name_with_location_hint(
_req: Request,
env: Env,
_data: crate::SomeSharedData,
) -> Result<Response> {
let namespace = env.durable_object("MY_CLASS")?;
let name = "my-durable-object";

// Using the new get_by_name_with_location_hint method
let stub = namespace.get_by_name_with_location_hint(name, "enam")?;

stub.fetch_with_str(&format!("https://fake-host/hello?name={name}"))
.await
}
2 changes: 2 additions & 0 deletions worker-sandbox/src/router.rs
Original file line number Diff line number Diff line change
Expand Up @@ -216,6 +216,8 @@ macro_rules! add_routes (
add_route!($obj, get, "/durable/hello-unique", durable::handle_hello_unique);
add_route!($obj, get, "/durable/storage", durable::handle_storage);
add_route!($obj, get, "/durable/handle-basic-test", durable::handle_basic_test);
add_route!($obj, get, "/durable/get-by-name", durable::handle_get_by_name);
add_route!($obj, get, "/durable/get-by-name-with-location-hint", durable::handle_get_by_name_with_location_hint);
add_route!($obj, get, "/js_snippets/now", js_snippets::performance_now);
add_route!($obj, get, "/js_snippets/log", js_snippets::console_log);
add_route!($obj, get, format_route!("/sql-counter/{}", "*path"), sql_counter::handle_sql_counter);
Expand Down
14 changes: 14 additions & 0 deletions worker-sandbox/tests/durable.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,18 @@ describe("durable", () => {
// await new Promise(resolve => setTimeout(resolve, 1000));
// expect(calledClose).toBe(true);
});

test("get-by-name", async () => {
const resp = await mf.dispatchFetch(`${mfUrl}durable/get-by-name`);
expect(resp.status).toBe(200);
const text = await resp.text();
expect(text).toBe("Hello from my-durable-object!");
});

test("get-by-name-with-location-hint", async () => {
const resp = await mf.dispatchFetch(`${mfUrl}durable/get-by-name-with-location-hint`);
expect(resp.status).toBe(200);
const text = await resp.text();
expect(text).toBe("Hello from my-durable-object!");
});
});
1 change: 1 addition & 0 deletions worker-sandbox/tests/mf.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ const mf_instance = new Miniflare({
COUNTER: "Counter",
PUT_RAW_TEST_OBJECT: "PutRawTestObject",
AUTO: "AutoResponseObject",
MY_CLASS: "MyClass",
SQL_COUNTER: {
className: "SqlCounter",
useSQLite: true,
Expand Down
13 changes: 13 additions & 0 deletions worker-sys/src/types/durable_object/namespace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,17 @@ extern "C" {
id: &DurableObjectId,
options: &JsValue,
) -> Result<DurableObject, JsValue>;

#[wasm_bindgen(method, catch, js_name=getByName)]
pub fn get_by_name(
this: &DurableObjectNamespace,
name: &str,
) -> Result<DurableObject, JsValue>;

#[wasm_bindgen(method, catch, js_name=getByName)]
pub fn get_by_name_with_options(
this: &DurableObjectNamespace,
name: &str,
options: &JsValue,
) -> Result<DurableObject, JsValue>;
}
25 changes: 25 additions & 0 deletions worker/src/durable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,31 @@ impl ObjectNamespace {
namespace: Some(self),
})
}

/// Get a Durable Object stub directly by name. This combines the functionality of
/// `id_from_name()` and `get_stub()` into a single method call.
pub fn get_by_name(&self, name: &str) -> Result<Stub> {
self.inner
.get_by_name(name)
.map_err(Error::from)
.map(|stub| Stub { inner: stub })
}

/// Get a Durable Object stub directly by name with options (such as location hints).
/// This combines the functionality of `id_from_name()` and `get_stub_with_location_hint()`
/// into a single method call.
pub fn get_by_name_with_location_hint(&self, name: &str, location_hint: &str) -> Result<Stub> {
let options = Object::new();
js_sys::Reflect::set(
&options,
&JsValue::from("locationHint"),
&location_hint.into(),
)?;
self.inner
.get_by_name_with_options(name, &options)
.map_err(Error::from)
.map(|stub| Stub { inner: stub })
}
}

/// An ObjectId is used to identify, locate, and access a Durable Object via interaction with its
Expand Down