@candidstartup/simple-spreadsheet-data 0.11.0 → 0.13.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/dist/index.d.ts +132 -14
- package/dist/index.js +371 -83
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { SpreadsheetData, ItemOffsetMapping, CellValue,
|
|
1
|
+
import { SpreadsheetData, Result, StorageError, ItemOffsetMapping, CellValue, CellFormat, ResultAsync, SpreadsheetDataError, ValidationError, SpreadsheetViewport, LogEntry, EventLog, PostMessageWorkerHost, PendingWorkflowMessage, SequenceId, AddEntryValue, AddEntryError, LogMetadata, MetadataError, QueryValue, QueryError, TruncateError, BlobDir, BlobName, ReadBlobError, WriteBlobError, RemoveBlobError, GetDirError, BlobDirEntries, DirQueryError, RemoveAllBlobDirError, BlobStore, GetRootDirError, WorkerMessage, InfiniSheetWorker, MessageHandler } from '@candidstartup/infinisheet-types';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Branding Enum. Used by {@link SimpleSnapshot} to ensure that
|
|
@@ -27,18 +27,23 @@ interface SimpleSnapshot {
|
|
|
27
27
|
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
28
28
|
*/
|
|
29
29
|
declare class SimpleSpreadsheetData implements SpreadsheetData<SimpleSnapshot> {
|
|
30
|
-
#private;
|
|
31
30
|
constructor();
|
|
32
31
|
subscribe(onDataChange: () => void): () => void;
|
|
33
32
|
getSnapshot(): SimpleSnapshot;
|
|
33
|
+
getLoadStatus(_snapshot: SimpleSnapshot): Result<boolean, StorageError>;
|
|
34
34
|
getRowCount(snapshot: SimpleSnapshot): number;
|
|
35
35
|
getRowItemOffsetMapping(_snapshot: SimpleSnapshot): ItemOffsetMapping;
|
|
36
36
|
getColumnCount(snapshot: SimpleSnapshot): number;
|
|
37
37
|
getColumnItemOffsetMapping(_snapshot: SimpleSnapshot): ItemOffsetMapping;
|
|
38
38
|
getCellValue(snapshot: SimpleSnapshot, row: number, column: number): CellValue;
|
|
39
|
-
getCellFormat(snapshot: SimpleSnapshot, row: number, column: number):
|
|
40
|
-
setCellValueAndFormat(row: number, column: number, value: CellValue, format:
|
|
41
|
-
isValidCellValueAndFormat(_row: number, _column: number, _value: CellValue, _format:
|
|
39
|
+
getCellFormat(snapshot: SimpleSnapshot, row: number, column: number): CellFormat;
|
|
40
|
+
setCellValueAndFormat(row: number, column: number, value: CellValue, format: CellFormat): ResultAsync<void, SpreadsheetDataError>;
|
|
41
|
+
isValidCellValueAndFormat(_row: number, _column: number, _value: CellValue, _format: CellFormat): Result<void, ValidationError>;
|
|
42
|
+
setViewport(viewport: SpreadsheetViewport | undefined): void;
|
|
43
|
+
getViewport(snapshot: SimpleSnapshot): SpreadsheetViewport | undefined;
|
|
44
|
+
private notifyListeners;
|
|
45
|
+
private listeners;
|
|
46
|
+
private content;
|
|
42
47
|
}
|
|
43
48
|
|
|
44
49
|
/**
|
|
@@ -76,7 +81,6 @@ type SnapshotType<T> = T extends SpreadsheetData<infer TResult> ? TResult : neve
|
|
|
76
81
|
* @typeParam EditSnapshot - Type of snapshot used by `EditData`. By default, inferred from `EditData`.
|
|
77
82
|
*/
|
|
78
83
|
declare class LayeredSpreadsheetData<BaseData extends SpreadsheetData<BaseSnapshot>, EditData extends SpreadsheetData<EditSnapshot>, BaseSnapshot = SnapshotType<BaseData>, EditSnapshot = SnapshotType<EditData>> implements SpreadsheetData<LayeredSnapshot<BaseSnapshot, EditSnapshot>> {
|
|
79
|
-
#private;
|
|
80
84
|
/**
|
|
81
85
|
* Creates a `LayeredSpreadsheetData` instance from two existing `SpreadsheetData` instances.
|
|
82
86
|
*
|
|
@@ -88,24 +92,138 @@ declare class LayeredSpreadsheetData<BaseData extends SpreadsheetData<BaseSnapsh
|
|
|
88
92
|
constructor(base: BaseData, edit: EditData);
|
|
89
93
|
subscribe(onDataChange: () => void): () => void;
|
|
90
94
|
getSnapshot(): LayeredSnapshot<BaseSnapshot, EditSnapshot>;
|
|
95
|
+
getLoadStatus(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): Result<boolean, StorageError>;
|
|
91
96
|
getRowCount(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): number;
|
|
92
97
|
getRowItemOffsetMapping(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): ItemOffsetMapping;
|
|
93
98
|
getColumnCount(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): number;
|
|
94
99
|
getColumnItemOffsetMapping(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): ItemOffsetMapping;
|
|
95
100
|
getCellValue(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>, row: number, column: number): CellValue;
|
|
96
|
-
getCellFormat(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>, row: number, column: number):
|
|
97
|
-
setCellValueAndFormat(row: number, column: number, value: CellValue, format:
|
|
98
|
-
isValidCellValueAndFormat(row: number, column: number, value: CellValue, format:
|
|
101
|
+
getCellFormat(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>, row: number, column: number): CellFormat;
|
|
102
|
+
setCellValueAndFormat(row: number, column: number, value: CellValue, format: CellFormat): ResultAsync<void, SpreadsheetDataError>;
|
|
103
|
+
isValidCellValueAndFormat(row: number, column: number, value: CellValue, format: CellFormat): Result<void, ValidationError>;
|
|
104
|
+
setViewport(viewport: SpreadsheetViewport | undefined): void;
|
|
105
|
+
getViewport(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): SpreadsheetViewport | undefined;
|
|
106
|
+
private base;
|
|
107
|
+
private edit;
|
|
108
|
+
private content;
|
|
99
109
|
}
|
|
100
110
|
|
|
111
|
+
/**
|
|
112
|
+
* Reference implementation of {@link EventLog}
|
|
113
|
+
*
|
|
114
|
+
* In-memory event log
|
|
115
|
+
*
|
|
116
|
+
* Intended for use as a mock, to compare with an optimized implementation when testing and
|
|
117
|
+
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
118
|
+
*/
|
|
101
119
|
declare class SimpleEventLog<T extends LogEntry> implements EventLog<T> {
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
120
|
+
constructor(workerHost?: PostMessageWorkerHost<PendingWorkflowMessage>);
|
|
121
|
+
/** Worker host used to process pending workflows */
|
|
122
|
+
workerHost?: PostMessageWorkerHost<PendingWorkflowMessage> | undefined;
|
|
123
|
+
addEntry(entry: T, sequenceId: SequenceId, snapshotId?: SequenceId): ResultAsync<AddEntryValue, AddEntryError>;
|
|
105
124
|
setMetadata(sequenceId: SequenceId, metadata: LogMetadata): ResultAsync<void, MetadataError>;
|
|
106
|
-
query(start: SequenceId | 'snapshot' | 'start', end: SequenceId | 'end'): ResultAsync<QueryValue<T>, QueryError>;
|
|
125
|
+
query(start: SequenceId | 'snapshot' | 'start', end: SequenceId | 'end', snapshotId?: SequenceId): ResultAsync<QueryValue<T>, QueryError>;
|
|
107
126
|
truncate(start: SequenceId): ResultAsync<void, TruncateError>;
|
|
127
|
+
private sendPendingWorkflowMessage;
|
|
128
|
+
private findSnapshot;
|
|
108
129
|
private findSnapshotIndex;
|
|
130
|
+
private startSequenceId;
|
|
131
|
+
private endSequenceId;
|
|
132
|
+
private entries;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/** Creates a promise that provides value after a delay (in ms) */
|
|
136
|
+
declare function delayPromise<T>(value: T, delay: number): Promise<T>;
|
|
137
|
+
declare function delayResult<T, E>(result: ResultAsync<T, E>, delay: number): ResultAsync<T, E>;
|
|
138
|
+
/**
|
|
139
|
+
* Wrapper around an {@link EventLog} that injects latency
|
|
140
|
+
*
|
|
141
|
+
* Intended for use when simulating the effects of latency in a real implementation
|
|
142
|
+
*/
|
|
143
|
+
declare class DelayEventLog<T extends LogEntry> implements EventLog<T> {
|
|
144
|
+
constructor(base: EventLog<T>, delay?: number);
|
|
145
|
+
/** Delay in milliseconds to add to response from each API call */
|
|
146
|
+
delay: number;
|
|
147
|
+
addEntry(entry: T, sequenceId: SequenceId, snapshotId?: SequenceId): ResultAsync<AddEntryValue, AddEntryError>;
|
|
148
|
+
setMetadata(sequenceId: SequenceId, metadata: LogMetadata): ResultAsync<void, MetadataError>;
|
|
149
|
+
query(start: SequenceId | 'snapshot' | 'start', end: SequenceId | 'end', snapshotId?: SequenceId): ResultAsync<QueryValue<T>, QueryError>;
|
|
150
|
+
truncate(start: SequenceId): ResultAsync<void, TruncateError>;
|
|
151
|
+
private base;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Branding Enum. Used by {@link SimpleBlobStore} to ensure that
|
|
156
|
+
* you'll get a type error if you pass some random object where a `SimpleBlobStoreContinuation`
|
|
157
|
+
* is expected.
|
|
158
|
+
* @internal
|
|
159
|
+
*/
|
|
160
|
+
declare enum _SimpleBlobStoreBrand {
|
|
161
|
+
_DO_NOT_USE = ""
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Opaque type representing a {@link SimpleSpreadsheetData} snapshot. All the
|
|
165
|
+
* internal implementation details are hidden from the exported API.
|
|
166
|
+
*/
|
|
167
|
+
interface SimpleBlobStoreContinuation {
|
|
168
|
+
/** @internal */
|
|
169
|
+
_brand: _SimpleBlobStoreBrand;
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Reference implementation of {@link BlobDir}
|
|
173
|
+
*
|
|
174
|
+
* Intended for use as a mock, to compare with an optimized implementation when testing and
|
|
175
|
+
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
176
|
+
*/
|
|
177
|
+
declare class SimpleBlobDir implements BlobDir<SimpleBlobStoreContinuation> {
|
|
178
|
+
constructor();
|
|
179
|
+
readBlob(name: BlobName): ResultAsync<Uint8Array, ReadBlobError>;
|
|
180
|
+
writeBlob(name: BlobName, content: Uint8Array): ResultAsync<void, WriteBlobError>;
|
|
181
|
+
removeBlob(name: BlobName): ResultAsync<void, RemoveBlobError>;
|
|
182
|
+
getDir(name: BlobName): ResultAsync<BlobDir<SimpleBlobStoreContinuation>, GetDirError>;
|
|
183
|
+
query(continuation?: SimpleBlobStoreContinuation): ResultAsync<BlobDirEntries<SimpleBlobStoreContinuation>, DirQueryError>;
|
|
184
|
+
removeAll(): ResultAsync<void, RemoveAllBlobDirError>;
|
|
185
|
+
private map;
|
|
186
|
+
}
|
|
187
|
+
/**
|
|
188
|
+
* Reference implementation of {@link BlobStore}
|
|
189
|
+
*
|
|
190
|
+
* Intended for use as a mock, to compare with an optimized implementation when testing and
|
|
191
|
+
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
192
|
+
*/
|
|
193
|
+
declare class SimpleBlobStore implements BlobStore<SimpleBlobStoreContinuation> {
|
|
194
|
+
constructor();
|
|
195
|
+
getRootDir(): ResultAsync<SimpleBlobDir, GetRootDirError>;
|
|
196
|
+
private root;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Reference implementation of {@link InfiniSheetWorker}
|
|
201
|
+
*
|
|
202
|
+
* In-process event loop based workers
|
|
203
|
+
*
|
|
204
|
+
* Intended for use as a mock, to compare with an optimized implementation when testing and
|
|
205
|
+
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
206
|
+
*/
|
|
207
|
+
declare class SimpleWorker<T extends WorkerMessage> implements InfiniSheetWorker<T> {
|
|
208
|
+
constructor();
|
|
209
|
+
onReceiveMessage: MessageHandler<T> | undefined;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Reference implementation of {@link PostMessageWorkerHost}
|
|
213
|
+
*
|
|
214
|
+
* In-process event loop based workers
|
|
215
|
+
*
|
|
216
|
+
* Intended for use as a mock, to compare with an optimized implementation when testing and
|
|
217
|
+
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
218
|
+
*/
|
|
219
|
+
declare class SimpleWorkerHost<T extends WorkerMessage> implements PostMessageWorkerHost<T> {
|
|
220
|
+
constructor(worker: SimpleWorker<T>, delay?: number);
|
|
221
|
+
/** @internal */
|
|
222
|
+
isHost(): this is PostMessageWorkerHost<T>;
|
|
223
|
+
postMessage(message: T): void;
|
|
224
|
+
private worker;
|
|
225
|
+
private delay;
|
|
109
226
|
}
|
|
110
227
|
|
|
111
|
-
export {
|
|
228
|
+
export { DelayEventLog, LayeredSpreadsheetData, SimpleBlobDir, SimpleBlobStore, SimpleEventLog, SimpleSpreadsheetData, SimpleWorker, SimpleWorkerHost, _LayeredSnapshotBrand, _SimpleBlobStoreBrand, _SimpleSnapshotBrand, delayPromise, delayResult };
|
|
229
|
+
export type { LayeredSnapshot, SimpleBlobStoreContinuation, SimpleSnapshot, SnapshotType };
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { FixedSizeItemOffsetMapping, rowColCoordsToRef,
|
|
1
|
+
import { FixedSizeItemOffsetMapping, ok, rowColCoordsToRef, okAsync, equalViewports, errAsync, conflictError, infinisheetRangeError, ResultAsync, invalidBlobNameError, storageError, notBlobError, notBlobDirError, noContinuationError } from '@candidstartup/infinisheet-types';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
4
|
* Branding Enum. Used by {@link SimpleSnapshot} to ensure that
|
|
@@ -29,21 +29,25 @@ function asSnapshot$1(snapshot) {
|
|
|
29
29
|
*/
|
|
30
30
|
class SimpleSpreadsheetData {
|
|
31
31
|
constructor() {
|
|
32
|
-
this
|
|
33
|
-
this
|
|
32
|
+
this.listeners = [];
|
|
33
|
+
this.content = {
|
|
34
34
|
values: {},
|
|
35
35
|
rowCount: 0,
|
|
36
|
-
colCount: 0
|
|
36
|
+
colCount: 0,
|
|
37
|
+
viewport: undefined
|
|
37
38
|
};
|
|
38
39
|
}
|
|
39
40
|
subscribe(onDataChange) {
|
|
40
|
-
this
|
|
41
|
+
this.listeners = [...this.listeners, onDataChange];
|
|
41
42
|
return () => {
|
|
42
|
-
this
|
|
43
|
+
this.listeners = this.listeners.filter(l => l !== onDataChange);
|
|
43
44
|
};
|
|
44
45
|
}
|
|
45
46
|
getSnapshot() {
|
|
46
|
-
return asSnapshot$1(this
|
|
47
|
+
return asSnapshot$1(this.content);
|
|
48
|
+
}
|
|
49
|
+
getLoadStatus(_snapshot) {
|
|
50
|
+
return ok(true);
|
|
47
51
|
}
|
|
48
52
|
getRowCount(snapshot) {
|
|
49
53
|
return asContent$1(snapshot).rowCount;
|
|
@@ -66,29 +70,39 @@ class SimpleSpreadsheetData {
|
|
|
66
70
|
return asContent$1(snapshot).values[ref]?.format;
|
|
67
71
|
}
|
|
68
72
|
setCellValueAndFormat(row, column, value, format) {
|
|
69
|
-
const curr = this
|
|
73
|
+
const curr = this.content;
|
|
70
74
|
const ref = rowColCoordsToRef(row, column);
|
|
71
75
|
// Snapshot semantics preserved by treating SimpleSnapshot as an immutable data structure which is
|
|
72
76
|
// replaced with a modified copy on every update. Yes, this is horribly inefficient.
|
|
73
77
|
// For simplicity, setting a value to undefined stores it explicitly rather than removing it. Functional
|
|
74
78
|
// behavior is the same.
|
|
75
|
-
this
|
|
79
|
+
this.content = {
|
|
76
80
|
values: { ...curr.values, [ref]: { value, format } },
|
|
77
81
|
rowCount: Math.max(curr.rowCount, row + 1),
|
|
78
|
-
colCount: Math.max(curr.colCount, column + 1)
|
|
82
|
+
colCount: Math.max(curr.colCount, column + 1),
|
|
83
|
+
viewport: curr.viewport
|
|
79
84
|
};
|
|
80
|
-
this
|
|
81
|
-
return ok();
|
|
85
|
+
return okAsync().andTee(() => this.notifyListeners());
|
|
82
86
|
}
|
|
83
87
|
isValidCellValueAndFormat(_row, _column, _value, _format) {
|
|
84
88
|
return ok();
|
|
85
89
|
}
|
|
86
|
-
|
|
87
|
-
|
|
90
|
+
setViewport(viewport) {
|
|
91
|
+
const curr = this.content;
|
|
92
|
+
if (equalViewports(curr.viewport, viewport))
|
|
93
|
+
return;
|
|
94
|
+
this.content = { ...curr, viewport };
|
|
95
|
+
this.notifyListeners();
|
|
96
|
+
}
|
|
97
|
+
getViewport(snapshot) {
|
|
98
|
+
return asContent$1(snapshot).viewport;
|
|
99
|
+
}
|
|
100
|
+
notifyListeners() {
|
|
101
|
+
for (const listener of this.listeners)
|
|
88
102
|
listener();
|
|
89
103
|
}
|
|
90
|
-
|
|
91
|
-
|
|
104
|
+
listeners;
|
|
105
|
+
content;
|
|
92
106
|
}
|
|
93
107
|
|
|
94
108
|
/**
|
|
@@ -130,146 +144,420 @@ class LayeredSpreadsheetData {
|
|
|
130
144
|
* @param edit - `SpreadsheetData` instance to use for the edit layer
|
|
131
145
|
*/
|
|
132
146
|
constructor(base, edit) {
|
|
133
|
-
this
|
|
134
|
-
this
|
|
147
|
+
this.base = base;
|
|
148
|
+
this.edit = edit;
|
|
135
149
|
}
|
|
136
150
|
subscribe(onDataChange) {
|
|
137
|
-
const unsubscribeBase = this
|
|
138
|
-
const unsubscribeEdit = this
|
|
151
|
+
const unsubscribeBase = this.base.subscribe(onDataChange);
|
|
152
|
+
const unsubscribeEdit = this.edit.subscribe(onDataChange);
|
|
139
153
|
return () => {
|
|
140
154
|
unsubscribeBase();
|
|
141
155
|
unsubscribeEdit();
|
|
142
156
|
};
|
|
143
157
|
}
|
|
144
158
|
getSnapshot() {
|
|
145
|
-
const baseSnapshot = this
|
|
146
|
-
const editSnapshot = this
|
|
147
|
-
if (!this
|
|
148
|
-
this
|
|
159
|
+
const baseSnapshot = this.base.getSnapshot();
|
|
160
|
+
const editSnapshot = this.edit.getSnapshot();
|
|
161
|
+
if (!this.content || this.content.base != baseSnapshot || this.content.edit != editSnapshot) {
|
|
162
|
+
this.content = { base: baseSnapshot, edit: editSnapshot };
|
|
149
163
|
}
|
|
150
|
-
return asSnapshot(this
|
|
164
|
+
return asSnapshot(this.content);
|
|
165
|
+
}
|
|
166
|
+
getLoadStatus(snapshot) {
|
|
167
|
+
const content = asContent(snapshot);
|
|
168
|
+
return this.base.getLoadStatus(content.base).andThen((t1) => this.edit.getLoadStatus(content.edit).map((t2) => t1 && t2));
|
|
151
169
|
}
|
|
152
170
|
getRowCount(snapshot) {
|
|
153
171
|
const content = asContent(snapshot);
|
|
154
|
-
return Math.max(this
|
|
172
|
+
return Math.max(this.base.getRowCount(content.base), this.edit.getRowCount(content.edit));
|
|
155
173
|
}
|
|
156
174
|
getRowItemOffsetMapping(snapshot) {
|
|
157
|
-
return this
|
|
175
|
+
return this.base.getRowItemOffsetMapping(asContent(snapshot).base);
|
|
158
176
|
}
|
|
159
177
|
getColumnCount(snapshot) {
|
|
160
178
|
const content = asContent(snapshot);
|
|
161
|
-
return Math.max(this
|
|
179
|
+
return Math.max(this.base.getColumnCount(content.base), this.edit.getColumnCount(content.edit));
|
|
162
180
|
}
|
|
163
181
|
getColumnItemOffsetMapping(snapshot) {
|
|
164
|
-
return this
|
|
182
|
+
return this.base.getColumnItemOffsetMapping(asContent(snapshot).base);
|
|
165
183
|
}
|
|
166
184
|
getCellValue(snapshot, row, column) {
|
|
167
185
|
const content = asContent(snapshot);
|
|
168
|
-
const editValue = this
|
|
186
|
+
const editValue = this.edit.getCellValue(content.edit, row, column);
|
|
169
187
|
if (editValue !== undefined)
|
|
170
188
|
return editValue;
|
|
171
|
-
return this
|
|
189
|
+
return this.base.getCellValue(content.base, row, column);
|
|
172
190
|
}
|
|
173
191
|
getCellFormat(snapshot, row, column) {
|
|
174
192
|
const content = asContent(snapshot);
|
|
175
|
-
const editValue = this
|
|
176
|
-
return (editValue === undefined) ? this
|
|
193
|
+
const editValue = this.edit.getCellValue(content.edit, row, column);
|
|
194
|
+
return (editValue === undefined) ? this.base.getCellFormat(content.base, row, column) : this.edit.getCellFormat(content.edit, row, column);
|
|
177
195
|
}
|
|
178
196
|
setCellValueAndFormat(row, column, value, format) {
|
|
179
|
-
const result = this
|
|
180
|
-
return result.
|
|
197
|
+
const result = this.base.isValidCellValueAndFormat(row, column, value, format);
|
|
198
|
+
return result.asyncAndThen(() => this.edit.setCellValueAndFormat(row, column, value, format));
|
|
181
199
|
}
|
|
182
200
|
// Must be valid for both layers
|
|
183
201
|
isValidCellValueAndFormat(row, column, value, format) {
|
|
184
|
-
const result = this
|
|
185
|
-
return result.andThen(() => this
|
|
202
|
+
const result = this.base.isValidCellValueAndFormat(row, column, value, format);
|
|
203
|
+
return result.andThen(() => this.edit.isValidCellValueAndFormat(row, column, value, format));
|
|
204
|
+
}
|
|
205
|
+
setViewport(viewport) {
|
|
206
|
+
this.base.setViewport(viewport);
|
|
207
|
+
this.edit.setViewport(viewport);
|
|
186
208
|
}
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
209
|
+
getViewport(snapshot) {
|
|
210
|
+
const content = asContent(snapshot);
|
|
211
|
+
return this.edit.getViewport(content.edit);
|
|
212
|
+
}
|
|
213
|
+
base;
|
|
214
|
+
edit;
|
|
215
|
+
content;
|
|
190
216
|
}
|
|
191
217
|
|
|
192
|
-
const QUERY_PAGE_SIZE = 10;
|
|
218
|
+
const QUERY_PAGE_SIZE$1 = 10;
|
|
219
|
+
/**
|
|
220
|
+
* Reference implementation of {@link EventLog}
|
|
221
|
+
*
|
|
222
|
+
* In-memory event log
|
|
223
|
+
*
|
|
224
|
+
* Intended for use as a mock, to compare with an optimized implementation when testing and
|
|
225
|
+
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
226
|
+
*/
|
|
193
227
|
class SimpleEventLog {
|
|
194
|
-
constructor() {
|
|
195
|
-
this
|
|
196
|
-
this
|
|
197
|
-
this
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
this
|
|
204
|
-
|
|
228
|
+
constructor(workerHost) {
|
|
229
|
+
this.workerHost = workerHost;
|
|
230
|
+
this.startSequenceId = 0n;
|
|
231
|
+
this.endSequenceId = 0n;
|
|
232
|
+
this.entries = [];
|
|
233
|
+
}
|
|
234
|
+
/** Worker host used to process pending workflows */
|
|
235
|
+
workerHost;
|
|
236
|
+
addEntry(entry, sequenceId, snapshotId) {
|
|
237
|
+
if (sequenceId !== this.endSequenceId)
|
|
238
|
+
return errAsync(conflictError("sequenceId is not next sequence id", this.endSequenceId));
|
|
239
|
+
this.entries.push(entry);
|
|
240
|
+
this.endSequenceId++;
|
|
241
|
+
if (entry.pending)
|
|
242
|
+
this.sendPendingWorkflowMessage(entry.pending, sequenceId);
|
|
243
|
+
const value = {};
|
|
244
|
+
if (snapshotId !== undefined) {
|
|
245
|
+
const snapshot = this.findSnapshot();
|
|
246
|
+
if (snapshot && snapshot.sequenceId !== snapshotId)
|
|
247
|
+
value.lastSnapshot = snapshot;
|
|
248
|
+
}
|
|
249
|
+
return okAsync(value);
|
|
205
250
|
}
|
|
206
251
|
setMetadata(sequenceId, metadata) {
|
|
207
|
-
if (sequenceId < this
|
|
252
|
+
if (sequenceId < this.startSequenceId || sequenceId >= this.endSequenceId)
|
|
208
253
|
return errAsync(infinisheetRangeError(`Log entry with sequenceId ${sequenceId} does not exist`));
|
|
209
|
-
const index = Number(sequenceId - this
|
|
210
|
-
const entry = this
|
|
254
|
+
const index = Number(sequenceId - this.startSequenceId);
|
|
255
|
+
const entry = this.entries[index];
|
|
211
256
|
if ("snapshot" in metadata)
|
|
212
257
|
entry.snapshot = metadata.snapshot;
|
|
213
258
|
if ("history" in metadata)
|
|
214
259
|
entry.history = metadata.history;
|
|
215
|
-
if ("pending" in metadata)
|
|
260
|
+
if ("pending" in metadata) {
|
|
216
261
|
entry.pending = metadata.pending;
|
|
262
|
+
if (entry.pending)
|
|
263
|
+
this.sendPendingWorkflowMessage(entry.pending, sequenceId);
|
|
264
|
+
}
|
|
217
265
|
return okAsync();
|
|
218
266
|
}
|
|
219
|
-
query(start, end) {
|
|
267
|
+
query(start, end, snapshotId) {
|
|
220
268
|
if (start === 'start')
|
|
221
|
-
start = this
|
|
269
|
+
start = this.startSequenceId;
|
|
222
270
|
else if (start === 'snapshot')
|
|
223
|
-
start = this
|
|
224
|
-
else if (start < this
|
|
271
|
+
start = this.startSequenceId + BigInt(this.findSnapshotIndex());
|
|
272
|
+
else if (start < this.startSequenceId || start > this.endSequenceId)
|
|
225
273
|
return errAsync(infinisheetRangeError("start index out of range"));
|
|
226
274
|
if (end === 'end')
|
|
227
|
-
end = this
|
|
275
|
+
end = this.endSequenceId;
|
|
228
276
|
const num = end - start;
|
|
229
|
-
const isComplete = num <= BigInt(QUERY_PAGE_SIZE);
|
|
230
|
-
let numToReturn = isComplete ? Number(num) : QUERY_PAGE_SIZE;
|
|
231
|
-
const firstIndex = Number(start - this
|
|
232
|
-
if (firstIndex + numToReturn > this
|
|
233
|
-
numToReturn = this
|
|
277
|
+
const isComplete = num <= BigInt(QUERY_PAGE_SIZE$1);
|
|
278
|
+
let numToReturn = isComplete ? Number(num) : QUERY_PAGE_SIZE$1;
|
|
279
|
+
const firstIndex = Number(start - this.startSequenceId);
|
|
280
|
+
if (firstIndex + numToReturn > this.entries.length)
|
|
281
|
+
numToReturn = this.entries.length - firstIndex;
|
|
234
282
|
const value = {
|
|
235
283
|
startSequenceId: start,
|
|
236
284
|
endSequenceId: start + BigInt(numToReturn),
|
|
237
285
|
isComplete,
|
|
238
|
-
entries: this
|
|
286
|
+
entries: this.entries.slice(firstIndex, firstIndex + numToReturn)
|
|
239
287
|
};
|
|
288
|
+
if (snapshotId !== undefined) {
|
|
289
|
+
const snapshot = this.findSnapshot();
|
|
290
|
+
if (snapshot && snapshot.sequenceId !== snapshotId)
|
|
291
|
+
value.lastSnapshot = snapshot;
|
|
292
|
+
}
|
|
240
293
|
return okAsync(value);
|
|
241
294
|
}
|
|
242
295
|
truncate(start) {
|
|
243
|
-
if (start < this
|
|
296
|
+
if (start < this.startSequenceId)
|
|
244
297
|
return errAsync(infinisheetRangeError("start before start entry in the log"));
|
|
245
|
-
if (start === this
|
|
298
|
+
if (start === this.startSequenceId)
|
|
246
299
|
return okAsync();
|
|
247
|
-
if (start === this
|
|
248
|
-
this
|
|
249
|
-
this
|
|
250
|
-
this
|
|
300
|
+
if (start === this.endSequenceId) {
|
|
301
|
+
this.startSequenceId = start;
|
|
302
|
+
this.endSequenceId = start;
|
|
303
|
+
this.entries = [];
|
|
251
304
|
return okAsync();
|
|
252
305
|
}
|
|
253
|
-
if (start > this
|
|
306
|
+
if (start > this.endSequenceId)
|
|
254
307
|
return errAsync(infinisheetRangeError("start after end entry in the log"));
|
|
255
|
-
const numToRemove = start - this
|
|
256
|
-
this
|
|
257
|
-
this
|
|
308
|
+
const numToRemove = start - this.startSequenceId;
|
|
309
|
+
this.startSequenceId = start;
|
|
310
|
+
this.entries.splice(0, Number(numToRemove));
|
|
258
311
|
return okAsync();
|
|
259
312
|
}
|
|
313
|
+
sendPendingWorkflowMessage(workflow, sequenceId) {
|
|
314
|
+
if (this.workerHost) {
|
|
315
|
+
const message = { type: 'PendingWorkflowMessage', sequenceId, workflow };
|
|
316
|
+
this.workerHost.postMessage(message);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
findSnapshot() {
|
|
320
|
+
for (let i = this.entries.length - 1; i > 0; i--) {
|
|
321
|
+
const entry = this.entries[i];
|
|
322
|
+
if (entry.snapshot) {
|
|
323
|
+
return { sequenceId: this.startSequenceId + BigInt(i), blobId: entry.snapshot };
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
return undefined;
|
|
327
|
+
}
|
|
260
328
|
findSnapshotIndex() {
|
|
261
|
-
for (let i = this
|
|
262
|
-
const entry = this
|
|
329
|
+
for (let i = this.entries.length - 1; i > 0; i--) {
|
|
330
|
+
const entry = this.entries[i];
|
|
263
331
|
if (entry.snapshot)
|
|
264
332
|
return i;
|
|
265
333
|
}
|
|
266
334
|
// If no other entry has a snapshot use the first (whether it has a snapshot or not)
|
|
267
335
|
return 0;
|
|
268
336
|
}
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
337
|
+
startSequenceId;
|
|
338
|
+
endSequenceId;
|
|
339
|
+
entries;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/** Creates a promise that provides value after a delay (in ms) */
|
|
343
|
+
function delayPromise(value, delay) {
|
|
344
|
+
return new Promise((resolve) => {
|
|
345
|
+
setTimeout(() => resolve(value), delay);
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
// Utility method that completes a `ResultAsync` after a delay (in ms)
|
|
349
|
+
function delayResult(result, delay) {
|
|
350
|
+
const promiseLike = result.then((r) => delayPromise(r, delay));
|
|
351
|
+
return new ResultAsync(Promise.resolve(promiseLike));
|
|
352
|
+
}
|
|
353
|
+
/**
|
|
354
|
+
* Wrapper around an {@link EventLog} that injects latency
|
|
355
|
+
*
|
|
356
|
+
* Intended for use when simulating the effects of latency in a real implementation
|
|
357
|
+
*/
|
|
358
|
+
class DelayEventLog {
|
|
359
|
+
constructor(base, delay = 0) {
|
|
360
|
+
this.base = base;
|
|
361
|
+
this.delay = delay;
|
|
362
|
+
}
|
|
363
|
+
/** Delay in milliseconds to add to response from each API call */
|
|
364
|
+
delay;
|
|
365
|
+
addEntry(entry, sequenceId, snapshotId) {
|
|
366
|
+
return delayResult(this.base.addEntry(entry, sequenceId, snapshotId), this.delay);
|
|
367
|
+
}
|
|
368
|
+
setMetadata(sequenceId, metadata) {
|
|
369
|
+
return delayResult(this.base.setMetadata(sequenceId, metadata), this.delay);
|
|
370
|
+
}
|
|
371
|
+
query(start, end, snapshotId) {
|
|
372
|
+
return delayResult(this.base.query(start, end, snapshotId), this.delay);
|
|
373
|
+
}
|
|
374
|
+
truncate(start) {
|
|
375
|
+
return delayResult(this.base.truncate(start), this.delay);
|
|
376
|
+
}
|
|
377
|
+
base;
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
const QUERY_PAGE_SIZE = 10;
|
|
381
|
+
/**
|
|
382
|
+
* Branding Enum. Used by {@link SimpleBlobStore} to ensure that
|
|
383
|
+
* you'll get a type error if you pass some random object where a `SimpleBlobStoreContinuation`
|
|
384
|
+
* is expected.
|
|
385
|
+
* @internal
|
|
386
|
+
*/
|
|
387
|
+
var _SimpleBlobStoreBrand;
|
|
388
|
+
(function (_SimpleBlobStoreBrand) {
|
|
389
|
+
_SimpleBlobStoreBrand["_DO_NOT_USE"] = "";
|
|
390
|
+
})(_SimpleBlobStoreBrand || (_SimpleBlobStoreBrand = {}));
|
|
391
|
+
function asIter(continuation) {
|
|
392
|
+
return continuation;
|
|
393
|
+
}
|
|
394
|
+
function asContinuation(iter) {
|
|
395
|
+
return iter;
|
|
396
|
+
}
|
|
397
|
+
/**
|
|
398
|
+
* Reference implementation of {@link BlobDir}
|
|
399
|
+
*
|
|
400
|
+
* Intended for use as a mock, to compare with an optimized implementation when testing and
|
|
401
|
+
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
402
|
+
*/
|
|
403
|
+
class SimpleBlobDir {
|
|
404
|
+
constructor() {
|
|
405
|
+
this.map = new Map;
|
|
406
|
+
}
|
|
407
|
+
// Logically directories only exist if they have entries. To simplify implementation we
|
|
408
|
+
// create on demand and treat empty dir the same as non-existent dir.
|
|
409
|
+
readBlob(name) {
|
|
410
|
+
if (!name)
|
|
411
|
+
return errAsync(invalidBlobNameError());
|
|
412
|
+
const value = this.map.get(name);
|
|
413
|
+
if (!value || (value instanceof SimpleBlobDir && value.map.size == 0))
|
|
414
|
+
return errAsync(storageError("Blob does not exist", 404));
|
|
415
|
+
if (value instanceof Uint8Array) {
|
|
416
|
+
return okAsync(value);
|
|
417
|
+
}
|
|
418
|
+
else {
|
|
419
|
+
return errAsync(notBlobError());
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
writeBlob(name, content) {
|
|
423
|
+
if (!name)
|
|
424
|
+
return errAsync(invalidBlobNameError());
|
|
425
|
+
const value = this.map.get(name);
|
|
426
|
+
if (value instanceof SimpleBlobDir && value.map.size > 0)
|
|
427
|
+
return errAsync(notBlobError());
|
|
428
|
+
this.map.set(name, new Uint8Array(content));
|
|
429
|
+
return okAsync();
|
|
430
|
+
}
|
|
431
|
+
removeBlob(name) {
|
|
432
|
+
if (!name)
|
|
433
|
+
return errAsync(invalidBlobNameError());
|
|
434
|
+
const value = this.map.get(name);
|
|
435
|
+
if (value instanceof SimpleBlobDir && value.map.size > 0)
|
|
436
|
+
return errAsync(notBlobError());
|
|
437
|
+
this.map.delete(name);
|
|
438
|
+
return okAsync();
|
|
439
|
+
}
|
|
440
|
+
getDir(name) {
|
|
441
|
+
if (!name)
|
|
442
|
+
return errAsync(invalidBlobNameError());
|
|
443
|
+
const value = this.map.get(name);
|
|
444
|
+
if (!value) {
|
|
445
|
+
const dir = new SimpleBlobDir();
|
|
446
|
+
this.map.set(name, dir);
|
|
447
|
+
return okAsync(dir);
|
|
448
|
+
}
|
|
449
|
+
if (value instanceof SimpleBlobDir)
|
|
450
|
+
return okAsync(value);
|
|
451
|
+
return errAsync(notBlobDirError());
|
|
452
|
+
}
|
|
453
|
+
query(continuation) {
|
|
454
|
+
let iter;
|
|
455
|
+
if (continuation) {
|
|
456
|
+
const sbsIter = asIter(continuation);
|
|
457
|
+
if (sbsIter.dir !== this)
|
|
458
|
+
return errAsync(noContinuationError("Invalid continuation"));
|
|
459
|
+
iter = sbsIter.iter;
|
|
460
|
+
if (!iter)
|
|
461
|
+
return errAsync(noContinuationError("Can't reuse continuation"));
|
|
462
|
+
// Iterator is mutated so can't reuse continuation to retry query
|
|
463
|
+
sbsIter.iter = undefined;
|
|
464
|
+
}
|
|
465
|
+
else {
|
|
466
|
+
iter = this.map.entries();
|
|
467
|
+
}
|
|
468
|
+
const entries = { blobs: [], dirs: [] };
|
|
469
|
+
for (let i = 0; i < QUERY_PAGE_SIZE; i++) {
|
|
470
|
+
const result = iter.next();
|
|
471
|
+
if (result.done)
|
|
472
|
+
return okAsync(entries);
|
|
473
|
+
const [name, value] = result.value;
|
|
474
|
+
if (value instanceof SimpleBlobDir) {
|
|
475
|
+
if (value.map.size > 0)
|
|
476
|
+
entries.dirs.push(name);
|
|
477
|
+
}
|
|
478
|
+
else {
|
|
479
|
+
entries.blobs.push(name);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
entries.continuation = asContinuation({ dir: this, iter });
|
|
483
|
+
return okAsync(entries);
|
|
484
|
+
}
|
|
485
|
+
removeAll() {
|
|
486
|
+
this.map.clear();
|
|
487
|
+
return okAsync();
|
|
488
|
+
}
|
|
489
|
+
map;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* Reference implementation of {@link BlobStore}
|
|
493
|
+
*
|
|
494
|
+
* Intended for use as a mock, to compare with an optimized implementation when testing and
|
|
495
|
+
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
496
|
+
*/
|
|
497
|
+
class SimpleBlobStore {
|
|
498
|
+
constructor() {
|
|
499
|
+
this.root = undefined;
|
|
500
|
+
}
|
|
501
|
+
getRootDir() {
|
|
502
|
+
if (!this.root)
|
|
503
|
+
this.root = new SimpleBlobDir;
|
|
504
|
+
return okAsync(this.root);
|
|
505
|
+
}
|
|
506
|
+
root;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Reference implementation of {@link InfiniSheetWorker}
|
|
511
|
+
*
|
|
512
|
+
* In-process event loop based workers
|
|
513
|
+
*
|
|
514
|
+
* Intended for use as a mock, to compare with an optimized implementation when testing and
|
|
515
|
+
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
516
|
+
*/
|
|
517
|
+
class SimpleWorker {
|
|
518
|
+
constructor() {
|
|
519
|
+
}
|
|
520
|
+
onReceiveMessage;
|
|
521
|
+
}
|
|
522
|
+
/**
|
|
523
|
+
* Reference implementation of {@link PostMessageWorkerHost}
|
|
524
|
+
*
|
|
525
|
+
* In-process event loop based workers
|
|
526
|
+
*
|
|
527
|
+
* Intended for use as a mock, to compare with an optimized implementation when testing and
|
|
528
|
+
* for simple sample apps. Simplest possible implementation, no attempt at optimization.
|
|
529
|
+
*/
|
|
530
|
+
class SimpleWorkerHost {
|
|
531
|
+
constructor(worker, delay = 0) {
|
|
532
|
+
this.worker = worker;
|
|
533
|
+
this.delay = delay;
|
|
534
|
+
}
|
|
535
|
+
/** @internal */
|
|
536
|
+
isHost() { return true; }
|
|
537
|
+
postMessage(message) {
|
|
538
|
+
const handler = this.worker.onReceiveMessage;
|
|
539
|
+
if (handler) {
|
|
540
|
+
// Using setTimeout ensures message is delivered via the event loop
|
|
541
|
+
setTimeout(() => {
|
|
542
|
+
const result = handler(message);
|
|
543
|
+
result.orElse(
|
|
544
|
+
// Intentionally results in an unhandled exception in event handler
|
|
545
|
+
// Should never use SimplerWorkers with workflow that can result in error
|
|
546
|
+
// Can't be unit tested as blows up the test
|
|
547
|
+
/* istanbul ignore next */
|
|
548
|
+
(error) => {
|
|
549
|
+
console.log(`SimpleWorker returned error ${JSON.stringify(error)}`);
|
|
550
|
+
throw Error("SimpleWorker returned error", { cause: error });
|
|
551
|
+
});
|
|
552
|
+
}, this.delay);
|
|
553
|
+
}
|
|
554
|
+
else {
|
|
555
|
+
throw Error("Worker has no message handler");
|
|
556
|
+
}
|
|
557
|
+
}
|
|
558
|
+
worker;
|
|
559
|
+
delay;
|
|
272
560
|
}
|
|
273
561
|
|
|
274
|
-
export { LayeredSpreadsheetData, SimpleEventLog, SimpleSpreadsheetData, _LayeredSnapshotBrand, _SimpleSnapshotBrand };
|
|
562
|
+
export { DelayEventLog, LayeredSpreadsheetData, SimpleBlobDir, SimpleBlobStore, SimpleEventLog, SimpleSpreadsheetData, SimpleWorker, SimpleWorkerHost, _LayeredSnapshotBrand, _SimpleBlobStoreBrand, _SimpleSnapshotBrand, delayPromise, delayResult };
|
|
275
563
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../src/SimpleSpreadsheetData.ts","../src/LayeredSpreadsheetData.ts","../src/SimpleEventLog.ts"],"sourcesContent":["import type { CellValue, SpreadsheetData, RowColRef, ItemOffsetMapping, Result, \n SpreadsheetDataError, ValidationError } from \"@candidstartup/infinisheet-types\";\nimport { FixedSizeItemOffsetMapping, rowColCoordsToRef, ok } from \"@candidstartup/infinisheet-types\";\n\ninterface CellContent {\n value: CellValue;\n format: string|undefined;\n}\n\ninterface SimpleSnapshotContent {\n values: Record<RowColRef,CellContent>;\n rowCount: number;\n colCount: number;\n}\n\n/** \n * Branding Enum. Used by {@link SimpleSnapshot} to ensure that\n * you'll get a type error if you pass some random object where a `SimpleSnapshot`\n * is expected.\n * @internal\n */\nexport enum _SimpleSnapshotBrand { _DO_NOT_USE=\"\" };\n\n/**\n * Opaque type representing a {@link SimpleSpreadsheetData} snapshot. All the\n * internal implementation details are hidden from the exported API.\n */\nexport interface SimpleSnapshot {\n /** @internal */\n _brand: _SimpleSnapshotBrand;\n}\n\nconst rowItemOffsetMapping = new FixedSizeItemOffsetMapping(30);\nconst columnItemOffsetMapping = new FixedSizeItemOffsetMapping(100);\n\nfunction asContent(snapshot: SimpleSnapshot) {\n return snapshot as unknown as SimpleSnapshotContent;\n}\n\nfunction asSnapshot(snapshot: SimpleSnapshotContent) {\n return snapshot as unknown as SimpleSnapshot;\n}\n\n/**\n * Reference implementation of {@link SpreadsheetData}\n * \n * Editable in-memory spreadsheet data container. Starts out empty. Use the API to fill\n * with data!\n * \n * Intended for use as a mock, to compare with an optimized implementation when testing and\n * for simple sample apps. Simplest possible implementation, no attempt at optimization.\n */\nexport class SimpleSpreadsheetData implements SpreadsheetData<SimpleSnapshot> {\n constructor () {\n this.#listeners = [];\n this.#content = {\n values: {},\n rowCount: 0,\n colCount: 0\n }\n }\n\n subscribe(onDataChange: () => void): () => void {\n this.#listeners = [...this.#listeners, onDataChange];\n return () => {\n this.#listeners = this.#listeners.filter(l => l !== onDataChange);\n }\n }\n\n getSnapshot(): SimpleSnapshot {\n return asSnapshot(this.#content);\n }\n\n getRowCount(snapshot: SimpleSnapshot): number {\n return asContent(snapshot).rowCount;\n }\n\n getRowItemOffsetMapping(_snapshot: SimpleSnapshot): ItemOffsetMapping {\n return rowItemOffsetMapping;\n }\n\n getColumnCount(snapshot: SimpleSnapshot): number {\n return asContent(snapshot).colCount;\n }\n\n getColumnItemOffsetMapping(_snapshot: SimpleSnapshot): ItemOffsetMapping {\n return columnItemOffsetMapping\n }\n\n getCellValue(snapshot: SimpleSnapshot, row: number, column: number): CellValue {\n const ref = rowColCoordsToRef(row, column);\n return asContent(snapshot).values[ref]?.value;\n }\n\n getCellFormat(snapshot: SimpleSnapshot, row: number, column: number): string | undefined {\n const ref = rowColCoordsToRef(row, column);\n return asContent(snapshot).values[ref]?.format;\n }\n\n setCellValueAndFormat(row: number, column: number, value: CellValue, format: string | undefined): Result<void,SpreadsheetDataError> {\n const curr = this.#content;\n const ref = rowColCoordsToRef(row, column);\n\n // Snapshot semantics preserved by treating SimpleSnapshot as an immutable data structure which is \n // replaced with a modified copy on every update. Yes, this is horribly inefficient. \n // For simplicity, setting a value to undefined stores it explicitly rather than removing it. Functional\n // behavior is the same.\n this.#content = {\n values: { ...curr.values, [ref]: { value, format }},\n rowCount: Math.max(curr.rowCount, row+1),\n colCount: Math.max(curr.colCount, column+1)\n }\n this.#notifyListeners();\n\n return ok();\n }\n\n isValidCellValueAndFormat(_row: number, _column: number, _value: CellValue, _format: string | undefined): Result<void,ValidationError> {\n return ok(); \n }\n\n #notifyListeners() {\n for (const listener of this.#listeners)\n listener();\n }\n\n #listeners: (() => void)[];\n #content: SimpleSnapshotContent;\n}\n","import type { CellValue, SpreadsheetData, ItemOffsetMapping, Result, \n SpreadsheetDataError, ValidationError } from \"@candidstartup/infinisheet-types\";\n\ninterface LayeredSnapshotContent<BaseSnapshot, EditSnapshot> {\n base: BaseSnapshot,\n edit: EditSnapshot\n}\n\n/** \n * Branding Enum. Used by {@link LayeredSnapshot} to ensure that\n * you'll get a type error if you pass some random object where a `LayeredSnapshot`\n * is expected.\n * @internal\n */\nexport enum _LayeredSnapshotBrand { _DO_NOT_USE=\"\" };\n\n/**\n * Opaque type representing a {@link LayeredSpreadsheetData} snapshot. All the\n * internal implementation details are hidden from the exported API.\n */\nexport interface LayeredSnapshot<BaseSnapshot,EditSnapshot> {\n /** @internal */\n _brand: [ _LayeredSnapshotBrand, BaseSnapshot, EditSnapshot ]\n}\n\nfunction asContent<Base,Edit>(snapshot: LayeredSnapshot<Base,Edit>) {\n return snapshot as unknown as LayeredSnapshotContent<Base,Edit>;\n}\n\nfunction asSnapshot<Base,Edit>(snapshot: LayeredSnapshotContent<Base,Edit>) {\n return snapshot as unknown as LayeredSnapshot<Base,Edit>;\n}\n\n/**\n * Extracts the snapshot type from a {@link SpreadsheetData} instance\n */\nexport type SnapshotType<T> = T extends SpreadsheetData<infer TResult> ? TResult : never;\n\n/**\n * Implementation of {@link SpreadsheetData} that layers two other `SpreadsheetData` instances on top of each other.\n * \n * There's an \"edit\" layer on top where any changes are stored, with a \"base\" layer underneath. If a value is `undefined` in the edit layer, \n * the corresponding value is returned from the base layer instead.\n * \n * Common use case is a read only reference data source as the base layer with an initially empty edit layer that accepts changes.\n * \n * @typeParam BaseData - Type of base layer `SpreadsheetData` instance\n * @typeParam EditData - Type of edit layer `SpreadsheetData` instance\n * @typeParam BaseSnapshot - Type of snapshot used by `BaseData`. By default, inferred from `BaseData`.\n * @typeParam EditSnapshot - Type of snapshot used by `EditData`. By default, inferred from `EditData`.\n */\nexport class LayeredSpreadsheetData<BaseData extends SpreadsheetData<BaseSnapshot>, \n EditData extends SpreadsheetData<EditSnapshot>, BaseSnapshot = SnapshotType<BaseData>, EditSnapshot = SnapshotType<EditData>>\n implements SpreadsheetData<LayeredSnapshot<BaseSnapshot, EditSnapshot>> {\n\n /**\n * Creates a `LayeredSpreadsheetData` instance from two existing `SpreadsheetData` instances.\n * \n * All type parameters can be inferred from the constructor arguments.\n * \n * @param base - `SpreadsheetData` instance to use for the base layer\n * @param edit - `SpreadsheetData` instance to use for the edit layer\n */\n constructor(base: BaseData, edit: EditData) {\n this.#base = base;\n this.#edit = edit;\n }\n\n subscribe(onDataChange: () => void): () => void {\n const unsubscribeBase = this.#base.subscribe(onDataChange);\n const unsubscribeEdit = this.#edit.subscribe(onDataChange);\n return () => {\n unsubscribeBase();\n unsubscribeEdit();\n }\n }\n\n getSnapshot(): LayeredSnapshot<BaseSnapshot, EditSnapshot> {\n const baseSnapshot = this.#base.getSnapshot();\n const editSnapshot = this.#edit.getSnapshot();\n\n if (!this.#content || this.#content.base != baseSnapshot || this.#content.edit != editSnapshot) {\n this.#content = { base: baseSnapshot, edit: editSnapshot } ;\n }\n\n return asSnapshot(this.#content);\n }\n\n getRowCount(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): number {\n const content = asContent(snapshot);\n return Math.max(this.#base.getRowCount(content.base), this.#edit.getRowCount(content.edit));\n }\n\n getRowItemOffsetMapping(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): ItemOffsetMapping {\n return this.#base.getRowItemOffsetMapping(asContent(snapshot).base);\n }\n\n getColumnCount(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): number {\n const content = asContent(snapshot);\n return Math.max(this.#base.getColumnCount(content.base), this.#edit.getColumnCount(content.edit));\n }\n\n getColumnItemOffsetMapping(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): ItemOffsetMapping {\n return this.#base.getColumnItemOffsetMapping(asContent(snapshot).base);\n }\n\n getCellValue(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>, row: number, column: number): CellValue {\n const content = asContent(snapshot);\n const editValue = this.#edit.getCellValue(content.edit, row, column);\n if (editValue !== undefined)\n return editValue;\n\n return this.#base.getCellValue(content.base, row, column);\n }\n\n getCellFormat(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>, row: number, column: number): string | undefined {\n const content = asContent(snapshot);\n const editValue = this.#edit.getCellValue(content.edit, row, column);\n return (editValue === undefined) ? this.#base.getCellFormat(content.base, row, column) : this.#edit.getCellFormat(content.edit, row, column);\n }\n\n setCellValueAndFormat(row: number, column: number, value: CellValue, format: string | undefined): Result<void,SpreadsheetDataError> {\n const result = this.#base.isValidCellValueAndFormat(row, column, value, format);\n return result.andThen(() => this.#edit.setCellValueAndFormat(row, column, value, format));\n }\n\n // Must be valid for both layers\n isValidCellValueAndFormat(row: number, column: number, value: CellValue, format: string | undefined): Result<void,ValidationError> {\n const result = this.#base.isValidCellValueAndFormat(row, column, value, format);\n return result.andThen(() => this.#edit.isValidCellValueAndFormat(row,column,value,format));\n }\n\n #base: BaseData;\n #edit: EditData;\n #content: LayeredSnapshotContent<BaseSnapshot, EditSnapshot> | undefined;\n}\n","import type { EventLog, LogEntry, LogMetadata, SequenceId, ResultAsync, QueryValue, \n AddEntryError, QueryError, TruncateError, MetadataError } from \"@candidstartup/infinisheet-types\";\nimport { okAsync, errAsync, conflictError, infinisheetRangeError } from \"@candidstartup/infinisheet-types\";\n\nconst QUERY_PAGE_SIZE = 10;\n\nexport class SimpleEventLog<T extends LogEntry> implements EventLog<T> {\n constructor() {\n this.#startSequenceId = 0n;\n this.#endSequenceId = 0n;\n this.#entries = [];\n }\n\n addEntry(entry: T, sequenceId: SequenceId): ResultAsync<void,AddEntryError> {\n if (sequenceId !== this.#endSequenceId)\n return errAsync(conflictError(\"sequenceId is not next sequence id\", this.#endSequenceId));\n\n this.#entries.push(entry);\n this.#endSequenceId ++;\n return okAsync();\n }\n\n setMetadata(sequenceId: SequenceId, metadata: LogMetadata): ResultAsync<void,MetadataError> {\n if (sequenceId < this.#startSequenceId || sequenceId >= this.#endSequenceId)\n return errAsync(infinisheetRangeError(`Log entry with sequenceId ${sequenceId} does not exist`));\n\n const index = Number(sequenceId - this.#startSequenceId);\n const entry = this.#entries[index]!;\n if (\"snapshot\" in metadata)\n entry.snapshot = metadata.snapshot;\n if (\"history\" in metadata)\n entry.history = metadata.history;\n if (\"pending\" in metadata)\n entry.pending = metadata.pending;\n\n return okAsync();\n }\n\n query(start: SequenceId | 'snapshot' | 'start', end: SequenceId | 'end'): ResultAsync<QueryValue<T>,QueryError> {\n if (start === 'start')\n start = this.#startSequenceId;\n else if (start === 'snapshot')\n start = this.#startSequenceId + BigInt(this.findSnapshotIndex());\n else if (start < this.#startSequenceId || start > this.#endSequenceId)\n return errAsync(infinisheetRangeError(\"start index out of range\"));\n\n if (end === 'end')\n end = this.#endSequenceId;\n\n const num = end - start;\n const isComplete = num <= BigInt(QUERY_PAGE_SIZE);\n let numToReturn = isComplete ? Number(num) : QUERY_PAGE_SIZE;\n const firstIndex = Number(start - this.#startSequenceId);\n if (firstIndex + numToReturn > this.#entries.length)\n numToReturn = this.#entries.length - firstIndex;\n\n const value: QueryValue<T> = {\n startSequenceId: start,\n endSequenceId: start + BigInt(numToReturn),\n isComplete,\n entries: this.#entries.slice(firstIndex, firstIndex + numToReturn)\n }\n\n return okAsync(value);\n }\n\n truncate(start: SequenceId): ResultAsync<void,TruncateError> {\n if (start < this.#startSequenceId)\n return errAsync(infinisheetRangeError(\"start before start entry in the log\"));\n\n if (start === this.#startSequenceId)\n return okAsync();\n \n if (start === this.#endSequenceId) {\n this.#startSequenceId = start;\n this.#endSequenceId = start;\n this.#entries = [];\n return okAsync();\n }\n\n if (start > this.#endSequenceId)\n return errAsync(infinisheetRangeError(\"start after end entry in the log\"));\n\n const numToRemove = start - this.#startSequenceId;\n this.#startSequenceId = start;\n this.#entries.splice(0, Number(numToRemove));\n return okAsync();\n }\n\n private findSnapshotIndex(): number {\n for (let i = this.#entries.length - 1; i > 0; i--) {\n const entry = this.#entries[i]!;\n if (entry.snapshot)\n return i;\n }\n\n // If no other entry has a snapshot use the first (whether it has a snapshot or not)\n return 0;\n }\n\n #startSequenceId: SequenceId;\n #endSequenceId: SequenceId;\n #entries: T[];\n}"],"names":["asContent","asSnapshot"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../src/SimpleSpreadsheetData.ts","../src/LayeredSpreadsheetData.ts","../src/SimpleEventLog.ts","../src/DelayEventLog.ts","../src/SimpleBlobStore.ts","../src/SimpleWorkers.ts"],"sourcesContent":["import type { CellValue, CellFormat, SpreadsheetData, RowColRef, ItemOffsetMapping, Result, ResultAsync,\n SpreadsheetDataError, ValidationError, StorageError, SpreadsheetViewport } from \"@candidstartup/infinisheet-types\";\nimport { FixedSizeItemOffsetMapping, rowColCoordsToRef, ok, okAsync, equalViewports } from \"@candidstartup/infinisheet-types\";\n\ninterface CellContent {\n value: CellValue;\n format: string|undefined;\n}\n\ninterface SimpleSnapshotContent {\n values: Record<RowColRef,CellContent>;\n rowCount: number;\n colCount: number;\n viewport: SpreadsheetViewport | undefined;\n}\n\n/** \n * Branding Enum. Used by {@link SimpleSnapshot} to ensure that\n * you'll get a type error if you pass some random object where a `SimpleSnapshot`\n * is expected.\n * @internal\n */\nexport enum _SimpleSnapshotBrand { _DO_NOT_USE=\"\" };\n\n/**\n * Opaque type representing a {@link SimpleSpreadsheetData} snapshot. All the\n * internal implementation details are hidden from the exported API.\n */\nexport interface SimpleSnapshot {\n /** @internal */\n _brand: _SimpleSnapshotBrand;\n}\n\nconst rowItemOffsetMapping = new FixedSizeItemOffsetMapping(30);\nconst columnItemOffsetMapping = new FixedSizeItemOffsetMapping(100);\n\nfunction asContent(snapshot: SimpleSnapshot) {\n return snapshot as unknown as SimpleSnapshotContent;\n}\n\nfunction asSnapshot(snapshot: SimpleSnapshotContent) {\n return snapshot as unknown as SimpleSnapshot;\n}\n\n/**\n * Reference implementation of {@link SpreadsheetData}\n * \n * Editable in-memory spreadsheet data container. Starts out empty. Use the API to fill\n * with data!\n * \n * Intended for use as a mock, to compare with an optimized implementation when testing and\n * for simple sample apps. Simplest possible implementation, no attempt at optimization.\n */\nexport class SimpleSpreadsheetData implements SpreadsheetData<SimpleSnapshot> {\n constructor () {\n this.listeners = [];\n this.content = {\n values: {},\n rowCount: 0,\n colCount: 0,\n viewport: undefined\n }\n }\n\n subscribe(onDataChange: () => void): () => void {\n this.listeners = [...this.listeners, onDataChange];\n return () => {\n this.listeners = this.listeners.filter(l => l !== onDataChange);\n }\n }\n\n getSnapshot(): SimpleSnapshot {\n return asSnapshot(this.content);\n }\n\n getLoadStatus(_snapshot: SimpleSnapshot): Result<boolean,StorageError> {\n return ok(true);\n }\n\n getRowCount(snapshot: SimpleSnapshot): number {\n return asContent(snapshot).rowCount;\n }\n\n getRowItemOffsetMapping(_snapshot: SimpleSnapshot): ItemOffsetMapping {\n return rowItemOffsetMapping;\n }\n\n getColumnCount(snapshot: SimpleSnapshot): number {\n return asContent(snapshot).colCount;\n }\n\n getColumnItemOffsetMapping(_snapshot: SimpleSnapshot): ItemOffsetMapping {\n return columnItemOffsetMapping\n }\n\n getCellValue(snapshot: SimpleSnapshot, row: number, column: number): CellValue {\n const ref = rowColCoordsToRef(row, column);\n return asContent(snapshot).values[ref]?.value;\n }\n\n getCellFormat(snapshot: SimpleSnapshot, row: number, column: number): CellFormat {\n const ref = rowColCoordsToRef(row, column);\n return asContent(snapshot).values[ref]?.format;\n }\n\n setCellValueAndFormat(row: number, column: number, value: CellValue, format: CellFormat): ResultAsync<void,SpreadsheetDataError> {\n const curr = this.content;\n const ref = rowColCoordsToRef(row, column);\n\n // Snapshot semantics preserved by treating SimpleSnapshot as an immutable data structure which is \n // replaced with a modified copy on every update. Yes, this is horribly inefficient. \n // For simplicity, setting a value to undefined stores it explicitly rather than removing it. Functional\n // behavior is the same.\n this.content = {\n values: { ...curr.values, [ref]: { value, format }},\n rowCount: Math.max(curr.rowCount, row+1),\n colCount: Math.max(curr.colCount, column+1),\n viewport: curr.viewport\n }\n\n return okAsync().andTee(() => this.notifyListeners());\n }\n\n isValidCellValueAndFormat(_row: number, _column: number, _value: CellValue, _format: CellFormat): Result<void,ValidationError> {\n return ok(); \n }\n\n setViewport(viewport: SpreadsheetViewport | undefined): void { \n const curr = this.content;\n if (equalViewports(curr.viewport, viewport))\n return;\n\n this.content = { ...curr, viewport };\n this.notifyListeners();\n }\n\n getViewport(snapshot: SimpleSnapshot): SpreadsheetViewport | undefined { \n return asContent(snapshot).viewport; \n }\n\n private notifyListeners() {\n for (const listener of this.listeners)\n listener();\n }\n\n private listeners: (() => void)[];\n private content: SimpleSnapshotContent;\n}\n","import type { CellValue, CellFormat, SpreadsheetData, ItemOffsetMapping, Result, ResultAsync,\n SpreadsheetDataError, ValidationError, StorageError, SpreadsheetViewport } from \"@candidstartup/infinisheet-types\";\n\ninterface LayeredSnapshotContent<BaseSnapshot, EditSnapshot> {\n base: BaseSnapshot,\n edit: EditSnapshot\n}\n\n/** \n * Branding Enum. Used by {@link LayeredSnapshot} to ensure that\n * you'll get a type error if you pass some random object where a `LayeredSnapshot`\n * is expected.\n * @internal\n */\nexport enum _LayeredSnapshotBrand { _DO_NOT_USE=\"\" };\n\n/**\n * Opaque type representing a {@link LayeredSpreadsheetData} snapshot. All the\n * internal implementation details are hidden from the exported API.\n */\nexport interface LayeredSnapshot<BaseSnapshot,EditSnapshot> {\n /** @internal */\n _brand: [ _LayeredSnapshotBrand, BaseSnapshot, EditSnapshot ]\n}\n\nfunction asContent<Base,Edit>(snapshot: LayeredSnapshot<Base,Edit>) {\n return snapshot as unknown as LayeredSnapshotContent<Base,Edit>;\n}\n\nfunction asSnapshot<Base,Edit>(snapshot: LayeredSnapshotContent<Base,Edit>) {\n return snapshot as unknown as LayeredSnapshot<Base,Edit>;\n}\n\n/**\n * Extracts the snapshot type from a {@link SpreadsheetData} instance\n */\nexport type SnapshotType<T> = T extends SpreadsheetData<infer TResult> ? TResult : never;\n\n/**\n * Implementation of {@link SpreadsheetData} that layers two other `SpreadsheetData` instances on top of each other.\n * \n * There's an \"edit\" layer on top where any changes are stored, with a \"base\" layer underneath. If a value is `undefined` in the edit layer, \n * the corresponding value is returned from the base layer instead.\n * \n * Common use case is a read only reference data source as the base layer with an initially empty edit layer that accepts changes.\n * \n * @typeParam BaseData - Type of base layer `SpreadsheetData` instance\n * @typeParam EditData - Type of edit layer `SpreadsheetData` instance\n * @typeParam BaseSnapshot - Type of snapshot used by `BaseData`. By default, inferred from `BaseData`.\n * @typeParam EditSnapshot - Type of snapshot used by `EditData`. By default, inferred from `EditData`.\n */\nexport class LayeredSpreadsheetData<BaseData extends SpreadsheetData<BaseSnapshot>, \n EditData extends SpreadsheetData<EditSnapshot>, BaseSnapshot = SnapshotType<BaseData>, EditSnapshot = SnapshotType<EditData>>\n implements SpreadsheetData<LayeredSnapshot<BaseSnapshot, EditSnapshot>> {\n\n /**\n * Creates a `LayeredSpreadsheetData` instance from two existing `SpreadsheetData` instances.\n * \n * All type parameters can be inferred from the constructor arguments.\n * \n * @param base - `SpreadsheetData` instance to use for the base layer\n * @param edit - `SpreadsheetData` instance to use for the edit layer\n */\n constructor(base: BaseData, edit: EditData) {\n this.base = base;\n this.edit = edit;\n }\n\n subscribe(onDataChange: () => void): () => void {\n const unsubscribeBase = this.base.subscribe(onDataChange);\n const unsubscribeEdit = this.edit.subscribe(onDataChange);\n return () => {\n unsubscribeBase();\n unsubscribeEdit();\n }\n }\n\n getSnapshot(): LayeredSnapshot<BaseSnapshot, EditSnapshot> {\n const baseSnapshot = this.base.getSnapshot();\n const editSnapshot = this.edit.getSnapshot();\n\n if (!this.content || this.content.base != baseSnapshot || this.content.edit != editSnapshot) {\n this.content = { base: baseSnapshot, edit: editSnapshot } ;\n }\n\n return asSnapshot(this.content);\n }\n\n getLoadStatus(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): Result<boolean,StorageError> {\n const content = asContent(snapshot);\n return this.base.getLoadStatus(content.base).andThen((t1) => this.edit.getLoadStatus(content.edit).map((t2) => t1 && t2));\n }\n\n getRowCount(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): number {\n const content = asContent(snapshot);\n return Math.max(this.base.getRowCount(content.base), this.edit.getRowCount(content.edit));\n }\n\n getRowItemOffsetMapping(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): ItemOffsetMapping {\n return this.base.getRowItemOffsetMapping(asContent(snapshot).base);\n }\n\n getColumnCount(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): number {\n const content = asContent(snapshot);\n return Math.max(this.base.getColumnCount(content.base), this.edit.getColumnCount(content.edit));\n }\n\n getColumnItemOffsetMapping(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): ItemOffsetMapping {\n return this.base.getColumnItemOffsetMapping(asContent(snapshot).base);\n }\n\n getCellValue(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>, row: number, column: number): CellValue {\n const content = asContent(snapshot);\n const editValue = this.edit.getCellValue(content.edit, row, column);\n if (editValue !== undefined)\n return editValue;\n\n return this.base.getCellValue(content.base, row, column);\n }\n\n getCellFormat(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>, row: number, column: number): CellFormat {\n const content = asContent(snapshot);\n const editValue = this.edit.getCellValue(content.edit, row, column);\n return (editValue === undefined) ? this.base.getCellFormat(content.base, row, column) : this.edit.getCellFormat(content.edit, row, column);\n }\n\n setCellValueAndFormat(row: number, column: number, value: CellValue, format: CellFormat): ResultAsync<void,SpreadsheetDataError> {\n const result = this.base.isValidCellValueAndFormat(row, column, value, format);\n return result.asyncAndThen(() => this.edit.setCellValueAndFormat(row, column, value, format));\n }\n\n // Must be valid for both layers\n isValidCellValueAndFormat(row: number, column: number, value: CellValue, format: CellFormat): Result<void,ValidationError> {\n const result = this.base.isValidCellValueAndFormat(row, column, value, format);\n return result.andThen(() => this.edit.isValidCellValueAndFormat(row,column,value,format));\n }\n\n setViewport(viewport: SpreadsheetViewport | undefined): void { \n this.base.setViewport(viewport);\n this.edit.setViewport(viewport);\n }\n getViewport(snapshot: LayeredSnapshot<BaseSnapshot, EditSnapshot>): SpreadsheetViewport | undefined { \n const content = asContent(snapshot);\n return this.edit.getViewport(content.edit);\n }\n\n private base: BaseData;\n private edit: EditData;\n private content: LayeredSnapshotContent<BaseSnapshot, EditSnapshot> | undefined;\n}\n","import type { EventLog, LogEntry, LogMetadata, SequenceId, ResultAsync, QueryValue, WorkflowId, AddEntryValue, \n AddEntryError, QueryError, TruncateError, MetadataError, PendingWorkflowMessage, SnapshotValue } from \"@candidstartup/infinisheet-types\";\nimport { okAsync, errAsync, conflictError, infinisheetRangeError, PostMessageWorkerHost } from \"@candidstartup/infinisheet-types\";\n\nconst QUERY_PAGE_SIZE = 10;\n\n/**\n * Reference implementation of {@link EventLog}\n * \n * In-memory event log\n * \n * Intended for use as a mock, to compare with an optimized implementation when testing and\n * for simple sample apps. Simplest possible implementation, no attempt at optimization.\n */\nexport class SimpleEventLog<T extends LogEntry> implements EventLog<T> {\n constructor(workerHost?: PostMessageWorkerHost<PendingWorkflowMessage>) {\n this.workerHost = workerHost;\n this.startSequenceId = 0n;\n this.endSequenceId = 0n;\n this.entries = [];\n }\n\n /** Worker host used to process pending workflows */\n workerHost?: PostMessageWorkerHost<PendingWorkflowMessage> | undefined;\n\n addEntry(entry: T, sequenceId: SequenceId, snapshotId?: SequenceId): ResultAsync<AddEntryValue,AddEntryError> {\n if (sequenceId !== this.endSequenceId)\n return errAsync(conflictError(\"sequenceId is not next sequence id\", this.endSequenceId));\n\n this.entries.push(entry);\n this.endSequenceId ++;\n\n if (entry.pending)\n this.sendPendingWorkflowMessage(entry.pending, sequenceId);\n\n const value: AddEntryValue = {};\n if (snapshotId !== undefined) {\n const snapshot = this.findSnapshot();\n if (snapshot && snapshot.sequenceId !== snapshotId)\n value.lastSnapshot = snapshot;\n }\n \n return okAsync(value);\n }\n\n setMetadata(sequenceId: SequenceId, metadata: LogMetadata): ResultAsync<void,MetadataError> {\n if (sequenceId < this.startSequenceId || sequenceId >= this.endSequenceId)\n return errAsync(infinisheetRangeError(`Log entry with sequenceId ${sequenceId} does not exist`));\n\n const index = Number(sequenceId - this.startSequenceId);\n const entry = this.entries[index]!;\n if (\"snapshot\" in metadata)\n entry.snapshot = metadata.snapshot;\n if (\"history\" in metadata)\n entry.history = metadata.history;\n if (\"pending\" in metadata) {\n entry.pending = metadata.pending;\n if (entry.pending)\n this.sendPendingWorkflowMessage(entry.pending, sequenceId);\n }\n\n return okAsync();\n }\n\n query(start: SequenceId | 'snapshot' | 'start', end: SequenceId | 'end', snapshotId?: SequenceId): ResultAsync<QueryValue<T>,QueryError> {\n if (start === 'start')\n start = this.startSequenceId;\n else if (start === 'snapshot')\n start = this.startSequenceId + BigInt(this.findSnapshotIndex());\n else if (start < this.startSequenceId || start > this.endSequenceId)\n return errAsync(infinisheetRangeError(\"start index out of range\"));\n\n if (end === 'end')\n end = this.endSequenceId;\n\n const num = end - start;\n const isComplete = num <= BigInt(QUERY_PAGE_SIZE);\n let numToReturn = isComplete ? Number(num) : QUERY_PAGE_SIZE;\n const firstIndex = Number(start - this.startSequenceId);\n if (firstIndex + numToReturn > this.entries.length)\n numToReturn = this.entries.length - firstIndex;\n\n \n const value: QueryValue<T> = {\n startSequenceId: start,\n endSequenceId: start + BigInt(numToReturn),\n isComplete,\n entries: this.entries.slice(firstIndex, firstIndex + numToReturn)\n }\n\n if (snapshotId !== undefined) {\n const snapshot = this.findSnapshot();\n if (snapshot && snapshot.sequenceId !== snapshotId)\n value.lastSnapshot = snapshot;\n }\n\n return okAsync(value);\n }\n\n truncate(start: SequenceId): ResultAsync<void,TruncateError> {\n if (start < this.startSequenceId)\n return errAsync(infinisheetRangeError(\"start before start entry in the log\"));\n\n if (start === this.startSequenceId)\n return okAsync();\n \n if (start === this.endSequenceId) {\n this.startSequenceId = start;\n this.endSequenceId = start;\n this.entries = [];\n return okAsync();\n }\n\n if (start > this.endSequenceId)\n return errAsync(infinisheetRangeError(\"start after end entry in the log\"));\n\n const numToRemove = start - this.startSequenceId;\n this.startSequenceId = start;\n this.entries.splice(0, Number(numToRemove));\n return okAsync();\n }\n\n private sendPendingWorkflowMessage(workflow: WorkflowId, sequenceId: SequenceId) {\n if (this.workerHost) {\n const message: PendingWorkflowMessage = { type: 'PendingWorkflowMessage', sequenceId, workflow }\n this.workerHost.postMessage(message);\n }\n }\n\n private findSnapshot(): SnapshotValue | undefined {\n for (let i = this.entries.length - 1; i > 0; i--) {\n const entry = this.entries[i]!;\n if (entry.snapshot) {\n return { sequenceId: this.startSequenceId + BigInt(i), blobId: entry.snapshot }\n }\n }\n\n return undefined;\n }\n\n private findSnapshotIndex(): number {\n for (let i = this.entries.length - 1; i > 0; i--) {\n const entry = this.entries[i]!;\n if (entry.snapshot)\n return i;\n }\n\n // If no other entry has a snapshot use the first (whether it has a snapshot or not)\n return 0;\n }\n\n private startSequenceId: SequenceId;\n private endSequenceId: SequenceId;\n private entries: T[];\n}","import type { EventLog, LogEntry, LogMetadata, SequenceId, Result, QueryValue, \n AddEntryError, QueryError, TruncateError, MetadataError, \n AddEntryValue} from \"@candidstartup/infinisheet-types\";\nimport { ResultAsync } from \"@candidstartup/infinisheet-types\";\n\n/** Creates a promise that provides value after a delay (in ms) */\nexport function delayPromise<T>(value: T, delay: number): Promise<T> {\n return new Promise<T>((resolve) => {\n setTimeout(() => resolve(value), delay);\n })\n}\n\n// Utility method that completes a `ResultAsync` after a delay (in ms)\nexport function delayResult<T,E>(result: ResultAsync<T,E>, delay: number): ResultAsync<T,E> {\n const promiseLike = result.then<Result<T,E>,never>((r) => delayPromise(r, delay));\n return new ResultAsync(Promise.resolve(promiseLike));\n}\n\n/**\n * Wrapper around an {@link EventLog} that injects latency\n * \n * Intended for use when simulating the effects of latency in a real implementation\n */\nexport class DelayEventLog<T extends LogEntry> implements EventLog<T> {\n constructor(base: EventLog<T>, delay: number=0) {\n this.base = base;\n this.delay = delay;\n }\n\n /** Delay in milliseconds to add to response from each API call */\n delay: number;\n\n addEntry(entry: T, sequenceId: SequenceId, snapshotId?: SequenceId): ResultAsync<AddEntryValue,AddEntryError> {\n return delayResult(this.base.addEntry(entry, sequenceId, snapshotId), this.delay);\n }\n\n setMetadata(sequenceId: SequenceId, metadata: LogMetadata): ResultAsync<void,MetadataError> {\n return delayResult(this.base.setMetadata(sequenceId, metadata), this.delay);\n }\n\n query(start: SequenceId | 'snapshot' | 'start', end: SequenceId | 'end', snapshotId?: SequenceId): ResultAsync<QueryValue<T>,QueryError> {\n return delayResult(this.base.query(start, end, snapshotId), this.delay);\n }\n\n truncate(start: SequenceId): ResultAsync<void,TruncateError> {\n return delayResult(this.base.truncate(start), this.delay);\n }\n\n private base: EventLog<T>;\n}","import type { BlobStore, BlobDir, BlobName, ResultAsync, \n GetRootDirError, ReadBlobError, WriteBlobError, RemoveBlobError, BlobDirEntries, \n GetDirError, DirQueryError, RemoveAllBlobDirError } from \"@candidstartup/infinisheet-types\";\nimport { errAsync, okAsync, storageError, notBlobError, notBlobDirError, invalidBlobNameError, noContinuationError } from \"@candidstartup/infinisheet-types\";\n\nconst QUERY_PAGE_SIZE = 10;\n\ninterface SimpleBlobStoreIter {\n dir: SimpleBlobDir;\n iter: MapIterator<[BlobName, BlobDir<SimpleBlobStoreContinuation>|Uint8Array]> | undefined;\n}\n\n/** \n * Branding Enum. Used by {@link SimpleBlobStore} to ensure that\n * you'll get a type error if you pass some random object where a `SimpleBlobStoreContinuation`\n * is expected.\n * @internal\n */\nexport enum _SimpleBlobStoreBrand { _DO_NOT_USE=\"\" };\n\n/**\n * Opaque type representing a {@link SimpleSpreadsheetData} snapshot. All the\n * internal implementation details are hidden from the exported API.\n */\nexport interface SimpleBlobStoreContinuation {\n /** @internal */\n _brand: _SimpleBlobStoreBrand;\n}\n\nfunction asIter(continuation: SimpleBlobStoreContinuation) {\n return continuation as unknown as SimpleBlobStoreIter;\n}\n\nfunction asContinuation(iter: SimpleBlobStoreIter) {\n return iter as unknown as SimpleBlobStoreContinuation;\n}\n\n/**\n * Reference implementation of {@link BlobDir}\n * \n * Intended for use as a mock, to compare with an optimized implementation when testing and\n * for simple sample apps. Simplest possible implementation, no attempt at optimization.\n */\nexport class SimpleBlobDir implements BlobDir<SimpleBlobStoreContinuation> {\n constructor () {\n this.map = new Map;\n }\n\n // Logically directories only exist if they have entries. To simplify implementation we\n // create on demand and treat empty dir the same as non-existent dir.\n\n readBlob(name: BlobName): ResultAsync<Uint8Array,ReadBlobError> {\n if (!name)\n return errAsync(invalidBlobNameError());\n const value = this.map.get(name);\n if (!value || (value instanceof SimpleBlobDir && value.map.size == 0))\n return errAsync(storageError(\"Blob does not exist\", 404));\n\n if (value instanceof Uint8Array) {\n return okAsync(value);\n } else {\n return errAsync(notBlobError())\n }\n }\n\n writeBlob(name: BlobName, content: Uint8Array): ResultAsync<void,WriteBlobError> {\n if (!name)\n return errAsync(invalidBlobNameError());\n const value = this.map.get(name);\n if (value instanceof SimpleBlobDir && value.map.size > 0)\n return errAsync(notBlobError());\n\n this.map.set(name,new Uint8Array(content));\n return okAsync();\n }\n\n removeBlob(name: BlobName): ResultAsync<void,RemoveBlobError> {\n if (!name)\n return errAsync(invalidBlobNameError());\n const value = this.map.get(name);\n if (value instanceof SimpleBlobDir && value.map.size > 0)\n return errAsync(notBlobError());\n\n this.map.delete(name);\n return okAsync();\n }\n\n getDir(name: BlobName): ResultAsync<BlobDir<SimpleBlobStoreContinuation>,GetDirError> {\n if (!name)\n return errAsync(invalidBlobNameError());\n\n const value = this.map.get(name);\n if (!value) {\n const dir = new SimpleBlobDir();\n this.map.set(name,dir);\n return okAsync(dir);\n }\n\n if (value instanceof SimpleBlobDir)\n return okAsync(value);\n\n return errAsync(notBlobDirError());\n }\n\n query(continuation?: SimpleBlobStoreContinuation): ResultAsync<BlobDirEntries<SimpleBlobStoreContinuation>,DirQueryError> {\n let iter;\n if (continuation) {\n const sbsIter = asIter(continuation);\n if (sbsIter.dir !== this)\n return errAsync(noContinuationError(\"Invalid continuation\"));\n iter = sbsIter.iter;\n if (!iter)\n return errAsync(noContinuationError(\"Can't reuse continuation\"));\n\n // Iterator is mutated so can't reuse continuation to retry query\n sbsIter.iter = undefined;\n } else {\n iter = this.map.entries();\n }\n const entries: BlobDirEntries<SimpleBlobStoreContinuation> = { blobs: [], dirs: [] }\n\n for (let i = 0; i < QUERY_PAGE_SIZE; i ++) {\n const result = iter.next();\n if (result.done)\n return okAsync(entries);\n\n const [name, value] = result.value;\n if (value instanceof SimpleBlobDir) {\n if (value.map.size > 0)\n entries.dirs.push(name);\n } else {\n entries.blobs.push(name);\n }\n }\n\n entries.continuation = asContinuation({ dir: this, iter });\n return okAsync(entries);\n }\n\n removeAll(): ResultAsync<void,RemoveAllBlobDirError> {\n this.map.clear();\n return okAsync();\n }\n \n private map: Map<BlobName,BlobDir<SimpleBlobStoreContinuation>|Uint8Array>\n}\n\n/**\n * Reference implementation of {@link BlobStore}\n * \n * Intended for use as a mock, to compare with an optimized implementation when testing and\n * for simple sample apps. Simplest possible implementation, no attempt at optimization.\n */\nexport class SimpleBlobStore implements BlobStore<SimpleBlobStoreContinuation> {\n constructor () {\n this.root = undefined;\n }\n\n getRootDir(): ResultAsync<SimpleBlobDir,GetRootDirError> {\n if (!this.root)\n this.root = new SimpleBlobDir;\n return okAsync(this.root);\n }\n\n private root: SimpleBlobDir | undefined;\n}\n","import type { WorkerMessage, MessageHandler } from \"@candidstartup/infinisheet-types\";\nimport { InfiniSheetWorker, PostMessageWorkerHost } from \"@candidstartup/infinisheet-types\";\n\n/**\n * Reference implementation of {@link InfiniSheetWorker}\n * \n * In-process event loop based workers\n * \n * Intended for use as a mock, to compare with an optimized implementation when testing and\n * for simple sample apps. Simplest possible implementation, no attempt at optimization.\n */\nexport class SimpleWorker<T extends WorkerMessage> implements InfiniSheetWorker<T> {\n constructor() {\n }\n\n onReceiveMessage: MessageHandler<T> | undefined;\n}\n\n/**\n * Reference implementation of {@link PostMessageWorkerHost}\n * \n * In-process event loop based workers\n * \n * Intended for use as a mock, to compare with an optimized implementation when testing and\n * for simple sample apps. Simplest possible implementation, no attempt at optimization.\n */\nexport class SimpleWorkerHost<T extends WorkerMessage> implements PostMessageWorkerHost<T> {\n constructor(worker: SimpleWorker<T>, delay: number = 0) {\n this.worker = worker;\n this.delay = delay;\n }\n\n /** @internal */\n isHost(): this is PostMessageWorkerHost<T> { return true; }\n\n postMessage(message: T): void {\n const handler = this.worker.onReceiveMessage;\n if (handler) {\n // Using setTimeout ensures message is delivered via the event loop\n setTimeout(() => { \n const result = handler(message);\n result.orElse(\n // Intentionally results in an unhandled exception in event handler\n // Should never use SimplerWorkers with workflow that can result in error\n // Can't be unit tested as blows up the test\n /* istanbul ignore next */\n (error) => {\n console.log(`SimpleWorker returned error ${JSON.stringify(error)}`);\n throw Error(\"SimpleWorker returned error\", { cause: error });\n }\n )\n }, this.delay);\n } else {\n throw Error(\"Worker has no message handler\");\n }\n }\n\n private worker: SimpleWorker<T>;\n private delay: number;\n}\n"],"names":["asContent","asSnapshot","QUERY_PAGE_SIZE"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@candidstartup/simple-spreadsheet-data",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.13.0",
|
|
5
5
|
"description": "Reference implementations of SpreadsheetData",
|
|
6
6
|
"author": "Tim Wiegand <tim.wiegand@thecandidstartup.org>",
|
|
7
7
|
"license": "BSD-3-Clause",
|
|
@@ -49,7 +49,7 @@
|
|
|
49
49
|
"test": "vitest"
|
|
50
50
|
},
|
|
51
51
|
"dependencies": {
|
|
52
|
-
"@candidstartup/infinisheet-types": "^0.
|
|
52
|
+
"@candidstartup/infinisheet-types": "^0.13.0"
|
|
53
53
|
},
|
|
54
|
-
"gitHead": "
|
|
54
|
+
"gitHead": "ca46dae5575a3011416803e2b159457ecb59eaee"
|
|
55
55
|
}
|