@byearlybird/starling 0.2.2 → 0.4.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 CHANGED
@@ -14,19 +14,20 @@ declare namespace value_d_exports {
14
14
  export { EncodedValue, decode$3 as decode, encode$3 as encode, isEncoded, merge$2 as merge };
15
15
  }
16
16
  type EncodedValue<T$1> = {
17
- __value: T$1;
18
- __eventstamp: string;
17
+ "~value": T$1;
18
+ "~eventstamp": string;
19
19
  };
20
20
  declare const encode$3: <T>(value: T, eventstamp: string) => EncodedValue<T>;
21
21
  declare const decode$3: <T>(value: EncodedValue<T>) => T;
22
22
  declare const merge$2: <T>(into: EncodedValue<T>, from: EncodedValue<T>) => EncodedValue<T>;
23
23
  declare const isEncoded: (value: unknown) => boolean;
24
24
  declare namespace record_d_exports {
25
- export { EncodedRecord, decode$2 as decode, encode$2 as encode, merge$1 as merge };
25
+ export { EncodedRecord, decode$2 as decode, encode$2 as encode, isObject, merge$1 as merge };
26
26
  }
27
27
  type EncodedRecord = {
28
28
  [key: string]: EncodedValue<unknown> | EncodedRecord;
29
29
  };
30
+ declare const isObject: (value: unknown) => boolean;
30
31
  declare const encode$2: <T extends Record<string, unknown>>(obj: T, eventstamp: string) => EncodedRecord;
31
32
  declare const decode$2: <T extends Record<string, unknown>>(obj: EncodedRecord) => T;
32
33
  declare const merge$1: (into: EncodedRecord, from: EncodedRecord) => EncodedRecord;
@@ -35,11 +36,11 @@ declare namespace document_d_exports {
35
36
  }
36
37
  type EncodedDocument = {
37
38
  "~id": string;
38
- "~data": EncodedRecord;
39
+ "~data": EncodedValue<unknown> | EncodedRecord;
39
40
  "~deletedAt": string | null;
40
41
  };
