connected-solid builds

main
Jackson Morgan 6 months ago
parent 453ee230f3
commit 2fa3e52246
  1. 4
      packages/connected-solid/src/notifications/SolidNotificationSubscription.ts
  2. 32
      packages/connected-solid/src/notifications/Websocket2023NotificationSubscription.ts
  3. 26
      packages/connected-solid/src/notifications/results/NotificationErrors.ts
  4. 5
      packages/connected-solid/src/resources/SolidContainer.ts
  5. 2
      packages/connected-solid/src/resources/SolidResource.ts
  6. 3
      packages/connected-solid/src/util/rdfUtils.ts

@ -125,7 +125,9 @@ export abstract class SolidNotificationSubscription {
* @internal * @internal
* onNotificationError * onNotificationError
*/ */
protected onNotificationError(message: NotificationCallbackError): void { protected onNotificationError(
message: NotificationCallbackError<SolidLeaf | SolidContainer>,
): void {
Object.values(this.subscriptions).forEach(({ onNotificationError }) => { Object.values(this.subscriptions).forEach(({ onNotificationError }) => {
onNotificationError?.(message); onNotificationError?.(message);
}); });

@ -1,4 +1,3 @@
import { UnexpectedResourceError } from "../../requester/results/error/ErrorResult";
import { SubscriptionClient } from "@solid-notifications/subscription"; import { SubscriptionClient } from "@solid-notifications/subscription";
import { WebSocket } from "ws"; import { WebSocket } from "ws";
import { import {
@ -6,14 +5,17 @@ import {
DisconnectedNotAttemptingReconnectError, DisconnectedNotAttemptingReconnectError,
UnsupportedNotificationError, UnsupportedNotificationError,
} from "./results/NotificationErrors"; } from "./results/NotificationErrors";
import type { NotificationMessage } from "./NotificationMessage"; import type { SolidNotificationMessage } from "./SolidNotificationMessage";
import type { Resource } from "../Resource"; import { UnexpectedResourceError, type ConnectedContext } from "@ldo/connected";
import type { SolidLdoDatasetContext } from "../../SolidLdoDatasetContext";
import type { import type {
ChannelType, ChannelType,
NotificationChannel, NotificationChannel,
} from "@solid-notifications/types"; } from "@solid-notifications/types";
import { SolidNotificationSubscription } from "./SolidNotificationSubscription"; import { SolidNotificationSubscription } from "./SolidNotificationSubscription";
import type { SolidConnectedPlugin } from "../SolidConnectedPlugin";
import type { SolidLeaf } from "../resources/SolidLeaf";
import type { SolidContainer } from "../resources/SolidContainer";
import { guaranteeFetch } from "../util/guaranteeFetch";
const CHANNEL_TYPE = const CHANNEL_TYPE =
"http://www.w3.org/ns/solid/notifications#WebSocketChannel2023"; "http://www.w3.org/ns/solid/notifications#WebSocketChannel2023";
@ -33,9 +35,9 @@ export class Websocket2023NotificationSubscription extends SolidNotificationSubs
private maxReconnectAttempts = 6; private maxReconnectAttempts = 6;
constructor( constructor(
resource: Resource, resource: SolidLeaf | SolidContainer,
parentSubscription: (message: NotificationMessage) => void, parentSubscription: (message: SolidNotificationMessage) => void,
context: SolidLdoDatasetContext, context: ConnectedContext<SolidConnectedPlugin[]>,
createWebsocket?: (address: string) => WebSocket, createWebsocket?: (address: string) => WebSocket,
) { ) {
super(resource, parentSubscription, context); super(resource, parentSubscription, context);
@ -52,11 +54,11 @@ export class Websocket2023NotificationSubscription extends SolidNotificationSubs
err.message.startsWith("Discovery did not succeed") err.message.startsWith("Discovery did not succeed")
) { ) {
this.onNotificationError( this.onNotificationError(
new UnsupportedNotificationError(this.resource.uri, err.message), new UnsupportedNotificationError(this.resource, err.message),
); );
} else { } else {
this.onNotificationError( this.onNotificationError(
UnexpectedResourceError.fromThrown(this.resource.uri, err), UnexpectedResourceError.fromThrown(this.resource, err),
); );
} }
this.onClose(); this.onClose();
@ -64,7 +66,9 @@ export class Websocket2023NotificationSubscription extends SolidNotificationSubs
} }
public async discoverNotificationChannel(): Promise<NotificationChannel> { public async discoverNotificationChannel(): Promise<NotificationChannel> {
const client = new SubscriptionClient(this.context.fetch); const client = new SubscriptionClient(
guaranteeFetch(this.context.solid.fetch),
);
return await client.subscribe( return await client.subscribe(
this.resource.uri, this.resource.uri,
CHANNEL_TYPE as ChannelType, CHANNEL_TYPE as ChannelType,
@ -86,14 +90,14 @@ export class Websocket2023NotificationSubscription extends SolidNotificationSubs
this.socket.onmessage = (message) => { this.socket.onmessage = (message) => {
const messageData = message.data.toString(); const messageData = message.data.toString();
// TODO uncompliant Pod error on misformatted message // TODO uncompliant Pod error on misformatted message
this.onNotification(JSON.parse(messageData) as NotificationMessage); this.onNotification(JSON.parse(messageData) as SolidNotificationMessage);
}; };
this.socket.onclose = this.onClose.bind(this); this.socket.onclose = this.onClose.bind(this);
this.socket.onerror = (err) => { this.socket.onerror = (err) => {
this.onNotificationError( this.onNotificationError(
new UnexpectedResourceError(this.resource.uri, err.error), new UnexpectedResourceError(this.resource, err.error),
); );
}; };
return; return;
@ -109,14 +113,14 @@ export class Websocket2023NotificationSubscription extends SolidNotificationSubs
}, this.reconnectInterval); }, this.reconnectInterval);
this.onNotificationError( this.onNotificationError(
new DisconnectedAttemptingReconnectError( new DisconnectedAttemptingReconnectError(
this.resource.uri, this.resource,
`Attempting to reconnect to Websocket for ${this.resource.uri}.`, `Attempting to reconnect to Websocket for ${this.resource.uri}.`,
), ),
); );
} else { } else {
this.onNotificationError( this.onNotificationError(
new DisconnectedNotAttemptingReconnectError( new DisconnectedNotAttemptingReconnectError(
this.resource.uri, this.resource,
`Lost connection to websocket for ${this.resource.uri}.`, `Lost connection to websocket for ${this.resource.uri}.`,
), ),
); );

@ -1,30 +1,36 @@
import type { UnexpectedResourceError } from "../../../requester/results/error/ErrorResult"; import type { Resource, UnexpectedResourceError } from "@ldo/connected";
import { ResourceError } from "../../../requester/results/error/ErrorResult"; import { ResourceError } from "@ldo/connected";
export type NotificationCallbackError = export type NotificationCallbackError<ResourceType extends Resource> =
| DisconnectedAttemptingReconnectError | DisconnectedAttemptingReconnectError<ResourceType>
| DisconnectedNotAttemptingReconnectError | DisconnectedNotAttemptingReconnectError<ResourceType>
| UnsupportedNotificationError | UnsupportedNotificationError<ResourceType>
| UnexpectedResourceError; | UnexpectedResourceError<ResourceType>;
/** /**
* Indicates that the requested method for receiving notifications is not * Indicates that the requested method for receiving notifications is not
* supported by this Pod. * supported by this Pod.
*/ */
export class UnsupportedNotificationError extends ResourceError { export class UnsupportedNotificationError<
ResourceType extends Resource,
> extends ResourceError<ResourceType> {
readonly type = "unsupportedNotificationError" as const; readonly type = "unsupportedNotificationError" as const;
} }
/** /**
* Indicates that the socket has disconnected and is attempting to reconnect. * Indicates that the socket has disconnected and is attempting to reconnect.
*/ */
export class DisconnectedAttemptingReconnectError extends ResourceError { export class DisconnectedAttemptingReconnectError<
ResourceType extends Resource,
> extends ResourceError<ResourceType> {
readonly type = "disconnectedAttemptingReconnectError" as const; readonly type = "disconnectedAttemptingReconnectError" as const;
} }
/** /**
* Indicates that the socket has disconnected and is attempting to reconnect. * Indicates that the socket has disconnected and is attempting to reconnect.
*/ */
export class DisconnectedNotAttemptingReconnectError extends ResourceError { export class DisconnectedNotAttemptingReconnectError<
ResourceType extends Resource,
> extends ResourceError<ResourceType> {
readonly type = "disconnectedNotAttemptingReconnectError" as const; readonly type = "disconnectedNotAttemptingReconnectError" as const;
} }

@ -38,6 +38,7 @@ import {
} from "@ldo/connected"; } from "@ldo/connected";
import type { SolidConnectedPlugin } from "../SolidConnectedPlugin"; import type { SolidConnectedPlugin } from "../SolidConnectedPlugin";
import type { SolidLeaf } from "./SolidLeaf"; import type { SolidLeaf } from "./SolidLeaf";
import type { HttpErrorResultType } from "../requester/results/error/HttpErrorResult";
/** /**
* Represents the current status of a specific container on a Pod as known by * Represents the current status of a specific container on a Pod as known by
@ -499,7 +500,9 @@ export class SolidContainer extends SolidResource {
}), }),
) )
).flat(); ).flat();
const errors = results.filter((value) => value.isError); const errors = results.filter(
(value): value is HttpErrorResultType<this> => value.isError,
);
if (errors.length > 0) { if (errors.length > 0) {
return new AggregateError(errors); return new AggregateError(errors);
} }

@ -135,7 +135,7 @@ export abstract class SolidResource
super(); super();
this.context = context; this.context = context;
this.notificationSubscription = new Websocket2023NotificationSubscription( this.notificationSubscription = new Websocket2023NotificationSubscription(
this, this as unknown as SolidLeaf | SolidContainer,
this.onNotification.bind(this), this.onNotification.bind(this),
this.context, this.context,
); );

@ -2,9 +2,6 @@ import type { LdoDataset } from "@ldo/ldo";
import { parseRdf } from "@ldo/ldo"; import { parseRdf } from "@ldo/ldo";
import { namedNode, quad as createQuad } from "@rdfjs/data-model"; import { namedNode, quad as createQuad } from "@rdfjs/data-model";
import type { Dataset } from "@rdfjs/types"; import type { Dataset } from "@rdfjs/types";
import type { NoncompliantPodError } from "../requester/results/error/NoncompliantPodError";
import { ErrorResult } from "@ldo/connected";
import { UnexpectedResourceError } from "@ldo/connected";
import type { SolidContainerUri } from "../types"; import type { SolidContainerUri } from "../types";
import { isSolidContainerUri } from "./isSolidUri"; import { isSolidContainerUri } from "./isSolidUri";

Loading…
Cancel
Save