@byearlybird/starling 0.4.0 → 0.6.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 +42 -129
- package/dist/index.js +1 -404
- package/package.json +1 -1
- package/dist/chunk-Bp6m_JJh.js +0 -13
package/dist/index.d.ts
CHANGED
|
@@ -1,160 +1,73 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
//#region src/clock.d.ts
|
|
4
|
-
declare namespace clock_d_exports {
|
|
5
|
-
export { Clock, create$2 as create };
|
|
6
|
-
}
|
|
7
|
-
type Clock = {
|
|
8
|
-
now: () => string;
|
|
9
|
-
latest: () => string;
|
|
10
|
-
forward: (eventstamp: string) => void;
|
|
11
|
-
};
|
|
12
|
-
declare const create$2: () => Clock;
|
|
13
|
-
declare namespace value_d_exports {
|
|
14
|
-
export { EncodedValue, decode$3 as decode, encode$3 as encode, isEncoded, merge$2 as merge };
|
|
15
|
-
}
|
|
1
|
+
//#region src/value.d.ts
|
|
16
2
|
type EncodedValue<T$1> = {
|
|
17
3
|
"~value": T$1;
|
|
18
4
|
"~eventstamp": string;
|
|
19
5
|
};
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
declare const merge$2: <T>(into: EncodedValue<T>, from: EncodedValue<T>) => EncodedValue<T>;
|
|
23
|
-
declare const isEncoded: (value: unknown) => boolean;
|
|
24
|
-
declare namespace record_d_exports {
|
|
25
|
-
export { EncodedRecord, decode$2 as decode, encode$2 as encode, isObject, merge$1 as merge };
|
|
26
|
-
}
|
|
6
|
+
//#endregion
|
|
7
|
+
//#region src/record.d.ts
|
|
27
8
|
type EncodedRecord = {
|
|
28
9
|
[key: string]: EncodedValue<unknown> | EncodedRecord;
|
|
29
10
|
};
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
declare const decode$2: <T extends Record<string, unknown>>(obj: EncodedRecord) => T;
|
|
33
|
-
declare const merge$1: (into: EncodedRecord, from: EncodedRecord) => EncodedRecord;
|
|
34
|
-
declare namespace document_d_exports {
|
|
35
|
-
export { EncodedDocument, decode$1 as decode, del, encode$1 as encode, merge };
|
|
36
|
-
}
|
|
11
|
+
//#endregion
|
|
12
|
+
//#region src/document.d.ts
|
|
37
13
|
type EncodedDocument = {
|
|
38
14
|
"~id": string;
|
|
39
15
|
"~data": EncodedValue<unknown> | EncodedRecord;
|
|
40
16
|
"~deletedAt": string | null;
|
|
41
17
|
};
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
};
|
|
48
|
-
declare const merge: (into: EncodedDocument, from: EncodedDocument) => EncodedDocument;
|
|
49
|
-
declare const del: (doc: EncodedDocument, eventstamp: string) => EncodedDocument;
|
|
50
|
-
declare namespace eventstamp_d_exports {
|
|
51
|
-
export { decode, encode };
|
|
52
|
-
}
|
|
53
|
-
declare const encode: (timestampMs: number, counter: number) => string;
|
|
54
|
-
declare const decode: (eventstamp: string) => {
|
|
55
|
-
timestampMs: number;
|
|
56
|
-
counter: number;
|
|
18
|
+
//#endregion
|
|
19
|
+
//#region src/transaction.d.ts
|
|
20
|
+
type DeepPartial<T$1> = T$1 extends object ? { [P in keyof T$1]?: DeepPartial<T$1[P]> } : T$1;
|
|
21
|
+
type StorePutOptions = {
|
|
22
|
+
withId?: string;
|
|
57
23
|
};
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
entries(): MapIterator<[string, EncodedDocument]>;
|
|
66
|
-
readonly size: number;
|
|
67
|
-
begin(): {
|
|
68
|
-
get(key: string): EncodedDocument | null;
|
|
69
|
-
put(key: string, value: EncodedDocument): void;
|
|
70
|
-
patch(key: string, value: EncodedDocument): void;
|
|
71
|
-
del(key: string, eventstamp: string): void;
|
|
72
|
-
has(key: string): boolean;
|
|
73
|
-
commit(): void;
|
|
74
|
-
rollback(): void;
|
|
75
|
-
};
|
|
24
|
+
type StoreSetTransaction<T$1> = {
|
|
25
|
+
add: (value: T$1, options?: StorePutOptions) => string;
|
|
26
|
+
update: (key: string, value: DeepPartial<T$1>) => void;
|
|
27
|
+
merge: (doc: EncodedDocument) => void;
|
|
28
|
+
del: (key: string) => void;
|
|
29
|
+
get: (key: string) => T$1 | null;
|
|
30
|
+
rollback: () => void;
|
|
76
31
|
};
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
}
|
|
80
|
-
type DeepPartial<T$1> = T$1 extends object ? { [P in keyof T$1]?: DeepPartial<T$1[P]> } : T$1;
|
|
81
|
-
/**
|
|
82
|
-
* Called once per commit with all put operations accumulated as decoded entries.
|
|
83
|
-
* Only fires if at least one put occurred.
|
|
84
|
-
*/
|
|
85
|
-
type StoreOnPut<T$1> = (entries: ReadonlyArray<readonly [string, T$1]>) => void;
|
|
86
|
-
/**
|
|
87
|
-
* Called once per commit with all patch operations accumulated as decoded entries.
|
|
88
|
-
* Only fires if at least one patch occurred.
|
|
89
|
-
*/
|
|
90
|
-
type StoreOnPatch<T$1> = (entries: ReadonlyArray<readonly [string, T$1]>) => void;
|
|
91
|
-
/**
|
|
92
|
-
* Called once per commit with all deleted keys (IDs).
|
|
93
|
-
* Only fires if at least one delete occurred.
|
|
94
|
-
*/
|
|
95
|
-
type StoreOnDelete = (keys: ReadonlyArray<string>) => void;
|
|
96
|
-
/**
|
|
97
|
-
* Called before a put operation is applied.
|
|
98
|
-
* Throws to reject the operation.
|
|
99
|
-
*/
|
|
100
|
-
type StoreOnBeforePut<T$1> = (key: string, value: T$1) => void;
|
|
101
|
-
/**
|
|
102
|
-
* Called before a patch operation is applied.
|
|
103
|
-
* Throws to reject the operation.
|
|
104
|
-
*/
|
|
105
|
-
type StoreOnBeforePatch<T$1> = (key: string, value: DeepPartial<T$1>) => void;
|
|
32
|
+
//#endregion
|
|
33
|
+
//#region src/store.d.ts
|
|
106
34
|
/**
|
|
107
|
-
*
|
|
108
|
-
*
|
|
35
|
+
* Type constraint to prevent Promise returns from set callbacks.
|
|
36
|
+
* Transactions must be synchronous operations.
|
|
109
37
|
*/
|
|
110
|
-
type
|
|
38
|
+
type NotPromise<T$1> = T$1 extends Promise<any> ? never : T$1;
|
|
111
39
|
/**
|
|
112
|
-
*
|
|
113
|
-
*
|
|
114
|
-
* Arrays are readonly to prevent external mutation.
|
|
40
|
+
* Plugin lifecycle and event hooks.
|
|
41
|
+
* All hooks are optional except onInit and onDispose, which are required.
|
|
115
42
|
*/
|
|
116
|
-
type
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
onDelete?: StoreOnDelete;
|
|
123
|
-
};
|
|
124
|
-
type StoreTransaction<T$1> = {
|
|
125
|
-
put: (key: string, value: T$1) => void;
|
|
126
|
-
patch: (key: string, value: DeepPartial<T$1>) => void;
|
|
127
|
-
merge: (doc: EncodedDocument) => void;
|
|
128
|
-
del: (key: string) => void;
|
|
129
|
-
has: (key: string) => boolean;
|
|
130
|
-
commit: (opts?: {
|
|
131
|
-
silent: boolean;
|
|
132
|
-
}) => void;
|
|
133
|
-
rollback: () => void;
|
|
43
|
+
type PluginHooks<T$1> = {
|
|
44
|
+
onInit: (store: Store<T$1>) => Promise<void> | void;
|
|
45
|
+
onDispose: () => Promise<void> | void;
|
|
46
|
+
onAdd?: (entries: ReadonlyArray<readonly [string, T$1]>) => void;
|
|
47
|
+
onUpdate?: (entries: ReadonlyArray<readonly [string, T$1]>) => void;
|
|
48
|
+
onDelete?: (keys: ReadonlyArray<string>) => void;
|
|
134
49
|
};
|
|
135
50
|
type PluginMethods = Record<string, (...args: any[]) => any>;
|
|
136
|
-
type
|
|
137
|
-
|
|
138
|
-
dispose: () => Promise<void> | void;
|
|
139
|
-
hooks?: StoreHooks<T$1>;
|
|
51
|
+
type Plugin<T$1, M$1 extends PluginMethods = {}> = {
|
|
52
|
+
hooks: PluginHooks<T$1>;
|
|
140
53
|
methods?: M$1;
|
|
141
54
|
};
|
|
142
|
-
type Plugin<T$1, M$1 extends PluginMethods = {}> = (store: Store<T$1, any>) => PluginHandle<T$1, M$1>;
|
|
143
55
|
type Store<T$1, Extended = {}> = {
|
|
144
56
|
get: (key: string) => T$1 | null;
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
57
|
+
begin: <R = void>(callback: (tx: StoreSetTransaction<T$1>) => NotPromise<R>, opts?: {
|
|
58
|
+
silent?: boolean;
|
|
59
|
+
}) => NotPromise<R>;
|
|
60
|
+
add: (value: T$1, options?: StorePutOptions) => string;
|
|
61
|
+
update: (key: string, value: DeepPartial<T$1>) => void;
|
|
62
|
+
del: (key: string) => void;
|
|
148
63
|
entries: () => IterableIterator<readonly [string, T$1]>;
|
|
149
64
|
snapshot: () => EncodedDocument[];
|
|
150
|
-
put: (key: string, value: T$1) => void;
|
|
151
|
-
patch: (key: string, value: DeepPartial<T$1>) => void;
|
|
152
|
-
del: (key: string) => void;
|
|
153
|
-
begin: () => StoreTransaction<T$1>;
|
|
154
65
|
use: <M extends PluginMethods>(plugin: Plugin<T$1, M>) => Store<T$1, Extended & M>;
|
|
155
66
|
init: () => Promise<Store<T$1, Extended>>;
|
|
156
67
|
dispose: () => Promise<void>;
|
|
157
68
|
} & Extended;
|
|
158
|
-
declare const
|
|
69
|
+
declare const createStore: <T>(config?: {
|
|
70
|
+
getId?: () => string;
|
|
71
|
+
}) => Store<T, {}>;
|
|
159
72
|
//#endregion
|
|
160
|
-
export { type
|
|
73
|
+
export { type EncodedDocument, Plugin, PluginHooks, PluginMethods, Store, createStore };
|
package/dist/index.js
CHANGED
|
@@ -1,404 +1 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
//#region src/eventstamp.ts
|
|
4
|
-
var eventstamp_exports = /* @__PURE__ */ __export({
|
|
5
|
-
decode: () => decode$3,
|
|
6
|
-
encode: () => encode$3
|
|
7
|
-
});
|
|
8
|
-
const encode$3 = (timestampMs, counter) => {
|
|
9
|
-
return `${new Date(timestampMs).toISOString()}|${counter.toString(16).padStart(8, "0")}`;
|
|
10
|
-
};
|
|
11
|
-
const decode$3 = (eventstamp) => {
|
|
12
|
-
const pipeIndex = eventstamp.indexOf("|");
|
|
13
|
-
const isoString = eventstamp.slice(0, pipeIndex);
|
|
14
|
-
const hexCounter = eventstamp.slice(pipeIndex + 1);
|
|
15
|
-
return {
|
|
16
|
-
timestampMs: new Date(isoString).getTime(),
|
|
17
|
-
counter: parseInt(hexCounter, 16)
|
|
18
|
-
};
|
|
19
|
-
};
|
|
20
|
-
|
|
21
|
-
//#endregion
|
|
22
|
-
//#region src/clock.ts
|
|
23
|
-
var clock_exports = /* @__PURE__ */ __export({ create: () => create$2 });
|
|
24
|
-
const create$2 = () => {
|
|
25
|
-
let counter = 0;
|
|
26
|
-
let lastMs = Date.now();
|
|
27
|
-
return {
|
|
28
|
-
now: () => {
|
|
29
|
-
const nowMs = Date.now();
|
|
30
|
-
if (nowMs <= lastMs) counter++;
|
|
31
|
-
else {
|
|
32
|
-
lastMs = nowMs;
|
|
33
|
-
counter = 0;
|
|
34
|
-
}
|
|
35
|
-
return encode$3(nowMs, counter);
|
|
36
|
-
},
|
|
37
|
-
latest() {
|
|
38
|
-
return encode$3(lastMs, counter);
|
|
39
|
-
},
|
|
40
|
-
forward(eventstamp) {
|
|
41
|
-
if (eventstamp > this.latest()) {
|
|
42
|
-
const newer = decode$3(eventstamp);
|
|
43
|
-
lastMs = newer.timestampMs;
|
|
44
|
-
counter = newer.counter;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
};
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
//#endregion
|
|
51
|
-
//#region src/value.ts
|
|
52
|
-
var value_exports = /* @__PURE__ */ __export({
|
|
53
|
-
decode: () => decode$2,
|
|
54
|
-
encode: () => encode$2,
|
|
55
|
-
isEncoded: () => isEncoded,
|
|
56
|
-
merge: () => merge$2
|
|
57
|
-
});
|
|
58
|
-
const encode$2 = (value, eventstamp) => ({
|
|
59
|
-
"~value": value,
|
|
60
|
-
"~eventstamp": eventstamp
|
|
61
|
-
});
|
|
62
|
-
const decode$2 = (value) => value["~value"];
|
|
63
|
-
const merge$2 = (into, from) => ({
|
|
64
|
-
"~value": into["~eventstamp"] > from["~eventstamp"] ? into["~value"] : from["~value"],
|
|
65
|
-
"~eventstamp": into["~eventstamp"] > from["~eventstamp"] ? into["~eventstamp"] : from["~eventstamp"]
|
|
66
|
-
});
|
|
67
|
-
const isEncoded = (value) => !!(typeof value === "object" && value !== null && "~value" in value && "~eventstamp" in value);
|
|
68
|
-
|
|
69
|
-
//#endregion
|
|
70
|
-
//#region src/record.ts
|
|
71
|
-
var record_exports = /* @__PURE__ */ __export({
|
|
72
|
-
decode: () => decode$1,
|
|
73
|
-
encode: () => encode$1,
|
|
74
|
-
isObject: () => isObject,
|
|
75
|
-
merge: () => merge$1
|
|
76
|
-
});
|
|
77
|
-
const isObject = (value) => !!(value != null && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype);
|
|
78
|
-
const encode$1 = (obj, eventstamp) => {
|
|
79
|
-
const result = {};
|
|
80
|
-
const step = (target, output) => {
|
|
81
|
-
for (const key in target) {
|
|
82
|
-
if (!Object.hasOwn(target, key)) continue;
|
|
83
|
-
const value = target[key];
|
|
84
|
-
if (isObject(value)) {
|
|
85
|
-
output[key] = {};
|
|
86
|
-
step(value, output[key]);
|
|
87
|
-
} else output[key] = encode$2(value, eventstamp);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
90
|
-
step(obj, result);
|
|
91
|
-
return result;
|
|
92
|
-
};
|
|
93
|
-
const decode$1 = (obj) => {
|
|
94
|
-
const result = {};
|
|
95
|
-
const step = (source, output) => {
|
|
96
|
-
for (const key in source) {
|
|
97
|
-
if (!Object.hasOwn(source, key)) continue;
|
|
98
|
-
const value = source[key];
|
|
99
|
-
if (isEncoded(value)) output[key] = decode$2(value);
|
|
100
|
-
else if (isObject(value)) {
|
|
101
|
-
output[key] = {};
|
|
102
|
-
step(value, output[key]);
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
};
|
|
106
|
-
step(obj, result);
|
|
107
|
-
return result;
|
|
108
|
-
};
|
|
109
|
-
const merge$1 = (into, from) => {
|
|
110
|
-
const result = {};
|
|
111
|
-
const step = (v1, v2, output) => {
|
|
112
|
-
for (const key in v1) {
|
|
113
|
-
if (!Object.hasOwn(v1, key)) continue;
|
|
114
|
-
const value1 = v1[key];
|
|
115
|
-
const value2 = v2[key];
|
|
116
|
-
if (isEncoded(value1) && isEncoded(value2)) output[key] = merge$2(value1, value2);
|
|
117
|
-
else if (isEncoded(value1)) output[key] = value1;
|
|
118
|
-
else if (isObject(value1) && isObject(value2)) {
|
|
119
|
-
output[key] = {};
|
|
120
|
-
step(value1, value2, output[key]);
|
|
121
|
-
} else if (value1) output[key] = value1;
|
|
122
|
-
}
|
|
123
|
-
for (const key in v2) {
|
|
124
|
-
if (!Object.hasOwn(v2, key) || Object.hasOwn(output, key)) continue;
|
|
125
|
-
const value = v2[key];
|
|
126
|
-
if (value !== void 0) output[key] = value;
|
|
127
|
-
}
|
|
128
|
-
};
|
|
129
|
-
step(into, from, result);
|
|
130
|
-
return result;
|
|
131
|
-
};
|
|
132
|
-
|
|
133
|
-
//#endregion
|
|
134
|
-
//#region src/document.ts
|
|
135
|
-
var document_exports = /* @__PURE__ */ __export({
|
|
136
|
-
decode: () => decode,
|
|
137
|
-
del: () => del,
|
|
138
|
-
encode: () => encode,
|
|
139
|
-
merge: () => merge
|
|
140
|
-
});
|
|
141
|
-
const encode = (id, obj, eventstamp, deletedAt = null) => ({
|
|
142
|
-
"~id": id,
|
|
143
|
-
"~data": isObject(obj) ? encode$1(obj, eventstamp) : encode$2(obj, eventstamp),
|
|
144
|
-
"~deletedAt": deletedAt
|
|
145
|
-
});
|
|
146
|
-
const decode = (doc) => ({
|
|
147
|
-
"~id": doc["~id"],
|
|
148
|
-
"~data": isEncoded(doc["~data"]) ? decode$2(doc["~data"]) : decode$1(doc["~data"]),
|
|
149
|
-
"~deletedAt": doc["~deletedAt"]
|
|
150
|
-
});
|
|
151
|
-
const merge = (into, from) => {
|
|
152
|
-
const intoIsValue = isEncoded(into["~data"]);
|
|
153
|
-
const fromIsValue = isEncoded(from["~data"]);
|
|
154
|
-
if (intoIsValue !== fromIsValue) throw new Error(`Cannot merge documents with incompatible types: ${intoIsValue ? "primitive" : "object"} vs ${fromIsValue ? "primitive" : "object"}`);
|
|
155
|
-
const mergedData = intoIsValue && fromIsValue ? merge$2(into["~data"], from["~data"]) : merge$1(into["~data"], from["~data"]);
|
|
156
|
-
const mergedDeletedAt = into["~deletedAt"] && from["~deletedAt"] ? into["~deletedAt"] > from["~deletedAt"] ? into["~deletedAt"] : from["~deletedAt"] : into["~deletedAt"] || from["~deletedAt"] || null;
|
|
157
|
-
return {
|
|
158
|
-
"~id": into["~id"],
|
|
159
|
-
"~data": mergedData,
|
|
160
|
-
"~deletedAt": mergedDeletedAt
|
|
161
|
-
};
|
|
162
|
-
};
|
|
163
|
-
const del = (doc, eventstamp) => ({
|
|
164
|
-
...doc,
|
|
165
|
-
"~deletedAt": eventstamp
|
|
166
|
-
});
|
|
167
|
-
|
|
168
|
-
//#endregion
|
|
169
|
-
//#region src/kv.ts
|
|
170
|
-
var kv_exports = /* @__PURE__ */ __export({ create: () => create$1 });
|
|
171
|
-
const create$1 = (iterable) => {
|
|
172
|
-
let readMap = new Map(iterable);
|
|
173
|
-
function cloneMap(src) {
|
|
174
|
-
return new Map(src);
|
|
175
|
-
}
|
|
176
|
-
return {
|
|
177
|
-
get(key) {
|
|
178
|
-
return readMap.get(key) ?? null;
|
|
179
|
-
},
|
|
180
|
-
has(key) {
|
|
181
|
-
return readMap.has(key);
|
|
182
|
-
},
|
|
183
|
-
values() {
|
|
184
|
-
return readMap.values();
|
|
185
|
-
},
|
|
186
|
-
entries() {
|
|
187
|
-
return readMap.entries();
|
|
188
|
-
},
|
|
189
|
-
get size() {
|
|
190
|
-
return readMap.size;
|
|
191
|
-
},
|
|
192
|
-
begin() {
|
|
193
|
-
const staging = cloneMap(readMap);
|
|
194
|
-
let committed = false;
|
|
195
|
-
return {
|
|
196
|
-
get(key) {
|
|
197
|
-
return staging.get(key) ?? null;
|
|
198
|
-
},
|
|
199
|
-
put(key, value) {
|
|
200
|
-
staging.set(key, value);
|
|
201
|
-
},
|
|
202
|
-
patch(key, value) {
|
|
203
|
-
const prev = staging.get(key);
|
|
204
|
-
staging.set(key, prev ? merge(prev, value) : value);
|
|
205
|
-
},
|
|
206
|
-
del(key, eventstamp) {
|
|
207
|
-
const prev = staging.get(key);
|
|
208
|
-
if (prev) staging.set(key, del(prev, eventstamp));
|
|
209
|
-
},
|
|
210
|
-
has(key) {
|
|
211
|
-
return staging.get(key) !== void 0;
|
|
212
|
-
},
|
|
213
|
-
commit() {
|
|
214
|
-
if (committed) return;
|
|
215
|
-
committed = true;
|
|
216
|
-
readMap = staging;
|
|
217
|
-
},
|
|
218
|
-
rollback() {
|
|
219
|
-
committed = true;
|
|
220
|
-
}
|
|
221
|
-
};
|
|
222
|
-
}
|
|
223
|
-
};
|
|
224
|
-
};
|
|
225
|
-
|
|
226
|
-
//#endregion
|
|
227
|
-
//#region src/store.ts
|
|
228
|
-
var store_exports = /* @__PURE__ */ __export({ create: () => create });
|
|
229
|
-
const create = () => {
|
|
230
|
-
const kv = create$1();
|
|
231
|
-
const clock = create$2();
|
|
232
|
-
const encodeValue = (key, value) => encode(key, value, clock.now());
|
|
233
|
-
const listeners = {
|
|
234
|
-
beforePut: /* @__PURE__ */ new Set(),
|
|
235
|
-
beforePatch: /* @__PURE__ */ new Set(),
|
|
236
|
-
beforeDel: /* @__PURE__ */ new Set(),
|
|
237
|
-
put: /* @__PURE__ */ new Set(),
|
|
238
|
-
patch: /* @__PURE__ */ new Set(),
|
|
239
|
-
del: /* @__PURE__ */ new Set()
|
|
240
|
-
};
|
|
241
|
-
const initializers = /* @__PURE__ */ new Set();
|
|
242
|
-
const disposers = /* @__PURE__ */ new Set();
|
|
243
|
-
const decodeActive = (doc) => {
|
|
244
|
-
if (!doc || doc["~deletedAt"]) return null;
|
|
245
|
-
return decode(doc)["~data"];
|
|
246
|
-
};
|
|
247
|
-
return {
|
|
248
|
-
get(key) {
|
|
249
|
-
return decodeActive(kv.get(key));
|
|
250
|
-
},
|
|
251
|
-
has(key) {
|
|
252
|
-
return decodeActive(kv.get(key)) !== null;
|
|
253
|
-
},
|
|
254
|
-
values() {
|
|
255
|
-
function* iterator() {
|
|
256
|
-
for (const doc of kv.values()) {
|
|
257
|
-
const data = decodeActive(doc);
|
|
258
|
-
if (data !== null) yield data;
|
|
259
|
-
}
|
|
260
|
-
}
|
|
261
|
-
return iterator();
|
|
262
|
-
},
|
|
263
|
-
entries() {
|
|
264
|
-
function* iterator() {
|
|
265
|
-
for (const [key, doc] of kv.entries()) {
|
|
266
|
-
const data = decodeActive(doc);
|
|
267
|
-
if (data !== null) yield [key, data];
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
return iterator();
|
|
271
|
-
},
|
|
272
|
-
snapshot() {
|
|
273
|
-
return Array.from(kv.values());
|
|
274
|
-
},
|
|
275
|
-
get size() {
|
|
276
|
-
let count = 0;
|
|
277
|
-
for (const doc of kv.values()) if (doc && !doc["~deletedAt"]) count++;
|
|
278
|
-
return count;
|
|
279
|
-
},
|
|
280
|
-
put(key, value) {
|
|
281
|
-
const tx = this.begin();
|
|
282
|
-
tx.put(key, value);
|
|
283
|
-
tx.commit();
|
|
284
|
-
},
|
|
285
|
-
patch(key, value) {
|
|
286
|
-
const tx = this.begin();
|
|
287
|
-
tx.patch(key, value);
|
|
288
|
-
tx.commit();
|
|
289
|
-
},
|
|
290
|
-
del(key) {
|
|
291
|
-
const tx = this.begin();
|
|
292
|
-
tx.del(key);
|
|
293
|
-
tx.commit();
|
|
294
|
-
},
|
|
295
|
-
begin() {
|
|
296
|
-
const tx = kv.begin();
|
|
297
|
-
const putKeyValues = [];
|
|
298
|
-
const patchKeyValues = [];
|
|
299
|
-
const deleteKeys = [];
|
|
300
|
-
return {
|
|
301
|
-
put(key, value) {
|
|
302
|
-
for (const fn of listeners.beforePut) fn(key, value);
|
|
303
|
-
tx.put(key, encodeValue(key, value));
|
|
304
|
-
putKeyValues.push([key, value]);
|
|
305
|
-
},
|
|
306
|
-
patch(key, value) {
|
|
307
|
-
for (const fn of listeners.beforePatch) fn(key, value);
|
|
308
|
-
tx.patch(key, encode(key, value, clock.now()));
|
|
309
|
-
const merged = decodeActive(tx.get(key));
|
|
310
|
-
if (merged) patchKeyValues.push([key, merged]);
|
|
311
|
-
},
|
|
312
|
-
merge(doc) {
|
|
313
|
-
if (tx.has(doc["~id"])) tx.patch(doc["~id"], doc);
|
|
314
|
-
else tx.put(doc["~id"], doc);
|
|
315
|
-
const currentDoc = tx.get(doc["~id"]);
|
|
316
|
-
if (currentDoc && !currentDoc["~deletedAt"]) {
|
|
317
|
-
const merged = decode(currentDoc)["~data"];
|
|
318
|
-
patchKeyValues.push([doc["~id"], merged]);
|
|
319
|
-
}
|
|
320
|
-
},
|
|
321
|
-
del(key) {
|
|
322
|
-
for (const fn of listeners.beforeDel) fn(key);
|
|
323
|
-
if (!tx.get(key)) return;
|
|
324
|
-
tx.del(key, clock.now());
|
|
325
|
-
deleteKeys.push(key);
|
|
326
|
-
},
|
|
327
|
-
has(key) {
|
|
328
|
-
return tx.has(key);
|
|
329
|
-
},
|
|
330
|
-
commit(opts = { silent: false }) {
|
|
331
|
-
tx.commit();
|
|
332
|
-
if (opts.silent) return;
|
|
333
|
-
if (putKeyValues.length > 0) for (const fn of listeners.put) fn(Object.freeze([...putKeyValues]));
|
|
334
|
-
if (patchKeyValues.length > 0) for (const fn of listeners.patch) fn(Object.freeze([...patchKeyValues]));
|
|
335
|
-
if (deleteKeys.length > 0) for (const fn of listeners.del) fn(Object.freeze([...deleteKeys]));
|
|
336
|
-
},
|
|
337
|
-
rollback() {
|
|
338
|
-
tx.rollback();
|
|
339
|
-
}
|
|
340
|
-
};
|
|
341
|
-
},
|
|
342
|
-
use(plugin) {
|
|
343
|
-
const { hooks: pluginHooks, init, dispose, methods } = plugin(this);
|
|
344
|
-
if (pluginHooks) {
|
|
345
|
-
if (pluginHooks.onBeforePut) {
|
|
346
|
-
const callback = pluginHooks.onBeforePut;
|
|
347
|
-
listeners.beforePut.add(callback);
|
|
348
|
-
disposers.add(() => {
|
|
349
|
-
listeners.beforePut.delete(callback);
|
|
350
|
-
});
|
|
351
|
-
}
|
|
352
|
-
if (pluginHooks.onBeforePatch) {
|
|
353
|
-
const callback = pluginHooks.onBeforePatch;
|
|
354
|
-
listeners.beforePatch.add(callback);
|
|
355
|
-
disposers.add(() => {
|
|
356
|
-
listeners.beforePatch.delete(callback);
|
|
357
|
-
});
|
|
358
|
-
}
|
|
359
|
-
if (pluginHooks.onBeforeDelete) {
|
|
360
|
-
const callback = pluginHooks.onBeforeDelete;
|
|
361
|
-
listeners.beforeDel.add(callback);
|
|
362
|
-
disposers.add(() => {
|
|
363
|
-
listeners.beforeDel.delete(callback);
|
|
364
|
-
});
|
|
365
|
-
}
|
|
366
|
-
if (pluginHooks.onPut) {
|
|
367
|
-
const callback = pluginHooks.onPut;
|
|
368
|
-
listeners.put.add(callback);
|
|
369
|
-
disposers.add(() => {
|
|
370
|
-
listeners.put.delete(callback);
|
|
371
|
-
});
|
|
372
|
-
}
|
|
373
|
-
if (pluginHooks.onPatch) {
|
|
374
|
-
const callback = pluginHooks.onPatch;
|
|
375
|
-
listeners.patch.add(callback);
|
|
376
|
-
disposers.add(() => {
|
|
377
|
-
listeners.patch.delete(callback);
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
if (pluginHooks.onDelete) {
|
|
381
|
-
const callback = pluginHooks.onDelete;
|
|
382
|
-
listeners.del.add(callback);
|
|
383
|
-
disposers.add(() => {
|
|
384
|
-
listeners.del.delete(callback);
|
|
385
|
-
});
|
|
386
|
-
}
|
|
387
|
-
}
|
|
388
|
-
if (methods) Object.assign(this, methods);
|
|
389
|
-
initializers.add(init);
|
|
390
|
-
disposers.add(dispose);
|
|
391
|
-
return this;
|
|
392
|
-
},
|
|
393
|
-
async init() {
|
|
394
|
-
for (const fn of initializers) await fn();
|
|
395
|
-
return this;
|
|
396
|
-
},
|
|
397
|
-
async dispose() {
|
|
398
|
-
for (const fn of Array.from(disposers).toReversed()) await fn();
|
|
399
|
-
}
|
|
400
|
-
};
|
|
401
|
-
};
|
|
402
|
-
|
|
403
|
-
//#endregion
|
|
404
|
-
export { clock_exports as Clock, document_exports as Document, eventstamp_exports as Eventstamp, kv_exports as KV, record_exports as Record, store_exports as Store, value_exports as Value };
|
|
1
|
+
const e=(e,t)=>`${new Date(e).toISOString()}|${t.toString(16).padStart(8,`0`)}`,t=e=>{let t=e.indexOf(`|`),n=e.slice(0,t),r=e.slice(t+1);return{timestampMs:new Date(n).getTime(),counter:parseInt(r,16)}},n=()=>{let n=0,r=Date.now();return{now:()=>{let t=Date.now();return t<=r?n++:(r=t,n=0),e(t,n)},latest(){return e(r,n)},forward(e){if(e>this.latest()){let i=t(e);r=i.timestampMs,n=i.counter}}}},r=e=>!!(typeof e==`object`&&e&&!Array.isArray(e)&&Object.getPrototypeOf(e)===Object.prototype),i=(e,t)=>({"~value":e,"~eventstamp":t}),a=e=>e[`~value`],o=(e,t)=>e[`~eventstamp`]>t[`~eventstamp`]?e:t,s=e=>!!(typeof e==`object`&&e&&`~value`in e&&`~eventstamp`in e),c=(e,t)=>{let n={},a=(e,n)=>{for(let o in e){if(!Object.hasOwn(e,o))continue;let s=e[o];r(s)?(n[o]={},a(s,n[o])):n[o]=i(s,t)}};return a(e,n),n},l=e=>{let t={},n=(e,t)=>{for(let i in e){if(!Object.hasOwn(e,i))continue;let o=e[i];s(o)?t[i]=a(o):r(o)&&(t[i]={},n(o,t[i]))}};return n(e,t),t},u=(e,t)=>{let n={},i=(e,t,n)=>{for(let a in e){if(!Object.hasOwn(e,a))continue;let c=e[a],l=t[a];s(c)&&s(l)?n[a]=o(c,l):s(c)?n[a]=c:r(c)&&r(l)?(n[a]={},i(c,l,n[a])):c&&(n[a]=c)}for(let e in t){if(!Object.hasOwn(t,e)||Object.hasOwn(n,e))continue;let r=t[e];r!==void 0&&(n[e]=r)}};return i(e,t,n),n},d=(e,t,n,a=null)=>({"~id":e,"~data":r(t)?c(t,n):i(t,n),"~deletedAt":a}),f=e=>({"~id":e[`~id`],"~data":s(e[`~data`])?a(e[`~data`]):l(e[`~data`]),"~deletedAt":e[`~deletedAt`]}),p=(e,t)=>{let n=s(e[`~data`]),r=s(t[`~data`]);if(n!==r)throw Error(`Merge error: Incompatible types`);let i=n&&r?o(e[`~data`],t[`~data`]):u(e[`~data`],t[`~data`]),a=e[`~deletedAt`]&&t[`~deletedAt`]?e[`~deletedAt`]>t[`~deletedAt`]?e[`~deletedAt`]:t[`~deletedAt`]:e[`~deletedAt`]||t[`~deletedAt`]||null;return{"~id":e[`~id`],"~data":i,"~deletedAt":a}},m=(e,t)=>({"~id":e[`~id`],"~data":e[`~data`],"~deletedAt":t}),h=e=>{let t=new Map(e);return{get(e){return t.get(e)??null},values(){return t.values()},entries(){return t.entries()},get size(){return t.size},begin(e){let n=new Map(t),r=!1;e({get(e){return n.get(e)??null},set(e,t,r){if(r?.replace)n.set(e,t);else{let r=n.get(e);n.set(e,r?p(r,t):t)}},del(e,t){let r=n.get(e);r&&n.set(e,m(r,t))},rollback(){r=!0}}),r||(t=n)}}},g=(e,t,n,r,i,a,o,s)=>{let c={rolledBack:!1},l={rolledBack:!1,add(t,i){let o=i?.withId??n();return e.set(o,r(o,t),{replace:!0}),a.push([o,t]),o},update(n,r){e.set(n,d(n,r,t.now()));let a=i(e.get(n));a&&o.push([n,a])},merge(t){e.get(t[`~id`])?e.set(t[`~id`],t):e.set(t[`~id`],t,{replace:!0});let n=e.get(t[`~id`]);if(n&&!n[`~deletedAt`]){let e=f(n)[`~data`];o.push([t[`~id`],e])}},del(n){e.get(n)&&(e.del(n,t.now()),s.push(n))},get(t){return i(e.get(t))},rollback(){c.rolledBack=!0,l.rolledBack=!0,e.rollback()}};return l},_=(e={})=>{let t=h(),r=n(),i=e.getId??(()=>crypto.randomUUID()),a=(e,t)=>d(e,t,r.now()),o=e=>!e||e[`~deletedAt`]?null:f(e)[`~data`],s=new Set,c=new Set,l=new Set,u=new Set,p=new Set;return{get(e){return o(t.get(e))},entries(){function*e(){for(let[e,n]of t.entries()){let t=o(n);t!==null&&(yield[e,t])}}return e()},snapshot(){return Array.from(t.values())},begin(e,n){let s=n?.silent??!1,c=[],d=[],f=[],m,h=!1;return t.begin(t=>{let n=g(t,r,i,a,o,c,d,f);m=e(n),!n.rolledBack&&!s&&(h=!0)}),h&&(c.length>0&&l.forEach(e=>{e(c)}),d.length>0&&u.forEach(e=>{e(d)}),f.length>0&&p.forEach(e=>{e(f)})),m},add(e,t){return this.begin(n=>n.add(e,t))},update(e,t){return this.begin(n=>n.update(e,t))},del(e){return this.begin(t=>t.del(e))},use(e){let{hooks:t,methods:n}=e;if(t.onAdd||t.onUpdate||t.onDelete){if(t.onAdd){let e=t.onAdd;l.add(e),c.add(()=>{l.delete(e)})}if(t.onUpdate){let e=t.onUpdate;u.add(e),c.add(()=>{u.delete(e)})}if(t.onDelete){let e=t.onDelete;p.add(e),c.add(()=>{p.delete(e)})}}return n&&Object.assign(this,n),s.add(t.onInit),c.add(t.onDispose),this},async init(){for(let e of s)await e(this);return this},async dispose(){let e=Array.from(c);e.reverse();for(let t of e)await t()}}};export{_ as createStore};
|
package/package.json
CHANGED
package/dist/chunk-Bp6m_JJh.js
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
//#region rolldown:runtime
|
|
2
|
-
var __defProp = Object.defineProperty;
|
|
3
|
-
var __export = (all) => {
|
|
4
|
-
let target = {};
|
|
5
|
-
for (var name in all) __defProp(target, name, {
|
|
6
|
-
get: all[name],
|
|
7
|
-
enumerable: true
|
|
8
|
-
});
|
|
9
|
-
return target;
|
|
10
|
-
};
|
|
11
|
-
|
|
12
|
-
//#endregion
|
|
13
|
-
export { __export as t };
|