41
- declare const encode$1: <T extends record_d_exports<string, unknown>>(id: string, obj: T, eventstamp: string, deletedAt?: string | null) => EncodedDocument;
42
- declare const decode$1: <T extends record_d_exports<string, unknown>>(doc: EncodedDocument) => {
42
+ declare const encode$1: <T>(id: string, obj: T, eventstamp: string, deletedAt?: string | null) => EncodedDocument;
43
+ declare const decode$1: <T>(doc: EncodedDocument) => {
43
44
  "~id": string;
44
45
  "~data": T;
45
46
  "~deletedAt": string | null;
@@ -74,19 +75,19 @@ declare const create$1: (iterable?: Iterable<readonly [string, EncodedDocument]>
74
75
  };
75
76
  };
76
77
  declare namespace store_d_exports {
77
- export { Plugin, PluginHandle, Store as StarlingStore, StoreHooks, StoreOnBeforeDelete, StoreOnBeforePatch, StoreOnBeforePut, StoreOnDelete, StoreOnPatch, StoreOnPut, StoreTransaction, create };
78
+ export { Plugin, PluginHandle, PluginMethods, Store as StarlingStore, StoreHooks, StoreOnBeforeDelete, StoreOnBeforePatch, StoreOnBeforePut, StoreOnDelete, StoreOnPatch, StoreOnPut, StoreTransaction, create };
78
79
  }
79
80
  type DeepPartial<T$1> = T$1 extends object ? { [P in keyof T$1]?: DeepPartial<T$1[P]> } : T$1;
80
81
  /**
81
82
  * Called once per commit with all put operations accumulated as decoded entries.
82
83
  * Only fires if at least one put occurred.
83
84
  */
84
- type StoreOnPut<T$1 extends Record<string, unknown>> = (entries: ReadonlyArray<readonly [string, T$1]>) => void;
85
+ type StoreOnPut<T$1> = (entries: ReadonlyArray<readonly [string, T$1]>) => void;
85
86
  /**
86
87
  * Called once per commit with all patch operations accumulated as decoded entries.
87
88
  * Only fires if at least one patch occurred.
88
89
  */
89
- type StoreOnPatch<T$1 extends Record<string, unknown>> = (entries: ReadonlyArray<readonly [string, T$1]>) => void;
90
+ type StoreOnPatch<T$1> = (entries: ReadonlyArray<readonly [string, T$1]>) => void;
90
91
  /**
91
92
  * Called once per commit with all deleted keys (IDs).
92
93
  * Only fires if at least one delete occurred.
@@ -96,12 +97,12 @@ type StoreOnDelete = (keys: ReadonlyArray<string>) => void;
96
97
  * Called before a put operation is applied.
97
98
  * Throws to reject the operation.
98
99
  */
99
- type StoreOnBeforePut<T$1 extends Record<string, unknown>> = (key: string, value: T$1) => void;
100
+ type StoreOnBeforePut<T$1> = (key: string, value: T$1) => void;
100
101
  /**
101
102
  * Called before a patch operation is applied.
102
103
  * Throws to reject the operation.
103
104
  */
104
- type StoreOnBeforePatch<T$1 extends Record<string, unknown>> = (key: string, value: DeepPartial<T$1>) => void;
105
+ type StoreOnBeforePatch<T$1> = (key: string, value: DeepPartial<T$1>) => void;
105
106
  /**
106
107
  * Called before a delete operation is applied.
107
108
  * Throws to reject the operation.
@@ -112,7 +113,7 @@ type StoreOnBeforeDelete = (key: string) => void;
112
113
  * Hooks fire on commit only, never during staged operations.
113
114
  * Arrays are readonly to prevent external mutation.
114
115
  */
115
- type StoreHooks<T$1 extends Record<string, unknown>> = {
116
+ type StoreHooks<T$1> = {
116
117
  onBeforePut?: StoreOnBeforePut<T$1>;
117
118
  onBeforePatch?: StoreOnBeforePatch<T$1>;
118
119
  onBeforeDelete?: StoreOnBeforeDelete;
@@ -120,7 +121,7 @@ type StoreHooks<T$1 extends Record<string, unknown>> = {
120
121
  onPatch?: StoreOnPatch<T$1>;
121
122
  onDelete?: StoreOnDelete;
122
123
  };
123
- type StoreTransaction<T$1 extends Record<string, unknown>> = {
124
+ type StoreTransaction<T$1> = {
124
125
  put: (key: string, value: T$1) => void;
125
126
  patch: (key: string, value: DeepPartial<T$1>) => void;
126
127
  merge: (doc: EncodedDocument) => void;
@@ -131,13 +132,15 @@ type StoreTransaction<T$1 extends Record<string, unknown>> = {
131
132
  }) => void;
132
133
  rollback: () => void;
133
134
  };
134
- type PluginHandle<T$1 extends Record<string, unknown>> = {
135
+ type PluginMethods = Record<string, (...args: any[]) => any>;
136
+ type PluginHandle<T$1, M$1 extends PluginMethods = {}> = {
135
137
  init: () => Promise<void> | void;
136
138
  dispose: () => Promise<void> | void;
137
139
  hooks?: StoreHooks<T$1>;
140
+ methods?: M$1;
138
141
  };
139
- type Plugin<T$1 extends Record<string, unknown>> = (store: Store<T$1>) => PluginHandle<T$1>;
140
- type Store<T$1 extends Record<string, unknown>> = {
142
+ type Plugin<T$1, M$1 extends PluginMethods = {}> = (store: Store<T$1, any>) => PluginHandle<T$1, M$1>;
143
+ type Store<T$1, Extended = {}> = {
141
144
  get: (key: string) => T$1 | null;
142
145
  has: (key: string) => boolean;
143
146
  readonly size: number;
@@ -148,10 +151,10 @@ type Store<T$1 extends Record<string, unknown>> = {
148
151
  patch: (key: string, value: DeepPartial<T$1>) => void;
149
152
  del: (key: string) => void;
150
153
  begin: () => StoreTransaction<T$1>;
151
- use: (plugin: Plugin<T$1>) => Store<T$1>;
152
- init: () => Promise<Store<T$1>>;
154
+ use: <M extends PluginMethods>(plugin: Plugin<T$1, M>) => Store<T$1, Extended & M>;
155
+ init: () => Promise<Store<T$1, Extended>>;
153
156
  dispose: () => Promise<void>;
154
- };
155
- declare const create: <T extends Record<string, unknown>>() => Store<T>;
157
+ } & Extended;
158
+ declare const create: <T>() => Store<T, {}>;
156
159
  //#endregion
157
160
  export { type clock_d_exports as Clock, document_d_exports as Document, eventstamp_d_exports as Eventstamp, kv_d_exports as KV, record_d_exports as Record, store_d_exports as Store, value_d_exports as Value };
package/dist/index.js CHANGED
@@ -20,8 +20,8 @@ const decode$3 = (eventstamp) => {
20
20
 
21
21
  //#endregion
22
22
  //#region src/clock.ts
23
- var clock_exports = /* @__PURE__ */ __export({ create: () => create });
24
- const create = () => {
23
+ var clock_exports = /* @__PURE__ */ __export({ create: () => create$2 });
24
+ const create$2 = () => {
25
25
  let counter = 0;
26
26
  let lastMs = Date.now();
27
27
  return {
@@ -56,21 +56,22 @@ var value_exports = /* @__PURE__ */ __export({
56
56
  merge: () => merge$2
57
57
  });
58
58
  const encode$2 = (value, eventstamp) => ({
59
- __value: value,
60
- __eventstamp: eventstamp
59
+ "~value": value,
60
+ "~eventstamp": eventstamp
61
61
  });
62
- const decode$2 = (value) => value.__value;
62
+ const decode$2 = (value) => value["~value"];
63
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
64
+ "~value": into["~eventstamp"] > from["~eventstamp"] ? into["~value"] : from["~value"],
65
+ "~eventstamp": into["~eventstamp"] > from["~eventstamp"] ? into["~eventstamp"] : from["~eventstamp"]
66
66
  });
67
- const isEncoded = (value) => !!(typeof value === "object" && value !== null && "__value" in value && "__eventstamp" in value);
67
+ const isEncoded = (value) => !!(typeof value === "object" && value !== null && "~value" in value && "~eventstamp" in value);
68
68
 
69
69
  //#endregion
70
70
  //#region src/record.ts
71
71
  var record_exports = /* @__PURE__ */ __export({
72
72
  decode: () => decode$1,
73
73
  encode: () => encode$1,
74
+ isObject: () => isObject,
74
75
  merge: () => merge$1
75
76
  });
76
77
  const isObject = (value) => !!(value != null && typeof value === "object" && !Array.isArray(value) && Object.getPrototypeOf(value) === Object.prototype);
@@ -139,19 +140,26 @@ var document_exports = /* @__PURE__ */ __export({
139
140
  });
140
141
  const encode = (id, obj, eventstamp, deletedAt = null) => ({
141
142
  "~id": id,
142
- "~data": encode$1(obj, eventstamp),
143
+ "~data": isObject(obj) ? encode$1(obj, eventstamp) : encode$2(obj, eventstamp),
143
144
  "~deletedAt": deletedAt
144
145
  });
145
146
  const decode = (doc) => ({
146
147
  "~id": doc["~id"],
147
- "~data": decode$1(doc["~data"]),
148
+ "~data": isEncoded(doc["~data"]) ? decode$2(doc["~data"]) : decode$1(doc["~data"]),
148
149
  "~deletedAt": doc["~deletedAt"]
149
150
  });
150
- const merge = (into, from) => ({
151
- "~id": into["~id"],
152
- "~data": merge$1(into["~data"], from["~data"]),
153
- "~deletedAt": into["~deletedAt"] && from["~deletedAt"] ? into["~deletedAt"] > from["~deletedAt"] ? into["~deletedAt"] : from["~deletedAt"] : into["~deletedAt"] || from["~deletedAt"] || null
154
- });
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
+ };
155
163
  const del = (doc, eventstamp) => ({
156
164
  ...doc,
157
165
  "~deletedAt": eventstamp
@@ -159,8 +167,8 @@ const del = (doc, eventstamp) => ({
159
167
 
160
168
  //#endregion
161
169
  //#region src/kv.ts
162
- var kv_exports = /* @__PURE__ */ __export({ create: () => create$2 });
163
- const create$2 = (iterable) => {
170
+ var kv_exports = /* @__PURE__ */ __export({ create: () => create$1 });
171
+ const create$1 = (iterable) => {
164
172
  let readMap = new Map(iterable);
165
173
  function cloneMap(src) {
166
174
  return new Map(src);
@@ -217,11 +225,11 @@ const create$2 = (iterable) => {
217
225
 
218
226
  //#endregion
219
227
  //#region src/store.ts
220
- var store_exports = /* @__PURE__ */ __export({ create: () => create$1 });
221
- const create$1 = () => {
222
- const clock = create();
228
+ var store_exports = /* @__PURE__ */ __export({ create: () => create });
229
+ const create = () => {
230
+ const kv = create$1();
231
+ const clock = create$2();
223
232
  const encodeValue = (key, value) => encode(key, value, clock.now());
224
- const kv = create$2();
225
233
  const listeners = {
226
234
  beforePut: /* @__PURE__ */ new Set(),
227
235
  beforePatch: /* @__PURE__ */ new Set(),
@@ -247,7 +255,7 @@ const create$1 = () => {
247
255
  function* iterator() {
248
256
  for (const doc of kv.values()) {
249
257
  const data = decodeActive(doc);
250
- if (data) yield data;
258
+ if (data !== null) yield data;
251
259
  }
252
260
  }
253
261
  return iterator();
@@ -256,7 +264,7 @@ const create$1 = () => {
256
264
  function* iterator() {
257
265
  for (const [key, doc] of kv.entries()) {
258
266
  const data = decodeActive(doc);
259
- if (data) yield [key, data];
267
+ if (data !== null) yield [key, data];
260
268
  }
261
269
  }
262
270
  return iterator();
@@ -332,7 +340,7 @@ const create$1 = () => {
332
340
  };
333
341
  },
334
342
  use(plugin) {
335
- const { hooks: pluginHooks, init, dispose } = plugin(this);
343
+ const { hooks: pluginHooks, init, dispose, methods } = plugin(this);
336
344
  if (pluginHooks) {
337
345
  if (pluginHooks.onBeforePut) {
338
346
  const callback = pluginHooks.onBeforePut;
@@ -377,6 +385,7 @@ const create$1 = () => {
377
385
  });
378
386
  }
379
387
  }
388
+ if (methods) Object.assign(this, methods);
380
389
  initializers.add(init);
381
390
  disposers.add(dispose);
382
391
  return this;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@byearlybird/starling",
3
- "version": "0.2.2",
3
+ "version": "0.4.0",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "main": "./dist/index.js",