@salesforce/lds-drafts 0.131.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.txt +82 -0
- package/dist/ldsDrafts.js +1718 -0
- package/dist/types/DraftAwareAdapter.d.ts +6 -0
- package/dist/types/DraftFetchResponse.d.ts +28 -0
- package/dist/types/DraftIdMapping.d.ts +12 -0
- package/dist/types/DraftManager.d.ts +161 -0
- package/dist/types/DraftQueue.d.ts +236 -0
- package/dist/types/DraftStore.d.ts +11 -0
- package/dist/types/DraftSynthesisError.d.ts +6 -0
- package/dist/types/DurableDraftQueue.d.ts +55 -0
- package/dist/types/DurableDraftStore.d.ts +43 -0
- package/dist/types/actionHandlers/AbstractResourceRequestActionHandler.d.ts +57 -0
- package/dist/types/actionHandlers/ActionHandler.d.ts +148 -0
- package/dist/types/actionHandlers/CustomActionHandler.d.ts +33 -0
- package/dist/types/main.d.ts +15 -0
- package/dist/types/makeEnvironmentDraftAware.d.ts +4 -0
- package/dist/types/utils/adapter.d.ts +2 -0
- package/dist/types/utils/clone.d.ts +1 -0
- package/dist/types/utils/id.d.ts +5 -0
- package/dist/types/utils/language.d.ts +24 -0
- package/package.json +31 -0
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { DispatchResourceRequestContext, Luvio, Snapshot } from '@luvio/engine';
|
|
2
|
+
import type { AbstractResourceRequestActionHandler } from './actionHandlers/AbstractResourceRequestActionHandler';
|
|
3
|
+
export type AdapterBuildNetworkSnapshot<Config, Response> = (luvio: Luvio, config: Config, dispatchResourceRequestContext?: DispatchResourceRequestContext) => Promise<Snapshot<Response>>;
|
|
4
|
+
export declare function buildLuvioOverrideForDraftAdapters<ResponseType = unknown, DraftMetadata = unknown>(luvio: Luvio, handler: AbstractResourceRequestActionHandler<ResponseType, DraftMetadata>, extractTargetIdFromCacheKey: (cacheKey: string) => string | undefined, options?: {
|
|
5
|
+
forDeleteAdapter?: boolean;
|
|
6
|
+
}): Luvio;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { FetchErrorResponse, FetchResponse, Headers } from '@luvio/engine';
|
|
2
|
+
import { HttpStatusCode } from '@luvio/engine';
|
|
3
|
+
import type { DraftSynthesisErrorType, DraftSynthesisError } from './DraftSynthesisError';
|
|
4
|
+
export declare const DRAFT_ERROR_CODE = "DRAFT_ERROR";
|
|
5
|
+
export declare class DraftFetchResponse<T> implements FetchResponse<T> {
|
|
6
|
+
status: HttpStatusCode;
|
|
7
|
+
body: T;
|
|
8
|
+
headers: Headers;
|
|
9
|
+
constructor(status: HttpStatusCode, body: T);
|
|
10
|
+
get statusText(): string;
|
|
11
|
+
get ok(): boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare class DraftErrorFetchResponse implements FetchErrorResponse {
|
|
14
|
+
status: HttpStatusCode;
|
|
15
|
+
body: unknown;
|
|
16
|
+
ok: boolean;
|
|
17
|
+
headers: Headers;
|
|
18
|
+
errorType: 'fetchResponse';
|
|
19
|
+
constructor(status: HttpStatusCode.BadRequest | HttpStatusCode.ServerError | HttpStatusCode.NotFound, body: unknown);
|
|
20
|
+
get statusText(): string;
|
|
21
|
+
}
|
|
22
|
+
export declare function createOkResponse<T>(body: T): DraftFetchResponse<T>;
|
|
23
|
+
export declare function createBadRequestResponse(body: unknown): DraftErrorFetchResponse;
|
|
24
|
+
export declare function createNotFoundResponse(body: unknown): DraftErrorFetchResponse;
|
|
25
|
+
export declare function transformErrorToDraftSynthesisError(error: Error | DraftSynthesisError<unknown>): DraftErrorFetchResponse;
|
|
26
|
+
export declare function createDraftSynthesisErrorResponse(message?: string, errorType?: DraftSynthesisErrorType): DraftErrorFetchResponse;
|
|
27
|
+
export declare function createDeletedResponse(): DraftFetchResponse<void>;
|
|
28
|
+
export declare function createInternalErrorResponse(): DraftErrorFetchResponse;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { DurableStore } from '@luvio/environments';
|
|
2
|
+
export interface DraftKeyMapping {
|
|
3
|
+
draftKey: string;
|
|
4
|
+
canonicalKey: string;
|
|
5
|
+
}
|
|
6
|
+
export declare const DRAFT_ID_MAPPINGS_SEGMENT = "DRAFT_ID_MAPPINGS";
|
|
7
|
+
/**
|
|
8
|
+
*
|
|
9
|
+
* @param mappingIds (optional) requested mapping ids, if undefined all will be retrieved
|
|
10
|
+
*/
|
|
11
|
+
export declare function getDraftIdMappings(durableStore: DurableStore, mappingIds?: string[]): Promise<DraftKeyMapping[]>;
|
|
12
|
+
export declare function clearDraftIdSegment(durableStore: DurableStore): Promise<void>;
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import type { CustomActionResult } from './actionHandlers/CustomActionHandler';
|
|
2
|
+
import type { DraftActionStatus, DraftQueue, DraftActionMetadata } from './DraftQueue';
|
|
3
|
+
import { DraftQueueState } from './DraftQueue';
|
|
4
|
+
/**
|
|
5
|
+
* Representation of the current state of the draft queue.
|
|
6
|
+
* Includes the overall state as well as a list of draft
|
|
7
|
+
* items that are currently in the queue.
|
|
8
|
+
*/
|
|
9
|
+
export interface DraftManagerState {
|
|
10
|
+
queueState: DraftQueueState;
|
|
11
|
+
items: DraftQueueItem[];
|
|
12
|
+
}
|
|
13
|
+
export type DraftQueueItemMetadata = {
|
|
14
|
+
[key: string]: string;
|
|
15
|
+
};
|
|
16
|
+
export type DraftManagerCustomActionExecutor = (item: DraftQueueItem, completed: (result: CustomActionResult) => void) => void;
|
|
17
|
+
/**
|
|
18
|
+
* An item in the draft queue that loosely maps to
|
|
19
|
+
* a DraftAction
|
|
20
|
+
*/
|
|
21
|
+
export interface DraftQueueItem {
|
|
22
|
+
/** The id of the Draft Action Item */
|
|
23
|
+
id: string;
|
|
24
|
+
/** The unique id of the target item */
|
|
25
|
+
targetId?: string;
|
|
26
|
+
/** The current status of this item */
|
|
27
|
+
state: DraftActionStatus;
|
|
28
|
+
/** The type of operation this item represents */
|
|
29
|
+
operationType: DraftActionOperationType;
|
|
30
|
+
/** Timestamp as unix epoch time */
|
|
31
|
+
timestamp: number;
|
|
32
|
+
/** undefined unless item is in an error state */
|
|
33
|
+
error?: undefined | DraftQueueItemError;
|
|
34
|
+
/** The stored metadata for the draft queue item */
|
|
35
|
+
metadata: DraftQueueItemMetadata;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* An error of a draft action that was submitted and failed
|
|
39
|
+
*/
|
|
40
|
+
export interface DraftQueueItemError {
|
|
41
|
+
/** The status code of the response */
|
|
42
|
+
status: number;
|
|
43
|
+
/** The headers of the response */
|
|
44
|
+
headers: {
|
|
45
|
+
[key: string]: string;
|
|
46
|
+
};
|
|
47
|
+
/** A flag representing the status of the response */
|
|
48
|
+
ok: boolean;
|
|
49
|
+
/** A summary of the response */
|
|
50
|
+
statusText: string;
|
|
51
|
+
/** A stringified object representing the body of the response */
|
|
52
|
+
bodyString: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Denotes what kind of operation a DraftQueueItem represents.
|
|
56
|
+
*/
|
|
57
|
+
export declare enum DraftActionOperationType {
|
|
58
|
+
Create = "create",
|
|
59
|
+
Update = "update",
|
|
60
|
+
Delete = "delete",
|
|
61
|
+
Custom = "custom"
|
|
62
|
+
}
|
|
63
|
+
export declare enum DraftQueueOperationType {
|
|
64
|
+
ItemAdded = "added",
|
|
65
|
+
ItemDeleted = "deleted",
|
|
66
|
+
ItemCompleted = "completed",
|
|
67
|
+
ItemFailed = "failed",
|
|
68
|
+
ItemUpdated = "updated",
|
|
69
|
+
QueueStarted = "started",
|
|
70
|
+
QueueStopped = "stopped"
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* A closure that draft queue change listeners pass to
|
|
74
|
+
* receive updates when the draft queue changes.
|
|
75
|
+
*/
|
|
76
|
+
export declare type DraftQueueListener = (state: DraftManagerState, operationType: DraftQueueOperationType, queueItem?: DraftQueueItem) => void;
|
|
77
|
+
export declare class DraftManager {
|
|
78
|
+
private draftQueue;
|
|
79
|
+
private listeners;
|
|
80
|
+
constructor(draftQueue: DraftQueue);
|
|
81
|
+
private shouldEmitDraftEvent;
|
|
82
|
+
private draftQueueEventTypeToOperationType;
|
|
83
|
+
private draftQueueStateToOperationType;
|
|
84
|
+
/**
|
|
85
|
+
* Enqueue a custom action on the DraftQueue for a handler
|
|
86
|
+
* @param handler the handler's id
|
|
87
|
+
* @param targetId
|
|
88
|
+
* @param tag - the key to group with in durable store
|
|
89
|
+
* @param metadata
|
|
90
|
+
* @returns
|
|
91
|
+
*/
|
|
92
|
+
addCustomAction(handler: string, targetId: string, tag: string, metadata: DraftActionMetadata): Promise<DraftQueueItem>;
|
|
93
|
+
/**
|
|
94
|
+
* Get the current state of each of the DraftActions in the DraftQueue
|
|
95
|
+
* @returns A promise of an array of the state of each item in the DraftQueue
|
|
96
|
+
*/
|
|
97
|
+
getQueue(): Promise<DraftManagerState>;
|
|
98
|
+
/**
|
|
99
|
+
* Starts the draft queue and begins processing the first item in the queue.
|
|
100
|
+
*/
|
|
101
|
+
startQueue(): Promise<void>;
|
|
102
|
+
/**
|
|
103
|
+
* Stops the draft queue from processing more draft items after any current
|
|
104
|
+
* in progress items are finished.
|
|
105
|
+
*/
|
|
106
|
+
stopQueue(): Promise<void>;
|
|
107
|
+
/**
|
|
108
|
+
* Subscribes the listener to changes to the draft queue.
|
|
109
|
+
*
|
|
110
|
+
* Returns a closure to invoke in order to unsubscribe the listener
|
|
111
|
+
* from changes to the draft queue.
|
|
112
|
+
*
|
|
113
|
+
* @param listener The listener closure to subscribe to changes
|
|
114
|
+
*/
|
|
115
|
+
registerDraftQueueChangedListener(listener: DraftQueueListener): () => Promise<void>;
|
|
116
|
+
/**
|
|
117
|
+
* Creates a custom action handler for the given handler
|
|
118
|
+
* @param handlerId
|
|
119
|
+
* @param executor
|
|
120
|
+
* @returns
|
|
121
|
+
*/
|
|
122
|
+
setCustomActionExecutor(handlerId: string, executor: DraftManagerCustomActionExecutor): Promise<() => Promise<void>>;
|
|
123
|
+
private buildDraftQueueItem;
|
|
124
|
+
private callListeners;
|
|
125
|
+
/**
|
|
126
|
+
* Removes the draft action identified by actionId from the draft queue.
|
|
127
|
+
*
|
|
128
|
+
* @param actionId The action identifier
|
|
129
|
+
*
|
|
130
|
+
* @returns The current state of the draft queue
|
|
131
|
+
*/
|
|
132
|
+
removeDraftAction(actionId: string): Promise<DraftManagerState>;
|
|
133
|
+
/**
|
|
134
|
+
* Replaces the resource request of `withAction` for the resource request
|
|
135
|
+
* of `actionId`. Action ids cannot be equal. Both actions must be acting
|
|
136
|
+
* on the same target object, and neither can currently be in progress.
|
|
137
|
+
*
|
|
138
|
+
* @param actionId The id of the draft action to replace
|
|
139
|
+
* @param withActionId The id of the draft action that will replace the other
|
|
140
|
+
*/
|
|
141
|
+
replaceAction(actionId: string, withActionId: string): Promise<DraftQueueItem>;
|
|
142
|
+
/**
|
|
143
|
+
* Merges two actions into a single target action. The target action maintains
|
|
144
|
+
* its position in the queue, while the source action is removed from the queue.
|
|
145
|
+
* Action ids cannot be equal. Both actions must be acting on the same target
|
|
146
|
+
* object, and neither can currently be in progress.
|
|
147
|
+
*
|
|
148
|
+
* @param targetActionId The draft action id of the target action. This action
|
|
149
|
+
* will be replaced with the merged result.
|
|
150
|
+
* @param sourceActionId The draft action id to merge onto the target. This
|
|
151
|
+
* action will be removed after the merge.
|
|
152
|
+
*/
|
|
153
|
+
mergeActions(targetActionId: string, sourceActionId: string): Promise<DraftQueueItem>;
|
|
154
|
+
/**
|
|
155
|
+
* Sets the metadata object of the specified action to the
|
|
156
|
+
* provided metadata
|
|
157
|
+
* @param actionId The id of the action to set the metadata on
|
|
158
|
+
* @param metadata The metadata to set on the specified action
|
|
159
|
+
*/
|
|
160
|
+
setMetadata(actionId: string, metadata: DraftQueueItemMetadata): Promise<DraftQueueItem>;
|
|
161
|
+
}
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import type { FetchResponse } from '@luvio/engine';
|
|
2
|
+
import type { ActionHandler } from './actionHandlers/ActionHandler';
|
|
3
|
+
import type { CustomActionExecutor } from './actionHandlers/CustomActionHandler';
|
|
4
|
+
export declare enum DraftActionStatus {
|
|
5
|
+
Pending = "pending",
|
|
6
|
+
Uploading = "uploading",
|
|
7
|
+
Error = "error",
|
|
8
|
+
Completed = "completed"
|
|
9
|
+
}
|
|
10
|
+
export type DraftActionMetadata = {
|
|
11
|
+
[key: string]: string;
|
|
12
|
+
};
|
|
13
|
+
interface BaseDraftAction<Data> {
|
|
14
|
+
status: DraftActionStatus;
|
|
15
|
+
id: string;
|
|
16
|
+
/** Timestamp as unix epoch time */
|
|
17
|
+
timestamp: number;
|
|
18
|
+
metadata: DraftActionMetadata;
|
|
19
|
+
/** typically the cache key */
|
|
20
|
+
targetId: string;
|
|
21
|
+
/** typically the unique record ID */
|
|
22
|
+
tag: string;
|
|
23
|
+
/** the handlerId */
|
|
24
|
+
handler: string;
|
|
25
|
+
/** the data being enqueued */
|
|
26
|
+
data: Data;
|
|
27
|
+
version: '242.0.0';
|
|
28
|
+
}
|
|
29
|
+
export interface CompletedDraftAction<Data, Response> extends BaseDraftAction<Data> {
|
|
30
|
+
status: DraftActionStatus.Completed;
|
|
31
|
+
response: FetchResponse<Response>;
|
|
32
|
+
}
|
|
33
|
+
export interface PendingDraftAction<Data> extends BaseDraftAction<Data> {
|
|
34
|
+
status: DraftActionStatus.Pending;
|
|
35
|
+
}
|
|
36
|
+
export interface ErrorDraftAction<Data> extends BaseDraftAction<Data> {
|
|
37
|
+
status: DraftActionStatus.Error;
|
|
38
|
+
error: any;
|
|
39
|
+
}
|
|
40
|
+
export interface UploadingDraftAction<Data> extends BaseDraftAction<Data> {
|
|
41
|
+
status: DraftActionStatus.Uploading;
|
|
42
|
+
}
|
|
43
|
+
export declare function isDraftCompleted<Data, Response>(draft: BaseDraftAction<Data>): draft is CompletedDraftAction<Data, Response>;
|
|
44
|
+
export declare function isDraftError<Data>(draft: BaseDraftAction<Data>): draft is ErrorDraftAction<Data>;
|
|
45
|
+
export declare function isDraftQueueStateChangeEvent(event: DraftQueueEvent): event is DraftQueueStateChangedEvent;
|
|
46
|
+
export type DraftAction<Data, Response> = CompletedDraftAction<Data, Response> | PendingDraftAction<Data> | ErrorDraftAction<Data> | UploadingDraftAction<Data>;
|
|
47
|
+
export type DraftQueueChangeListener = (event: DraftQueueEvent) => Promise<void>;
|
|
48
|
+
export declare enum ProcessActionResult {
|
|
49
|
+
ACTION_ERRORED = "ERROR",
|
|
50
|
+
ACTION_SUCCEEDED = "SUCCESS",
|
|
51
|
+
NO_ACTION_TO_PROCESS = "NO_ACTION_TO_PROCESS",
|
|
52
|
+
ACTION_ALREADY_PROCESSING = "ACTION_ALREADY_PROCESSING",
|
|
53
|
+
NETWORK_ERROR = "NETWORK_ERROR",
|
|
54
|
+
BLOCKED_ON_ERROR = "BLOCKED_ON_ERROR",
|
|
55
|
+
CUSTOM_ACTION_WAITING = "CUSTOM_ACTION_WAITING"
|
|
56
|
+
}
|
|
57
|
+
export declare enum DraftQueueState {
|
|
58
|
+
/** Currently processing an item in the queue or queue is empty and waiting to process the next item. */
|
|
59
|
+
Started = "started",
|
|
60
|
+
/**
|
|
61
|
+
* The queue is stopped and will not attempt to upload any drafts until startDraftQueue() is called.
|
|
62
|
+
* This is the initial state when the DraftQueue gets instantiated.
|
|
63
|
+
*/
|
|
64
|
+
Stopped = "stopped",
|
|
65
|
+
/**
|
|
66
|
+
* The queue is stopped due to a blocking error from the last upload attempt.
|
|
67
|
+
* The queue will not run again until startDraftQueue() is called.
|
|
68
|
+
*/
|
|
69
|
+
Error = "error",
|
|
70
|
+
/**
|
|
71
|
+
* There was a network error and the queue will attempt to upload again shortly.
|
|
72
|
+
* To attempt to force an upload now call startDraftQueue().
|
|
73
|
+
*/
|
|
74
|
+
Waiting = "waiting"
|
|
75
|
+
}
|
|
76
|
+
export declare enum DraftQueueEventType {
|
|
77
|
+
/**
|
|
78
|
+
* Triggered after an action had been added to the queue
|
|
79
|
+
*/
|
|
80
|
+
ActionAdded = "added",
|
|
81
|
+
/**
|
|
82
|
+
* Triggered once an action failed
|
|
83
|
+
*/
|
|
84
|
+
ActionFailed = "failed",
|
|
85
|
+
/**
|
|
86
|
+
* Triggered after an action has been deleted from the queue
|
|
87
|
+
*/
|
|
88
|
+
ActionDeleted = "deleted",
|
|
89
|
+
/**
|
|
90
|
+
* Triggered after an action has been completed and after it has been removed from the queue
|
|
91
|
+
*/
|
|
92
|
+
ActionCompleted = "completed",
|
|
93
|
+
/**
|
|
94
|
+
* Triggered after an action has been updated by the updateAction API
|
|
95
|
+
*/
|
|
96
|
+
ActionUpdated = "updated",
|
|
97
|
+
/**
|
|
98
|
+
* Triggered after the Draft Queue state changes
|
|
99
|
+
*/
|
|
100
|
+
QueueStateChanged = "state"
|
|
101
|
+
}
|
|
102
|
+
export interface DraftQueueAddEvent {
|
|
103
|
+
type: DraftQueueEventType.ActionAdded;
|
|
104
|
+
action: PendingDraftAction<unknown>;
|
|
105
|
+
}
|
|
106
|
+
export interface DraftQueueDeleteEvent {
|
|
107
|
+
type: DraftQueueEventType.ActionDeleted;
|
|
108
|
+
action: DraftAction<unknown, unknown>;
|
|
109
|
+
}
|
|
110
|
+
export interface DraftQueueCompleteEvent {
|
|
111
|
+
type: DraftQueueEventType.ActionCompleted;
|
|
112
|
+
action: CompletedDraftAction<unknown, unknown>;
|
|
113
|
+
}
|
|
114
|
+
export interface DraftQueueActionFailedEvent {
|
|
115
|
+
type: DraftQueueEventType.ActionFailed;
|
|
116
|
+
action: ErrorDraftAction<unknown>;
|
|
117
|
+
}
|
|
118
|
+
export interface DraftQueueActionUpdatedEvent {
|
|
119
|
+
type: DraftQueueEventType.ActionUpdated;
|
|
120
|
+
action: DraftAction<unknown, unknown>;
|
|
121
|
+
}
|
|
122
|
+
export interface DraftQueueStateChangedEvent {
|
|
123
|
+
type: DraftQueueEventType.QueueStateChanged;
|
|
124
|
+
state: DraftQueueState;
|
|
125
|
+
}
|
|
126
|
+
export type DraftQueueItemEvent = DraftQueueAddEvent | DraftQueueCompleteEvent | DraftQueueDeleteEvent | DraftQueueActionFailedEvent | DraftQueueActionUpdatedEvent;
|
|
127
|
+
export type DraftQueueEvent = DraftQueueStateChangedEvent | DraftQueueItemEvent;
|
|
128
|
+
export declare enum QueueOperationType {
|
|
129
|
+
Add = "add",
|
|
130
|
+
Delete = "delete",
|
|
131
|
+
Update = "update"
|
|
132
|
+
}
|
|
133
|
+
export interface AddQueueOperation {
|
|
134
|
+
type: QueueOperationType.Add;
|
|
135
|
+
action: DraftAction<unknown, unknown>;
|
|
136
|
+
}
|
|
137
|
+
export interface DeleteQueueOperation {
|
|
138
|
+
type: QueueOperationType.Delete;
|
|
139
|
+
id: string;
|
|
140
|
+
}
|
|
141
|
+
export interface UpdateQueueOperation {
|
|
142
|
+
type: QueueOperationType.Update;
|
|
143
|
+
id: string;
|
|
144
|
+
action: DraftAction<unknown, unknown>;
|
|
145
|
+
}
|
|
146
|
+
export type QueueOperation = UpdateQueueOperation | AddQueueOperation | DeleteQueueOperation;
|
|
147
|
+
export interface EnqueueResult<Data, Response> {
|
|
148
|
+
action: PendingDraftAction<Data>;
|
|
149
|
+
data: Response;
|
|
150
|
+
}
|
|
151
|
+
export interface DraftQueue {
|
|
152
|
+
/**
|
|
153
|
+
* Enqueues a draft action into the DraftQueue
|
|
154
|
+
* @param handlerId the id of the handler associated with the data
|
|
155
|
+
* @param data the data the handler will use to create the draft action with
|
|
156
|
+
* @returns A promise including the pending action created for the request and the data associated with the action
|
|
157
|
+
* @throws {Error} An error when a proper action handler is not found or conditions are not met to enqueue the action
|
|
158
|
+
*/
|
|
159
|
+
enqueue<Data, Response>(handlerId: string, data: Data): Promise<EnqueueResult<Data, Response>>;
|
|
160
|
+
/**
|
|
161
|
+
* add a new handler to the draft queue to process the data in the actions
|
|
162
|
+
* @param id identifier to the handler
|
|
163
|
+
* @param handler ActionHandler to process action
|
|
164
|
+
*/
|
|
165
|
+
addHandler<Data, Type>(handler: ActionHandler<Data, unknown, Type>): Promise<void>;
|
|
166
|
+
/**
|
|
167
|
+
* Creates a ActionHandler<CustomActionData> with a callback to let the DraftQueue know when it has been processed
|
|
168
|
+
* @param id identifier of the handler
|
|
169
|
+
* @param executor callback to inform DraftQueue it is complete
|
|
170
|
+
*/
|
|
171
|
+
addCustomHandler(id: string, executor: CustomActionExecutor): Promise<void>;
|
|
172
|
+
/**
|
|
173
|
+
* Removes an added ActionHandler
|
|
174
|
+
* @param id identifier of the handler
|
|
175
|
+
*/
|
|
176
|
+
removeHandler(id: string): Promise<void>;
|
|
177
|
+
/**
|
|
178
|
+
* Registers a listener to be notified when the Draft Queue changes
|
|
179
|
+
* @param listener Listener to notify when the draft queue changes, with an optional parameter
|
|
180
|
+
* for a completed DraftAction that triggered the change.
|
|
181
|
+
*/
|
|
182
|
+
registerOnChangedListener(listener: DraftQueueChangeListener): () => Promise<void>;
|
|
183
|
+
/**
|
|
184
|
+
* Processes the next action in the draft queue
|
|
185
|
+
*/
|
|
186
|
+
processNextAction(): Promise<ProcessActionResult>;
|
|
187
|
+
/**
|
|
188
|
+
* Get the current list of draft actions in queue
|
|
189
|
+
*/
|
|
190
|
+
getQueueActions(): Promise<DraftAction<unknown, unknown>[]>;
|
|
191
|
+
/** The current state of the DraftQueue */
|
|
192
|
+
getQueueState(): DraftQueueState;
|
|
193
|
+
/**
|
|
194
|
+
* Removes the draft action identified by actionId from the draft queue.
|
|
195
|
+
*
|
|
196
|
+
* @param actionId The action identifier
|
|
197
|
+
*/
|
|
198
|
+
removeDraftAction(actionId: string): Promise<void>;
|
|
199
|
+
/**
|
|
200
|
+
* Replaces the resource request of `withActionId` for the resource request
|
|
201
|
+
* of `actionId`. Action ids cannot be equal. Both actions must be acting
|
|
202
|
+
* on the same target object, and neither can currently be in progress.
|
|
203
|
+
*
|
|
204
|
+
* @param targetActionId The draft action id of the target action. This action
|
|
205
|
+
* will be replaced by the source action while maintaining its position in
|
|
206
|
+
* the queue.
|
|
207
|
+
* @param sourceActionId The draft action id of the source action. This
|
|
208
|
+
* action will replace the target action and will be removed from the queue.
|
|
209
|
+
*/
|
|
210
|
+
replaceAction<Data, Response>(targetActionId: string, sourceActionId: string): Promise<DraftAction<Data, Response>>;
|
|
211
|
+
/**
|
|
212
|
+
* Merges two actions into a single target action. The target action maintains
|
|
213
|
+
* its position in the queue, while the source action is removed from the queue.
|
|
214
|
+
* Action ids cannot be equal. Both actions must be acting on the same target
|
|
215
|
+
* object, and neither can currently be in progress.
|
|
216
|
+
*
|
|
217
|
+
* @param targetActionId The draft action id of the target action. This action
|
|
218
|
+
* will be replaced with the merged result.
|
|
219
|
+
* @param sourceActionId The draft action id to merge onto the target. This
|
|
220
|
+
* action will be removed after the merge.
|
|
221
|
+
*/
|
|
222
|
+
mergeActions<Data, Response>(targetActionId: string, sourceActionId: string): Promise<DraftAction<Data, Response>>;
|
|
223
|
+
/** Set the draft queue state to Started and process the next item */
|
|
224
|
+
startQueue(): Promise<void>;
|
|
225
|
+
/** Set the draft queue state to Stopped and don't let another item begin */
|
|
226
|
+
stopQueue(): Promise<void>;
|
|
227
|
+
/**
|
|
228
|
+
* Sets the metadata object of the specified action to the
|
|
229
|
+
* provided metadata
|
|
230
|
+
*
|
|
231
|
+
* @param actionId The id of the draft action to set metadata on
|
|
232
|
+
* @param metadata The metadata to set on the specified action
|
|
233
|
+
*/
|
|
234
|
+
setMetadata(actionId: string, metadata: DraftActionMetadata): Promise<DraftAction<unknown, unknown>>;
|
|
235
|
+
}
|
|
236
|
+
export {};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { DraftAction, QueueOperation } from './DraftQueue';
|
|
2
|
+
/**
|
|
3
|
+
* Defines the store where drafts are persisted
|
|
4
|
+
*/
|
|
5
|
+
export interface DraftStore {
|
|
6
|
+
writeAction(action: DraftAction<unknown, unknown>): Promise<void>;
|
|
7
|
+
getAllDrafts(): Promise<DraftAction<unknown, unknown>[]>;
|
|
8
|
+
deleteDraft(actionId: string): Promise<void>;
|
|
9
|
+
deleteByTag(tag: string): Promise<void>;
|
|
10
|
+
completeAction(queueOperations: QueueOperation[]): Promise<void>;
|
|
11
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type DraftSynthesisErrorType = 'MISSING_ID' | 'OBJECT_INFO_MISSING' | 'REFERENCED_RECORDS_MISSING' | 'UNEXPECTED_FIELDS' | 'RECORD_NOT_CACHED' | 'UNKNOWN';
|
|
2
|
+
export declare class DraftSynthesisError<T> extends Error {
|
|
3
|
+
errorType: T;
|
|
4
|
+
constructor(message: string, errorType: T);
|
|
5
|
+
}
|
|
6
|
+
export declare function isDraftSynthesisError<T>(error: Error): error is DraftSynthesisError<T>;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import type { DraftQueue, DraftAction, CompletedDraftAction, DraftQueueChangeListener, DraftActionMetadata, EnqueueResult } from './DraftQueue';
|
|
2
|
+
import { ProcessActionResult, DraftQueueState } from './DraftQueue';
|
|
3
|
+
import type { CustomActionExecutor } from './actionHandlers/CustomActionHandler';
|
|
4
|
+
import type { ActionHandler } from './actionHandlers/ActionHandler';
|
|
5
|
+
import type { DraftStore } from './DraftStore';
|
|
6
|
+
export declare const DRAFT_SEGMENT = "DRAFT";
|
|
7
|
+
export declare class DurableDraftQueue implements DraftQueue {
|
|
8
|
+
private retryIntervalMilliseconds;
|
|
9
|
+
private minimumRetryInterval;
|
|
10
|
+
private maximumRetryInterval;
|
|
11
|
+
private draftStore;
|
|
12
|
+
private draftQueueChangedListeners;
|
|
13
|
+
private state;
|
|
14
|
+
private userState;
|
|
15
|
+
private processingAction?;
|
|
16
|
+
private replacingAction?;
|
|
17
|
+
private uploadingActionId?;
|
|
18
|
+
private timeoutHandler;
|
|
19
|
+
private workerPool;
|
|
20
|
+
private handlers;
|
|
21
|
+
private getHandler;
|
|
22
|
+
constructor(draftStore: DraftStore);
|
|
23
|
+
addHandler<Data>(handler: ActionHandler<Data, unknown, unknown>): Promise<void>;
|
|
24
|
+
removeHandler(id: string): Promise<void>;
|
|
25
|
+
addCustomHandler(id: string, executor: CustomActionExecutor): Promise<void>;
|
|
26
|
+
getQueueState(): DraftQueueState;
|
|
27
|
+
startQueue(): Promise<void>;
|
|
28
|
+
stopQueue(): Promise<void>;
|
|
29
|
+
/**
|
|
30
|
+
* Used to stop the queue within DraftQueue without user interaction
|
|
31
|
+
*/
|
|
32
|
+
private stopQueueManually;
|
|
33
|
+
getQueueActions<Data = unknown, Response = unknown>(): Promise<DraftAction<Data, Response>[]>;
|
|
34
|
+
enqueue<Data, Response>(handlerId: string, data: unknown): Promise<EnqueueResult<Data, Response>>;
|
|
35
|
+
registerOnChangedListener(listener: DraftQueueChangeListener): () => Promise<void>;
|
|
36
|
+
actionCompleted(action: CompletedDraftAction<unknown, unknown>): Promise<void>;
|
|
37
|
+
actionFailed(action: DraftAction<unknown, unknown>, retry: boolean): Promise<void>;
|
|
38
|
+
handle(action: DraftAction<unknown, unknown>): Promise<ProcessActionResult>;
|
|
39
|
+
processNextAction(): Promise<ProcessActionResult>;
|
|
40
|
+
private handleServerError;
|
|
41
|
+
private notifyChangedListeners;
|
|
42
|
+
/**
|
|
43
|
+
* only starts the queue if user state is "Started" and if queue not already
|
|
44
|
+
* started
|
|
45
|
+
*/
|
|
46
|
+
private startQueueSafe;
|
|
47
|
+
removeDraftAction(actionId: string): Promise<void>;
|
|
48
|
+
replaceAction<Data, Response>(targetActionId: string, sourceActionId: string): Promise<DraftAction<Data, Response>>;
|
|
49
|
+
mergeActions<Data, Response>(targetActionId: string, sourceActionId: string): Promise<DraftAction<Data, Response>>;
|
|
50
|
+
setMetadata(actionId: string, metadata: DraftActionMetadata): Promise<DraftAction<unknown, unknown>>;
|
|
51
|
+
private scheduleRetry;
|
|
52
|
+
private getActionsForReplaceOrMerge;
|
|
53
|
+
private assertReplaceOrMergePrerequisites;
|
|
54
|
+
private replaceOrMergeActions;
|
|
55
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import type { DurableStore } from '@luvio/environments';
|
|
2
|
+
import type { DraftAction, QueueOperation } from './DraftQueue';
|
|
3
|
+
import type { DraftStore } from './DraftStore';
|
|
4
|
+
/**
|
|
5
|
+
* Implements a write-through InMemoryStore for Drafts, storing all drafts in a
|
|
6
|
+
* in-memory store with a write through to the DurableStore.
|
|
7
|
+
*
|
|
8
|
+
* Before any reads or writes come in from the draft queue, we need to revive the draft
|
|
9
|
+
* queue into memory. During this initial revive, any writes are queued up and operated on the
|
|
10
|
+
* queue once it's in memory. Similarly any reads are delayed until the queue is in memory.
|
|
11
|
+
*
|
|
12
|
+
*/
|
|
13
|
+
export declare class DurableDraftStore implements DraftStore {
|
|
14
|
+
private durableStore;
|
|
15
|
+
private draftStore;
|
|
16
|
+
private syncPromise;
|
|
17
|
+
private writeQueue;
|
|
18
|
+
constructor(durableStore: DurableStore);
|
|
19
|
+
writeAction(action: DraftAction<unknown, unknown>): Promise<void>;
|
|
20
|
+
getAllDrafts<_R, _D>(): Promise<DraftAction<unknown, unknown>[]>;
|
|
21
|
+
deleteDraft(id: string): Promise<void>;
|
|
22
|
+
deleteByTag(tag: string): Promise<void>;
|
|
23
|
+
completeAction(queueOperations: QueueOperation[]): Promise<void>;
|
|
24
|
+
/**
|
|
25
|
+
* Runs a write operation against the draft store, if the initial
|
|
26
|
+
* revive is still in progress, the action gets enqueued to run once the
|
|
27
|
+
* initial revive is complete
|
|
28
|
+
* @param action
|
|
29
|
+
* @returns a promise that is resolved once the action has run
|
|
30
|
+
*/
|
|
31
|
+
private enqueueAction;
|
|
32
|
+
/**
|
|
33
|
+
* Revives the draft store from the durable store. Once the draft store is
|
|
34
|
+
* revived, executes any queued up draft store operations that came in while
|
|
35
|
+
* reviving
|
|
36
|
+
*/
|
|
37
|
+
private resyncDraftStore;
|
|
38
|
+
/**
|
|
39
|
+
* Runs the operations that were queued up while reviving the
|
|
40
|
+
* draft store from the durable store
|
|
41
|
+
*/
|
|
42
|
+
private runQueuedOperations;
|
|
43
|
+
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { NetworkAdapter, ResourceRequest, Luvio, DurableStoreKeyMetadataMap } from '@luvio/engine';
|
|
2
|
+
import type { DraftAction, CompletedDraftAction, QueueOperation, PendingDraftAction, DraftActionMetadata, DraftQueue, EnqueueResult } from '../DraftQueue';
|
|
3
|
+
import { ProcessActionResult } from '../DraftQueue';
|
|
4
|
+
import type { ActionHandler, DraftIdAndKeyMapping } from './ActionHandler';
|
|
5
|
+
export type ResponseIngestionEntry<T = unknown> = {
|
|
6
|
+
response: T;
|
|
7
|
+
synchronousIngest: AbstractResourceRequestActionHandler<T, unknown>['synchronousIngest'];
|
|
8
|
+
buildCacheKeysForResponse: AbstractResourceRequestActionHandler<T, unknown>['buildCacheKeysFromResponse'];
|
|
9
|
+
};
|
|
10
|
+
export declare abstract class AbstractResourceRequestActionHandler<ResponseType, DraftMetadata> implements ActionHandler<ResourceRequest, DraftMetadata, ResponseType> {
|
|
11
|
+
protected readonly draftQueue: DraftQueue;
|
|
12
|
+
protected readonly networkAdapter: NetworkAdapter;
|
|
13
|
+
protected readonly getLuvio: () => Luvio;
|
|
14
|
+
ephemeralRedirects: {
|
|
15
|
+
[key: string]: string;
|
|
16
|
+
};
|
|
17
|
+
constructor(draftQueue: DraftQueue, networkAdapter: NetworkAdapter, getLuvio: () => Luvio);
|
|
18
|
+
enqueue(data: ResourceRequest): Promise<EnqueueResult<ResourceRequest, ResponseType>>;
|
|
19
|
+
handleAction(action: DraftAction<ResourceRequest, ResponseType>, actionCompleted: (action: CompletedDraftAction<ResourceRequest, ResponseType>) => Promise<void>, actionErrored: (action: DraftAction<ResourceRequest, ResponseType>, retry: boolean) => Promise<void>): Promise<ProcessActionResult>;
|
|
20
|
+
buildPendingAction(request: ResourceRequest, queue: DraftAction<unknown, unknown>[]): Promise<PendingDraftAction<ResourceRequest>>;
|
|
21
|
+
handleActionEnqueued(action: PendingDraftAction<ResourceRequest>): Promise<void>;
|
|
22
|
+
handleActionRemoved(action: DraftAction<ResourceRequest, ResponseType>): Promise<void>;
|
|
23
|
+
getQueueOperationsForCompletingDrafts(queue: DraftAction<unknown, unknown>[], action: CompletedDraftAction<ResourceRequest, ResponseType>): QueueOperation[];
|
|
24
|
+
getRedirectMappings(action: CompletedDraftAction<ResourceRequest, ResponseType>): DraftIdAndKeyMapping[] | undefined;
|
|
25
|
+
handleActionCompleted(action: CompletedDraftAction<ResourceRequest, ResponseType>, queueOperations: QueueOperation[], allHandlers: ActionHandler<unknown, unknown, unknown>[]): Promise<void>;
|
|
26
|
+
handleReplaceAction(targetAction: DraftAction<ResourceRequest, ResponseType>, sourceAction: DraftAction<ResourceRequest, ResponseType>): DraftAction<ResourceRequest, ResponseType>;
|
|
27
|
+
mergeActions(targetAction: DraftAction<ResourceRequest, ResponseType>, sourceAction: DraftAction<ResourceRequest, ResponseType>): DraftAction<ResourceRequest, ResponseType>;
|
|
28
|
+
shouldDeleteActionByTagOnRemoval(action: DraftAction<ResourceRequest, ResponseType>): boolean;
|
|
29
|
+
updateMetadata(_existingMetadata: DraftActionMetadata, incomingMetadata: DraftActionMetadata): DraftActionMetadata;
|
|
30
|
+
private isActionOfType;
|
|
31
|
+
protected reingestRecord(action: DraftAction<ResourceRequest, ResponseType>): Promise<void>;
|
|
32
|
+
getDraftIdsFromAction(action: DraftAction<ResourceRequest, ResponseType>): string[];
|
|
33
|
+
ingestResponses(responses: ResponseIngestionEntry[], action: DraftAction<ResourceRequest, ResponseType>): Promise<void>;
|
|
34
|
+
evictKey(key: string): Promise<void>;
|
|
35
|
+
abstract handlerId: string;
|
|
36
|
+
abstract canHandlePublish(key: string): boolean;
|
|
37
|
+
abstract canRepresentationContainDraftMetadata(representationName: string): boolean;
|
|
38
|
+
abstract getIdFromRequest(request: ResourceRequest): Promise<string | undefined>;
|
|
39
|
+
abstract getIdFromResponseBody(responseBody: ResponseType): string;
|
|
40
|
+
abstract buildTagForTargetId(id: string): string;
|
|
41
|
+
abstract buildCacheKeysFromResponse(response: ResponseType): DurableStoreKeyMetadataMap;
|
|
42
|
+
abstract synchronousIngest(response: ResponseType, action: DraftAction<ResourceRequest, ResponseType>): void;
|
|
43
|
+
abstract getDataForAction(action: DraftAction<ResourceRequest, ResponseType>): Promise<ResponseType | undefined>;
|
|
44
|
+
abstract getDraftMetadata(key: string): Promise<DraftMetadata | undefined>;
|
|
45
|
+
abstract applyDraftsToIncomingData(key: string, data: unknown, draftMetadata: DraftMetadata | undefined, publishFn: (key: string, data: any) => void): void;
|
|
46
|
+
/**
|
|
47
|
+
* Returns true if the given targetId is a for a draft-created record
|
|
48
|
+
*
|
|
49
|
+
* @param targetId the targetId to check
|
|
50
|
+
*/
|
|
51
|
+
abstract isDraftId(targetId: string): boolean;
|
|
52
|
+
/**
|
|
53
|
+
* Overlay the sourceBody over top of the targetBody
|
|
54
|
+
*/
|
|
55
|
+
abstract mergeRequestBody<T = unknown>(targetBody: T, sourceBody: T): T;
|
|
56
|
+
}
|
|
57
|
+
export declare function isResourceRequestAction(action: DraftAction<unknown, unknown>): action is DraftAction<ResourceRequest, unknown>;
|