Skip to content

Commit

Permalink
Beta 4 (#4)
Browse files Browse the repository at this point in the history
  • Loading branch information
daniel-nagy authored Dec 31, 2023
1 parent 0042300 commit 5f63a80
Show file tree
Hide file tree
Showing 8 changed files with 58 additions and 21 deletions.
Binary file modified bun.lockb
Binary file not shown.
26 changes: 26 additions & 0 deletions packages/browser/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,10 @@ An interface for making requests to a browsing context or worker.
- [BrowserClient](#BrowserClient_BrowserClient)
- [Options](#Options)

###### Constants

- [WS](#WS)

###### Constructors

- [from](#From)
Expand Down Expand Up @@ -151,6 +155,28 @@ type Options = {

Options when creating a `BrowserClient`.

#### WS

<sup>_Constant_</sup>

```ts
const SW = Symbol.for("ServiceWorker");
```

An atom that symbolizes a `ServiceWorker`. When used as a target the client will make requests to the currently active `ServiceWorker`.

##### Example

```ts
import * as BrowserClient from "@daniel-nagy/transporter-browser/BrowserClient";

await navigator.serviceWorker.register("./sw.js", {
type: "module"
});

const client = BrowserClient.from(BrowserClient.SW);
```

#### From

<sup>_Constructor_</sup>
Expand Down
2 changes: 1 addition & 1 deletion packages/browser/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@daniel-nagy/transporter-browser",
"type": "module",
"version": "1.0.0-beta.3",
"version": "1.0.0-beta.4",
"description": "Typesafe distributed computing in the browser.",
"author": "Daniel Nagy <1622446+daniel-nagy@users.noreply.github.com>",
"repository": "github:daniel-nagy/transporter",
Expand Down
3 changes: 2 additions & 1 deletion packages/browser/src/BroadcastSubject.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ test("using a broadcast subject to synchronize state between two same-origin bro
const next = spy();

darkMode.subscribe(next);
const change = firstValueFrom(darkMode);

await Test.createIframe(
/* html */ `
Expand All @@ -23,7 +24,7 @@ test("using a broadcast subject to synchronize state between two same-origin bro
{ crossOrigin: false }
);

await firstValueFrom(darkMode);
await change;

assert.calledOnce(next);
assert.calledWith(next, true);
Expand Down
4 changes: 2 additions & 2 deletions packages/browser/src/BrowserClient.sw.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ afterEach(async () => {
});

test("a frame making a request to a service worker", async () => {
const [worker] = await Test.createServiceWorker(/* ts */ `
await Test.createServiceWorker(/* ts */ `
import * as BrowserServer from "http://localhost:8000/packages/browser/src/BrowserServer.ts";
const server = BrowserServer.listen({
Expand All @@ -24,7 +24,7 @@ test("a frame making a request to a service worker", async () => {
});
`);

const client = BrowserClient.from(worker);
const client = BrowserClient.from(BrowserClient.SW);
const response = await client.fetch();

assert.match(response, "hi from the worker");
Expand Down
32 changes: 17 additions & 15 deletions packages/browser/src/BrowserClient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ export type Options = {
origin?: string;
};

/**
* An atom that symbolizes a `ServiceWorker`. When used as a target the client
* will make requests to the currently active `ServiceWorker`.
*/
export const SW = Symbol.for("ServiceWorker");

export type SW = typeof SW;

export class BrowserClient {
/**
* The address of the server. An address is like a port number, except an
Expand All @@ -37,7 +45,7 @@ export class BrowserClient {
/**
* The message target. A message target is like a server host.
*/
public readonly target: Window | Worker | SharedWorker | ServiceWorker;
public readonly target: Window | Worker | SharedWorker | SW;

constructor({
address = "",
Expand All @@ -46,7 +54,7 @@ export class BrowserClient {
}: {
address?: string;
origin?: string;
target: Window | Worker | SharedWorker | ServiceWorker;
target: Window | Worker | SharedWorker | SW;
}) {
this.serverAddress = address;
this.origin = origin;
Expand All @@ -58,7 +66,7 @@ export class BrowserClient {
* response from the server.
*/
async fetch(body: StructuredCloneable.t): Promise<StructuredCloneable.t> {
const messageSink = getMessageSink(this.target);
const messageSink = await getMessageSink(this.target);
const messageSource = getMessageSource(this.target);
const request = Request.t({ address: this.serverAddress, body });

Expand All @@ -73,10 +81,6 @@ export class BrowserClient {
Observable.map((message) => message.data.body)
);

// Not sure it this is necessary or useful.
if (this.target instanceof ServiceWorker)
await navigator.serviceWorker.ready;

messageSink.postMessage(request, { targetOrigin: this.origin });

return Observable.firstValueFrom(response);
Expand All @@ -94,29 +98,27 @@ export class BrowserClient {
* const response = await client.fetch("👋");
*/
export function from(
target: Window | Worker | SharedWorker | ServiceWorker,
target: Window | Worker | SharedWorker | SW,
options: Options = {}
) {
if (target instanceof SharedWorker) target.port.start();
return new BrowserClient({ ...options, target });
}

function getMessageSink(
target: Window | Worker | SharedWorker | ServiceWorker
) {
function getMessageSink(target: Window | Worker | SharedWorker | SW) {
switch (true) {
case target === SW:
return navigator.serviceWorker.ready.then((r) => r.active!);
case target instanceof SharedWorker:
return target.port;
default:
return target;
}
}

function getMessageSource(
target: Window | Worker | SharedWorker | ServiceWorker
) {
function getMessageSource(target: Window | Worker | SharedWorker | SW) {
switch (true) {
case target instanceof ServiceWorker:
case target === SW:
return navigator.serviceWorker;
case target instanceof SharedWorker:
return target.port;
Expand Down
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "@daniel-nagy/transporter",
"type": "module",
"version": "1.0.0-beta.3",
"version": "1.0.0-beta.4",
"description": "Typesafe distributed computing in TypeScript.",
"author": "Daniel Nagy <1622446+daniel-nagy@users.noreply.github.com>",
"repository": "github:daniel-nagy/transporter",
Expand Down
10 changes: 9 additions & 1 deletion packages/core/src/Injector.typetest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,15 @@ describe("decorating functions", () => {
test("providing a value to a function with additional arguments", () => {
const Tag = Injector.Tag<string>();
// $ExpectType (_b: number) => void
Injector.provide([Tag], (_a: string, _b: number) => {});
Injector.provide([Tag], (_a, _b: number) => {});
// ^? (parameter) _a: string
});

// TODO: See if type of injected dependency can be inferred when using generics.
test("generics propagate", () => {
const Tag = Injector.Tag<string>();
// $ExpectType <B>(_b: B) => void
Injector.provide([Tag], <B>(_a: string, _b: B) => {});
});

test("providing multiple values to a function", () => {
Expand Down

0 comments on commit 5f63a80

Please sign in to comment.