parent
3c571a6098
commit
f11fcbda49
@ -1,3 +1,74 @@ |
||||
import type { Resource } from "@ldo/connected"; |
||||
import { |
||||
Unfetched, |
||||
type ConnectedResult, |
||||
type Resource, |
||||
type ResourceResult, |
||||
type SubscriptionCallbacks, |
||||
type ResourceEventEmitter, |
||||
} from "@ldo/connected"; |
||||
import type { NextGraphUri } from "../types"; |
||||
import EventEmitter from "events"; |
||||
|
||||
export class NextGraphResource implements Resource {} |
||||
export class NextGraphResource |
||||
extends (EventEmitter as new () => ResourceEventEmitter) |
||||
implements Resource<NextGraphUri> |
||||
{ |
||||
public readonly uri: NextGraphUri; |
||||
public readonly type = "NextGraphResource" as const; |
||||
public status: ConnectedResult; |
||||
|
||||
constructor(uri: NextGraphUri) { |
||||
super(); |
||||
this.uri = uri; |
||||
this.status = new Unfetched(this); |
||||
} |
||||
|
||||
isLoading(): boolean { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
isFetched(): boolean { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
isUnfetched(): boolean { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
isDoingInitialFetch(): boolean { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
isPresent(): boolean { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
isAbsent(): boolean { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
isSubscribedToNotifications(): boolean { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
read(): Promise<ResourceResult<this>> { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
readIfAbsent(): Promise<ResourceResult<this>> { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
subscribeToNotifications(callbacks?: SubscriptionCallbacks): Promise<string> { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
unsubscribeFromNotifications(subscriptionId: string): Promise<void> { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
unsubscribeFromAllNotifications(): Promise<void> { |
||||
throw new Error("Method not implemented."); |
||||
} |
||||
|
||||
} |
||||
|
@ -0,0 +1,64 @@ |
||||
import EventEmitter from "events"; |
||||
import type { Resource, ResourceEventEmitter } from "./Resource"; |
||||
import { InvalidUriError } from "./results/error/InvalidUriError"; |
||||
import type { SubscriptionCallbacks } from "./notifications/NotificationSubscription"; |
||||
|
||||
export class InvalidIdentifierResource |
||||
extends (EventEmitter as new () => ResourceEventEmitter) |
||||
implements Resource |
||||
{ |
||||
public readonly uri: string; |
||||
public readonly type = "InvalidIdentifierResouce" as const; |
||||
public status: InvalidUriError<this>; |
||||
|
||||
constructor(uri: string) { |
||||
super(); |
||||
this.uri = uri; |
||||
this.status = new InvalidUriError(this); |
||||
} |
||||
|
||||
isLoading(): boolean { |
||||
return false; |
||||
} |
||||
isFetched(): boolean { |
||||
return false; |
||||
} |
||||
isUnfetched(): boolean { |
||||
return true; |
||||
} |
||||
isDoingInitialFetch(): boolean { |
||||
return false; |
||||
} |
||||
isPresent(): boolean { |
||||
return false; |
||||
} |
||||
isAbsent(): boolean { |
||||
return true; |
||||
} |
||||
isSubscribedToNotifications(): boolean { |
||||
return false; |
||||
} |
||||
async read(): Promise<InvalidUriError<this>> { |
||||
return this.status; |
||||
} |
||||
async readIfAbsent(): Promise<InvalidUriError<this>> { |
||||
return this.status; |
||||
} |
||||
async createAndOverwrite(): Promise<InvalidUriError<this>> { |
||||
return this.status; |
||||
} |
||||
async createIfAbsent(): Promise<InvalidUriError<this>> { |
||||
return this.status; |
||||
} |
||||
async subscribeToNotifications( |
||||
_callbacks?: SubscriptionCallbacks, |
||||
): Promise<string> { |
||||
throw new Error("Cannot subscribe to an invalid resource."); |
||||
} |
||||
async unsubscribeFromNotifications(_subscriptionId: string): Promise<void> { |
||||
// Do Nothing
|
||||
} |
||||
async unsubscribeFromAllNotifications(): Promise<void> { |
||||
// Do Nothing
|
||||
} |
||||
} |
@ -1 +1,28 @@ |
||||
export interface Resource {} |
||||
import type TypedEmitter from "typed-emitter"; |
||||
import type { ConnectedResult } from "./results/ConnectedResult"; |
||||
import type { ResourceResult } from "./results/ResourceResult"; |
||||
import type { SubscriptionCallbacks } from "./notifications/NotificationSubscription"; |
||||
|
||||
export type ResourceEventEmitter = TypedEmitter<{ |
||||
update: () => void; |
||||
notification: () => void; |
||||
}>; |
||||
|
||||
export interface Resource<UriType extends string = string> |
||||
extends ResourceEventEmitter { |
||||
readonly uri: UriType; |
||||
readonly type: string; |
||||
status: ConnectedResult; |
||||
isLoading(): boolean; |
||||
isFetched(): boolean; |
||||
isUnfetched(): boolean; |
||||
isDoingInitialFetch(): boolean; |
||||
isPresent(): boolean; |
||||
isAbsent(): boolean; |
||||
isSubscribedToNotifications(): boolean; |
||||
read(): Promise<ResourceResult<this>>; |
||||
readIfAbsent(): Promise<ResourceResult<this>>; |
||||
subscribeToNotifications(callbacks?: SubscriptionCallbacks): Promise<string>; |
||||
unsubscribeFromNotifications(subscriptionId: string): Promise<void>; |
||||
unsubscribeFromAllNotifications(): Promise<void>; |
||||
} |
||||
|
@ -1,5 +1,13 @@ |
||||
import { ConnectedLdoDataset } from "./ConnectedLdoDataset"; |
||||
|
||||
export * from "./ConnectedLdoDataset"; |
||||
export * from "./ConnectedPlugin"; |
||||
export * from "./Resource"; |
||||
export * from "./InvalidIdentifierResource"; |
||||
|
||||
export * from "./notifications/NotificationMessage"; |
||||
export * from "./notifications/NotificationSubscription"; |
||||
|
||||
export * from "./results/ConnectedResult"; |
||||
export * from "./results/ResourceResult"; |
||||
export * from "./results/error/ErrorResult"; |
||||
export * from "./results/success/SuccessResult"; |
||||
export * from "./results/success/Unfetched"; |
||||
|
@ -0,0 +1,10 @@ |
||||
/** |
||||
* A message sent from the Pod as a notification |
||||
*/ |
||||
export interface NotificationMessage { |
||||
"@context": string | string[]; |
||||
id: string; |
||||
type: "Update" | "Delete" | "Remove" | "Add"; |
||||
object: string; |
||||
published: string; |
||||
} |
@ -0,0 +1,144 @@ |
||||
import type { SolidLdoDatasetContext } from "../../SolidLdoDatasetContext"; |
||||
import type { Resource } from "../Resource"; |
||||
import type { NotificationMessage } from "./NotificationMessage"; |
||||
import type { NotificationCallbackError } from "./results/NotificationErrors"; |
||||
import { v4 } from "uuid"; |
||||
|
||||
export interface SubscriptionCallbacks { |
||||
onNotification?: (message: NotificationMessage) => void; |
||||
// TODO: make notification errors more specific
|
||||
onNotificationError?: (error: Error) => void; |
||||
} |
||||
|
||||
/** |
||||
* @internal |
||||
* Abstract class for notification subscription methods. |
||||
*/ |
||||
export abstract class NotificationSubscription { |
||||
protected resource: Resource; |
||||
protected parentSubscription: (message: NotificationMessage) => void; |
||||
protected context: SolidLdoDatasetContext; |
||||
protected subscriptions: Record<string, SubscriptionCallbacks> = {}; |
||||
private isOpen: boolean = false; |
||||
|
||||
constructor( |
||||
resource: Resource, |
||||
parentSubscription: (message: NotificationMessage) => void, |
||||
context: SolidLdoDatasetContext, |
||||
) { |
||||
this.resource = resource; |
||||
this.parentSubscription = parentSubscription; |
||||
this.context = context; |
||||
} |
||||
|
||||
public isSubscribedToNotifications(): boolean { |
||||
return this.isOpen; |
||||
} |
||||
|
||||
/** |
||||
* =========================================================================== |
||||
* PUBLIC |
||||
* =========================================================================== |
||||
*/ |
||||
|
||||
/** |
||||
* @internal |
||||
* subscribeToNotifications |
||||
*/ |
||||
async subscribeToNotifications( |
||||
subscriptionCallbacks?: SubscriptionCallbacks, |
||||
): Promise<string> { |
||||
const subscriptionId = v4(); |
||||
this.subscriptions[subscriptionId] = subscriptionCallbacks ?? {}; |
||||
if (!this.isOpen) { |
||||
await this.open(); |
||||
this.setIsOpen(true); |
||||
} |
||||
return subscriptionId; |
||||
} |
||||
|
||||
/** |
||||
* @internal |
||||
* unsubscribeFromNotification |
||||
*/ |
||||
async unsubscribeFromNotification(subscriptionId: string): Promise<void> { |
||||
if ( |
||||
!!this.subscriptions[subscriptionId] && |
||||
Object.keys(this.subscriptions).length === 1 |
||||
) { |
||||
await this.close(); |
||||
this.setIsOpen(false); |
||||
} |
||||
delete this.subscriptions[subscriptionId]; |
||||
} |
||||
|
||||
/** |
||||
* @internal |
||||
* unsubscribeFromAllNotifications |
||||
*/ |
||||
async unsubscribeFromAllNotifications(): Promise<void> { |
||||
await Promise.all( |
||||
Object.keys(this.subscriptions).map((id) => |
||||
this.unsubscribeFromNotification(id), |
||||
), |
||||
); |
||||
} |
||||
|
||||
/** |
||||
* =========================================================================== |
||||
* HELPERS |
||||
* =========================================================================== |
||||
*/ |
||||
|
||||
/** |
||||
* @internal |
||||
* Opens the subscription |
||||
*/ |
||||
protected abstract open(): Promise<void>; |
||||
|
||||
/** |
||||
* @internal |
||||
* Closes the subscription |
||||
*/ |
||||
protected abstract close(): Promise<void>; |
||||
|
||||
/** |
||||
* =========================================================================== |
||||
* CALLBACKS |
||||
* =========================================================================== |
||||
*/ |
||||
|
||||
/** |
||||
* @internal |
||||
* onNotification |
||||
*/ |
||||
protected onNotification(message: NotificationMessage): void { |
||||
this.parentSubscription(message); |
||||
Object.values(this.subscriptions).forEach(({ onNotification }) => { |
||||
onNotification?.(message); |
||||
}); |
||||
} |
||||
|
||||
/** |
||||
* @internal |
||||
* onNotificationError |
||||
*/ |
||||
protected onNotificationError(message: NotificationCallbackError): void { |
||||
Object.values(this.subscriptions).forEach(({ onNotificationError }) => { |
||||
onNotificationError?.(message); |
||||
}); |
||||
if (message.type === "disconnectedNotAttemptingReconnectError") { |
||||
this.setIsOpen(false); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* @internal |
||||
* setIsOpen |
||||
*/ |
||||
protected setIsOpen(status: boolean) { |
||||
const shouldUpdate = status !== this.isOpen; |
||||
this.isOpen = status; |
||||
if (shouldUpdate) this.resource.emit("update"); |
||||
} |
||||
} |
@ -0,0 +1,30 @@ |
||||
import type { UnexpectedResourceError } from "../../../requester/results/error/ErrorResult"; |
||||
import { ResourceError } from "../../../requester/results/error/ErrorResult"; |
||||
|
||||
export type NotificationCallbackError = |
||||
| DisconnectedAttemptingReconnectError |
||||
| DisconnectedNotAttemptingReconnectError |
||||
| UnsupportedNotificationError |
||||
| UnexpectedResourceError; |
||||
|
||||
/** |
||||
* Indicates that the requested method for receiving notifications is not |
||||
* supported by this Pod. |
||||
*/ |
||||
export class UnsupportedNotificationError extends ResourceError { |
||||
readonly type = "unsupportedNotificationError" as const; |
||||
} |
||||
|
||||
/** |
||||
* Indicates that the socket has disconnected and is attempting to reconnect. |
||||
*/ |
||||
export class DisconnectedAttemptingReconnectError extends ResourceError { |
||||
readonly type = "disconnectedAttemptingReconnectError" as const; |
||||
} |
||||
|
||||
/** |
||||
* Indicates that the socket has disconnected and is attempting to reconnect. |
||||
*/ |
||||
export class DisconnectedNotAttemptingReconnectError extends ResourceError { |
||||
readonly type = "disconnectedNotAttemptingReconnectError" as const; |
||||
} |
@ -0,0 +1,7 @@ |
||||
/** |
||||
* A type returned by all request functions |
||||
*/ |
||||
export interface ConnectedResult { |
||||
readonly type: string; |
||||
readonly isError: boolean; |
||||
} |
@ -0,0 +1,7 @@ |
||||
import type { Resource } from "../Resource"; |
||||
import type { ResourceError } from "./error/ErrorResult"; |
||||
import type { ResourceSuccess } from "./success/SuccessResult"; |
||||
|
||||
export type ResourceResult<ResourceType extends Resource> = |
||||
| ResourceSuccess<ResourceType> |
||||
| ResourceError<ResourceType>; |
@ -0,0 +1,139 @@ |
||||
import type { Resource } from "../../Resource"; |
||||
import type { ConnectedResult } from "../ConnectedResult"; |
||||
|
||||
/** |
||||
* A result indicating that the request failed in some kind of way |
||||
*/ |
||||
export abstract class ErrorResult extends Error implements ConnectedResult { |
||||
/** |
||||
* Indicates the specific type of error |
||||
*/ |
||||
abstract readonly type: string; |
||||
|
||||
/** |
||||
* Always true |
||||
*/ |
||||
readonly isError = true as const; |
||||
|
||||
/** |
||||
* @param message - a custom message for the error |
||||
*/ |
||||
constructor(message?: string) { |
||||
super(message || "An unkown error was encountered."); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* An error for a specific resource |
||||
*/ |
||||
export abstract class ResourceError< |
||||
ResourceType extends Resource, |
||||
> extends ErrorResult { |
||||
/** |
||||
* The URI of the resource |
||||
*/ |
||||
readonly uri: ResourceType["uri"]; |
||||
|
||||
/** |
||||
* The resource that failed |
||||
*/ |
||||
readonly resource: ResourceType; |
||||
|
||||
/** |
||||
* @param uri - The URI of the resource |
||||
* @param message - A custom message for the error |
||||
*/ |
||||
constructor(resource: ResourceType, message?: string) { |
||||
super(message || `An unkown error for ${resource.uri}`); |
||||
this.uri = resource.uri; |
||||
this.resource = resource; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* An error that aggregates many errors |
||||
*/ |
||||
export class AggregateError<ErrorType extends ErrorResult> extends ErrorResult { |
||||
readonly type = "aggregateError" as const; |
||||
|
||||
/** |
||||
* A list of all errors returned |
||||
*/ |
||||
readonly errors: ErrorType[]; |
||||
|
||||
/** |
||||
* @param errors - List of all errors returned |
||||
* @param message - A custom message for the error |
||||
*/ |
||||
constructor( |
||||
errors: (ErrorType | AggregateError<ErrorType>)[], |
||||
message?: string, |
||||
) { |
||||
const allErrors: ErrorType[] = []; |
||||
errors.forEach((error) => { |
||||
if (error instanceof AggregateError) { |
||||
error.errors.forEach((subError) => { |
||||
allErrors.push(subError); |
||||
}); |
||||
} else { |
||||
allErrors.push(error); |
||||
} |
||||
}); |
||||
super( |
||||
message || |
||||
`Encountered multiple errors:${allErrors.reduce( |
||||
(agg, cur) => `${agg}\n${cur}`, |
||||
"", |
||||
)}`,
|
||||
); |
||||
this.errors = allErrors; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Represents some error that isn't handled under other errors. This is usually |
||||
* returned when something threw an error that LDO did not expect. |
||||
*/ |
||||
export class UnexpectedResourceError< |
||||
ResourceType extends Resource, |
||||
> extends ResourceError<ResourceType> { |
||||
readonly type = "unexpectedResourceError" as const; |
||||
|
||||
/** |
||||
* The error that was thrown |
||||
*/ |
||||
error: Error; |
||||
|
||||
/** |
||||
* @param uri - URI of the resource |
||||
* @param error - The error that was thrown |
||||
*/ |
||||
constructor(resource: ResourceType, error: Error) { |
||||
super(resource, error.message); |
||||
this.error = error; |
||||
} |
||||
|
||||
/** |
||||
* @internal |
||||
* |
||||
* Creates an UnexpectedResourceError from a thrown error |
||||
* @param uri - The URI of the resource |
||||
* @param err - The thrown error |
||||
* @returns an UnexpectedResourceError |
||||
*/ |
||||
static fromThrown<ResourceType extends Resource>( |
||||
resource: ResourceType, |
||||
err: unknown, |
||||
): UnexpectedResourceError<ResourceType> { |
||||
if (err instanceof Error) { |
||||
return new UnexpectedResourceError(resource, err); |
||||
} else if (typeof err === "string") { |
||||
return new UnexpectedResourceError(resource, new Error(err)); |
||||
} else { |
||||
return new UnexpectedResourceError( |
||||
resource, |
||||
new Error(`Error of type ${typeof err} thrown: ${err}`), |
||||
); |
||||
} |
||||
} |
||||
} |
@ -0,0 +1,16 @@ |
||||
import type { Resource } from "../../Resource"; |
||||
import { ResourceError } from "./ErrorResult"; |
||||
|
||||
/** |
||||
* An InvalidUriError is returned when a URI was provided that is not a valid |
||||
* URI. |
||||
*/ |
||||
export class InvalidUriError< |
||||
ResourceType extends Resource, |
||||
> extends ResourceError<ResourceType> { |
||||
readonly type = "invalidUriError" as const; |
||||
|
||||
constructor(resource: ResourceType, message?: string) { |
||||
super(resource, message || `${resource.uri} is an invalid uri.`); |
||||
} |
||||
} |
@ -0,0 +1,19 @@ |
||||
import type { Container } from "../../../resource/Container"; |
||||
import type { ResourceSuccess, SuccessResult } from "./SuccessResult"; |
||||
|
||||
/** |
||||
* Indicates that the request to check if a resource is the root container was |
||||
* a success. |
||||
*/ |
||||
export interface CheckRootContainerSuccess extends ResourceSuccess { |
||||
type: "checkRootContainerSuccess"; |
||||
/** |
||||
* True if this resoure is the root container |
||||
*/ |
||||
isRootContainer: boolean; |
||||
} |
||||
|
||||
export interface GetStorageContainerFromWebIdSuccess extends SuccessResult { |
||||
type: "getStorageContainerFromWebIdSuccess"; |
||||
storageContainers: Container[]; |
||||
} |
@ -0,0 +1,13 @@ |
||||
import type { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
/** |
||||
* Indicates that the request to create the resource was a success. |
||||
*/ |
||||
export interface CreateSuccess extends ResourceSuccess { |
||||
type: "createSuccess"; |
||||
/** |
||||
* True if there was a resource that existed before at the given URI that was |
||||
* overwritten |
||||
*/ |
||||
didOverwrite: boolean; |
||||
} |
@ -0,0 +1,14 @@ |
||||
import type { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
/** |
||||
* Indicates that the request to delete a resource was a success. |
||||
*/ |
||||
export interface DeleteSuccess extends ResourceSuccess { |
||||
type: "deleteSuccess"; |
||||
|
||||
/** |
||||
* True if there was a resource at the provided URI that was deleted. False if |
||||
* a resource didn't exist. |
||||
*/ |
||||
resourceExisted: boolean; |
||||
} |
@ -0,0 +1,71 @@ |
||||
import type { ResourceSuccess, SuccessResult } from "./SuccessResult"; |
||||
|
||||
/** |
||||
* Indicates that the request to read a resource was a success |
||||
*/ |
||||
export interface ReadSuccess extends ResourceSuccess { |
||||
/** |
||||
* True if the resource was recalled from local memory rather than a recent |
||||
* request |
||||
*/ |
||||
recalledFromMemory: boolean; |
||||
} |
||||
|
||||
/** |
||||
* Indicates that the read request was successful and that the resource |
||||
* retrieved was a binary resource. |
||||
*/ |
||||
export interface BinaryReadSuccess extends ReadSuccess { |
||||
type: "binaryReadSuccess"; |
||||
/** |
||||
* The raw data for the binary resource |
||||
*/ |
||||
blob: Blob; |
||||
/** |
||||
* The mime type of the binary resource |
||||
*/ |
||||
mimeType: string; |
||||
} |
||||
|
||||
/** |
||||
* Indicates that the read request was successful and that the resource |
||||
* retrieved was a data (RDF) resource. |
||||
*/ |
||||
export interface DataReadSuccess extends ReadSuccess { |
||||
type: "dataReadSuccess"; |
||||
} |
||||
|
||||
/** |
||||
* Indicates that the read request was successful and that the resource |
||||
* retrieved was a container resource. |
||||
*/ |
||||
export interface ContainerReadSuccess extends ReadSuccess { |
||||
type: "containerReadSuccess"; |
||||
/** |
||||
* True if this container is a root container |
||||
*/ |
||||
isRootContainer: boolean; |
||||
} |
||||
|
||||
/** |
||||
* Indicates that the read request was successful, but no resource exists at |
||||
* the provided URI. |
||||
*/ |
||||
export interface AbsentReadSuccess extends ReadSuccess { |
||||
type: "absentReadSuccess"; |
||||
} |
||||
|
||||
/** |
||||
* A helper function that checks to see if a result is a ReadSuccess result |
||||
* |
||||
* @param result - the result to check |
||||
* @returns true if the result is a ReadSuccessResult result |
||||
*/ |
||||
export function isReadSuccess(result: SuccessResult): result is ReadSuccess { |
||||
return ( |
||||
result.type === "binaryReadSuccess" || |
||||
result.type === "dataReadSuccess" || |
||||
result.type === "absentReadSuccess" || |
||||
result.type === "containerReadSuccess" |
||||
); |
||||
} |
@ -0,0 +1,51 @@ |
||||
import type { Resource } from "../../Resource"; |
||||
import type { ConnectedResult } from "../ConnectedResult"; |
||||
|
||||
/** |
||||
* Indicates that some action taken by LDO was a success |
||||
*/ |
||||
export abstract class SuccessResult implements ConnectedResult { |
||||
abstract readonly type: string; |
||||
readonly isError = false as const; |
||||
} |
||||
|
||||
/** |
||||
* Indicates that a request to a resource was aa success |
||||
*/ |
||||
export abstract class ResourceSuccess< |
||||
ResourceType extends Resource, |
||||
> extends SuccessResult { |
||||
/** |
||||
* The URI of the resource |
||||
*/ |
||||
uri: ResourceType["uri"]; |
||||
/** |
||||
* The resource that was successful |
||||
*/ |
||||
resource: Resource; |
||||
|
||||
constructor(resource: ResourceType) { |
||||
super(); |
||||
this.uri = resource.uri; |
||||
this.resource = resource; |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* A grouping of multiple successes as a result of an action |
||||
*/ |
||||
export class AggregateSuccess< |
||||
SuccessType extends SuccessResult, |
||||
> extends SuccessResult { |
||||
type = "aggregateSuccess" as const; |
||||
|
||||
/** |
||||
* An array of all successesses |
||||
*/ |
||||
results: SuccessType[]; |
||||
|
||||
constructor(results: SuccessType[]) { |
||||
super(); |
||||
this.results = results; |
||||
} |
||||
} |
@ -0,0 +1,11 @@ |
||||
import type { Resource } from "../../Resource"; |
||||
import { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
/** |
||||
* Indicates that a specific resource is unfetched |
||||
*/ |
||||
export class Unfetched< |
||||
ResourceType extends Resource, |
||||
> extends ResourceSuccess<ResourceType> { |
||||
readonly type = "unfetched" as const; |
||||
} |
@ -0,0 +1,24 @@ |
||||
import type { ResourceSuccess } from "./SuccessResult"; |
||||
|
||||
/** |
||||
* Indicates that an update request to a resource was successful |
||||
*/ |
||||
export interface UpdateSuccess extends ResourceSuccess { |
||||
type: "updateSuccess"; |
||||
} |
||||
|
||||
/** |
||||
* Indicates that an update request to the default graph was successful. This |
||||
* data was not written to a Pod. It was only written locally. |
||||
*/ |
||||
export interface UpdateDefaultGraphSuccess extends ResourceSuccess { |
||||
type: "updateDefaultGraphSuccess"; |
||||
} |
||||
|
||||
/** |
||||
* Indicates that LDO ignored an invalid update (usually because a container |
||||
* attempted an update) |
||||
*/ |
||||
export interface IgnoredInvalidUpdateSuccess extends ResourceSuccess { |
||||
type: "ignoredInvalidUpdateSuccess"; |
||||
} |
Loading…
Reference in new issue