tinybase 4.2.0-beta.0 → 4.2.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.
Files changed (97) hide show
  1. package/lib/cjs/persisters/persister-indexed-db.cjs +1 -0
  2. package/lib/cjs/persisters/persister-indexed-db.cjs.gz +0 -0
  3. package/lib/cjs/persisters/persister-remote.cjs +1 -1
  4. package/lib/cjs/persisters/persister-remote.cjs.gz +0 -0
  5. package/lib/cjs/persisters/persister-yjs.cjs +1 -1
  6. package/lib/cjs/persisters/persister-yjs.cjs.gz +0 -0
  7. package/lib/cjs/tools.cjs +1 -1
  8. package/lib/cjs/tools.cjs.gz +0 -0
  9. package/lib/cjs/ui-react-dom-debug.cjs +1 -1
  10. package/lib/cjs/ui-react-dom-debug.cjs.gz +0 -0
  11. package/lib/cjs/ui-react-dom.cjs +1 -1
  12. package/lib/cjs/ui-react-dom.cjs.gz +0 -0
  13. package/lib/cjs/ui-react.cjs +1 -1
  14. package/lib/cjs/ui-react.cjs.gz +0 -0
  15. package/lib/cjs-es6/persisters/persister-indexed-db.cjs +1 -0
  16. package/lib/cjs-es6/persisters/persister-indexed-db.cjs.gz +0 -0
  17. package/lib/cjs-es6/persisters/persister-remote.cjs +1 -1
  18. package/lib/cjs-es6/persisters/persister-remote.cjs.gz +0 -0
  19. package/lib/cjs-es6/persisters/persister-yjs.cjs +1 -1
  20. package/lib/cjs-es6/persisters/persister-yjs.cjs.gz +0 -0
  21. package/lib/cjs-es6/tools.cjs +1 -1
  22. package/lib/cjs-es6/tools.cjs.gz +0 -0
  23. package/lib/cjs-es6/ui-react-dom-debug.cjs +1 -1
  24. package/lib/cjs-es6/ui-react-dom-debug.cjs.gz +0 -0
  25. package/lib/cjs-es6/ui-react-dom.cjs +1 -1
  26. package/lib/cjs-es6/ui-react-dom.cjs.gz +0 -0
  27. package/lib/cjs-es6/ui-react.cjs +1 -1
  28. package/lib/cjs-es6/ui-react.cjs.gz +0 -0
  29. package/lib/debug/persisters/persister-browser.js +13 -8
  30. package/lib/debug/persisters/persister-indexed-db.js +272 -0
  31. package/lib/debug/persisters/persister-remote.js +1 -1
  32. package/lib/debug/persisters/persister-yjs.js +10 -16
  33. package/lib/debug/tools.js +21 -5
  34. package/lib/debug/ui-react-dom.js +187 -126
  35. package/lib/debug/ui-react.js +4 -3
  36. package/lib/es6/persisters/persister-indexed-db.js +1 -0
  37. package/lib/es6/persisters/persister-indexed-db.js.gz +0 -0
  38. package/lib/es6/persisters/persister-remote.js +1 -1
  39. package/lib/es6/persisters/persister-remote.js.gz +0 -0
  40. package/lib/es6/persisters/persister-yjs.js +1 -1
  41. package/lib/es6/persisters/persister-yjs.js.gz +0 -0
  42. package/lib/es6/tools.js +1 -1
  43. package/lib/es6/tools.js.gz +0 -0
  44. package/lib/es6/ui-react-dom-debug.js +1 -1
  45. package/lib/es6/ui-react-dom-debug.js.gz +0 -0
  46. package/lib/es6/ui-react-dom.js +1 -1
  47. package/lib/es6/ui-react-dom.js.gz +0 -0
  48. package/lib/es6/ui-react.js +1 -1
  49. package/lib/es6/ui-react.js.gz +0 -0
  50. package/lib/persisters/persister-indexed-db.js +1 -0
  51. package/lib/persisters/persister-indexed-db.js.gz +0 -0
  52. package/lib/persisters/persister-remote.js +1 -1
  53. package/lib/persisters/persister-remote.js.gz +0 -0
  54. package/lib/persisters/persister-yjs.js +1 -1
  55. package/lib/persisters/persister-yjs.js.gz +0 -0
  56. package/lib/tools.js +1 -1
  57. package/lib/tools.js.gz +0 -0
  58. package/lib/types/persisters/persister-indexed-db.d.ts +75 -0
  59. package/lib/types/persisters/persister-remote.d.ts +2 -2
  60. package/lib/types/persisters.d.ts +1 -0
  61. package/lib/types/with-schemas/persisters/persister-indexed-db.d.ts +86 -0
  62. package/lib/types/with-schemas/persisters/persister-remote.d.ts +3 -3
  63. package/lib/types/with-schemas/persisters.d.ts +1 -0
  64. package/lib/ui-react-dom.js +1 -1
  65. package/lib/ui-react-dom.js.gz +0 -0
  66. package/lib/ui-react.js +1 -1
  67. package/lib/ui-react.js.gz +0 -0
  68. package/lib/umd/persisters/persister-indexed-db.js +1 -0
  69. package/lib/umd/persisters/persister-indexed-db.js.gz +0 -0
  70. package/lib/umd/persisters/persister-remote.js +1 -1
  71. package/lib/umd/persisters/persister-remote.js.gz +0 -0
  72. package/lib/umd/persisters/persister-yjs.js +1 -1
  73. package/lib/umd/persisters/persister-yjs.js.gz +0 -0
  74. package/lib/umd/tools.js +1 -1
  75. package/lib/umd/tools.js.gz +0 -0
  76. package/lib/umd/ui-react-dom-debug.js +1 -1
  77. package/lib/umd/ui-react-dom-debug.js.gz +0 -0
  78. package/lib/umd/ui-react-dom.js +1 -1
  79. package/lib/umd/ui-react-dom.js.gz +0 -0
  80. package/lib/umd/ui-react.js +1 -1
  81. package/lib/umd/ui-react.js.gz +0 -0
  82. package/lib/umd-es6/persisters/persister-indexed-db.js +1 -0
  83. package/lib/umd-es6/persisters/persister-indexed-db.js.gz +0 -0
  84. package/lib/umd-es6/persisters/persister-remote.js +1 -1
  85. package/lib/umd-es6/persisters/persister-remote.js.gz +0 -0
  86. package/lib/umd-es6/persisters/persister-yjs.js +1 -1
  87. package/lib/umd-es6/persisters/persister-yjs.js.gz +0 -0
  88. package/lib/umd-es6/tools.js +1 -1
  89. package/lib/umd-es6/tools.js.gz +0 -0
  90. package/lib/umd-es6/ui-react-dom-debug.js +1 -1
  91. package/lib/umd-es6/ui-react-dom-debug.js.gz +0 -0
  92. package/lib/umd-es6/ui-react-dom.js +1 -1
  93. package/lib/umd-es6/ui-react-dom.js.gz +0 -0
  94. package/lib/umd-es6/ui-react.js +1 -1
  95. package/lib/umd-es6/ui-react.js.gz +0 -0
  96. package/package.json +29 -27
  97. package/readme.md +13 -13
@@ -0,0 +1,272 @@
1
+ const T = 't';
2
+ const V = 'v';
3
+
4
+ const arrayMap = (array, cb) => array.map(cb);
5
+ const arrayLength = (array) => array.length;
6
+ const arrayPush = (array, ...values) => array.push(...values);
7
+ const arrayShift = (array) => array.shift();
8
+
9
+ const promise = Promise;
10
+ const startInterval = setInterval;
11
+ const stopInterval = clearInterval;
12
+ const isInstanceOf = (thing, cls) => thing instanceof cls;
13
+ const isUndefined = (thing) => thing == void 0;
14
+ const ifNotUndefined = (value, then, otherwise) =>
15
+ isUndefined(value) ? otherwise?.() : then(value);
16
+ const promiseNew = (resolver) => new promise(resolver);
17
+ const promiseAll = async (promises) => promise.all(promises);
18
+
19
+ const object = Object;
20
+ const objIds = object.keys;
21
+ const objFreeze = object.freeze;
22
+ const isObject = (obj) =>
23
+ isInstanceOf(obj, object) && obj.constructor == object;
24
+ const objNew = (entries = []) => object.fromEntries(entries);
25
+ const objGet = (obj, id) => ifNotUndefined(obj, (obj2) => obj2[id]);
26
+ const objHas = (obj, id) => !isUndefined(objGet(obj, id));
27
+ const objMap = (obj, cb) =>
28
+ arrayMap(object.entries(obj), ([id, value]) => cb(value, id));
29
+ const objSize = (obj) => arrayLength(objIds(obj));
30
+ const objIsEmpty = (obj) => isObject(obj) && objSize(obj) == 0;
31
+
32
+ const collHas = (coll, keyOrValue) => coll?.has(keyOrValue) ?? false;
33
+ const collDel = (coll, keyOrValue) => coll?.delete(keyOrValue);
34
+
35
+ const mapNew = (entries) => new Map(entries);
36
+ const mapGet = (map, key) => map?.get(key);
37
+ const mapSet = (map, key, value) =>
38
+ isUndefined(value) ? (collDel(map, key), map) : map?.set(key, value);
39
+ const mapEnsure = (map, key, getDefaultValue) => {
40
+ if (!collHas(map, key)) {
41
+ mapSet(map, key, getDefaultValue());
42
+ }
43
+ return mapGet(map, key);
44
+ };
45
+
46
+ const scheduleRunning = mapNew();
47
+ const scheduleActions = mapNew();
48
+ const createCustomPersister = (
49
+ store,
50
+ getPersisted,
51
+ setPersisted,
52
+ addPersisterListener,
53
+ delPersisterListener,
54
+ onIgnoredError,
55
+ scheduleId = [],
56
+ ) => {
57
+ let listenerId;
58
+ let loadSave = 0;
59
+ let loads = 0;
60
+ let saves = 0;
61
+ let listening = 0;
62
+ let action;
63
+ let listeningHandle;
64
+ mapEnsure(scheduleRunning, scheduleId, () => 0);
65
+ mapEnsure(scheduleActions, scheduleId, () => []);
66
+ const run = async () => {
67
+ /* istanbul ignore else */
68
+ if (!mapGet(scheduleRunning, scheduleId)) {
69
+ mapSet(scheduleRunning, scheduleId, 1);
70
+ while (
71
+ !isUndefined((action = arrayShift(mapGet(scheduleActions, scheduleId))))
72
+ ) {
73
+ try {
74
+ await action();
75
+ } catch (error) {
76
+ /* istanbul ignore next */
77
+ onIgnoredError?.(error);
78
+ }
79
+ }
80
+ mapSet(scheduleRunning, scheduleId, 0);
81
+ }
82
+ };
83
+ const loadLock = async (actions) => {
84
+ /* istanbul ignore else */
85
+ if (loadSave != 2) {
86
+ loadSave = 1;
87
+ {
88
+ loads++;
89
+ }
90
+ await persister.schedule(async () => {
91
+ await actions();
92
+ loadSave = 0;
93
+ });
94
+ }
95
+ return persister;
96
+ };
97
+ const persister = {
98
+ load: async (initialTables, initialValues) =>
99
+ await loadLock(async () => {
100
+ try {
101
+ store.setContent(await getPersisted());
102
+ } catch {
103
+ store.setContent([initialTables, initialValues]);
104
+ }
105
+ }),
106
+ startAutoLoad: async (initialTables = {}, initialValues = {}) => {
107
+ persister.stopAutoLoad();
108
+ await persister.load(initialTables, initialValues);
109
+ listening = 1;
110
+ listeningHandle = addPersisterListener(
111
+ async (getContent, getTransactionChanges) => {
112
+ if (getTransactionChanges) {
113
+ const transactionChanges = getTransactionChanges();
114
+ await loadLock(async () =>
115
+ store.setTransactionChanges(transactionChanges),
116
+ );
117
+ } else {
118
+ await loadLock(async () => {
119
+ try {
120
+ store.setContent(getContent?.() ?? (await getPersisted()));
121
+ } catch (error) {
122
+ onIgnoredError?.(error);
123
+ }
124
+ });
125
+ }
126
+ },
127
+ );
128
+ return persister;
129
+ },
130
+ stopAutoLoad: () => {
131
+ if (listening) {
132
+ delPersisterListener(listeningHandle);
133
+ listeningHandle = void 0;
134
+ listening = 0;
135
+ }
136
+ return persister;
137
+ },
138
+ save: async (getTransactionChanges) => {
139
+ /* istanbul ignore else */
140
+ if (loadSave != 1) {
141
+ loadSave = 2;
142
+ {
143
+ saves++;
144
+ }
145
+ await persister.schedule(async () => {
146
+ try {
147
+ await setPersisted(store.getContent, getTransactionChanges);
148
+ } catch (error) {
149
+ /* istanbul ignore next */
150
+ onIgnoredError?.(error);
151
+ }
152
+ loadSave = 0;
153
+ });
154
+ }
155
+ return persister;
156
+ },
157
+ startAutoSave: async () => {
158
+ await persister.stopAutoSave().save();
159
+ listenerId = store.addDidFinishTransactionListener(
160
+ (_store, getTransactionChanges) => {
161
+ const [tableChanges, valueChanges] = getTransactionChanges();
162
+ if (!objIsEmpty(tableChanges) || !objIsEmpty(valueChanges)) {
163
+ persister.save(() => [tableChanges, valueChanges]);
164
+ }
165
+ },
166
+ );
167
+ return persister;
168
+ },
169
+ stopAutoSave: () => {
170
+ ifNotUndefined(listenerId, store.delListener);
171
+ return persister;
172
+ },
173
+ schedule: async (...actions) => {
174
+ arrayPush(mapGet(scheduleActions, scheduleId), ...actions);
175
+ await run();
176
+ return persister;
177
+ },
178
+ getStore: () => store,
179
+ destroy: () => persister.stopAutoLoad().stopAutoSave(),
180
+ getStats: () => ({loads, saves}),
181
+ };
182
+ return objFreeze(persister);
183
+ };
184
+
185
+ const WINDOW = globalThis.window;
186
+ const OBJECT_STORE_NAMES = [T, V];
187
+ const KEY_PATH = {keyPath: 'k'};
188
+ const objectStoreMatch = async (objectStore, obj) => {
189
+ const actions = objMap(obj, (v, k) =>
190
+ execObjectStore(objectStore, 'put', {k, v}),
191
+ );
192
+ arrayMap(await execObjectStore(objectStore, 'getAllKeys'), (id) =>
193
+ objHas(obj, id)
194
+ ? 0
195
+ : arrayPush(actions, execObjectStore(objectStore, 'delete', id)),
196
+ );
197
+ await promiseAll(actions);
198
+ };
199
+ const execObjectStore = async (objectStore, func, arg) =>
200
+ promiseNew((resolve, reject) => {
201
+ const request = objectStore[func](arg);
202
+ request.onsuccess = () => resolve(request.result);
203
+ request.onerror = () => reject(`objectStore.${func} error`);
204
+ });
205
+ const createIndexedDbPersister = (
206
+ store,
207
+ dbName,
208
+ autoLoadIntervalSeconds = 1,
209
+ onIgnoredError,
210
+ ) => {
211
+ const forObjectStores = async (forObjectStore, args = [], create = 0) =>
212
+ promiseNew((resolve, reject) => {
213
+ const request = WINDOW.indexedDB.open(dbName, 1);
214
+ request.onupgradeneeded = () =>
215
+ create &&
216
+ arrayMap(OBJECT_STORE_NAMES, (objectStoreName) =>
217
+ request.result.createObjectStore(objectStoreName, KEY_PATH),
218
+ );
219
+ request.onsuccess = async () => {
220
+ try {
221
+ const transaction = request.result.transaction(
222
+ OBJECT_STORE_NAMES,
223
+ 'readwrite',
224
+ );
225
+ const result = await promiseAll(
226
+ arrayMap(
227
+ OBJECT_STORE_NAMES,
228
+ async (objectStoreName, index) =>
229
+ await forObjectStore(
230
+ transaction.objectStore(objectStoreName),
231
+ args[index],
232
+ ),
233
+ ),
234
+ );
235
+ request.result.close();
236
+ resolve(result);
237
+ } catch (e) {
238
+ reject(e);
239
+ }
240
+ };
241
+ request.onerror = () => reject('indexedDB.open error');
242
+ });
243
+ const getPersisted = async () =>
244
+ await forObjectStores(async (objectStore) =>
245
+ objNew(
246
+ arrayMap(await execObjectStore(objectStore, 'getAll'), ({k, v}) => [
247
+ k,
248
+ v,
249
+ ]),
250
+ ),
251
+ );
252
+ const setPersisted = async (getContent) =>
253
+ await forObjectStores(
254
+ async (objectStore, content) =>
255
+ await objectStoreMatch(objectStore, content),
256
+ getContent(),
257
+ 1,
258
+ );
259
+ const addPersisterListener = (listener) =>
260
+ startInterval(listener, autoLoadIntervalSeconds * 1e3);
261
+ const delPersisterListener = (interval) => stopInterval(interval);
262
+ return createCustomPersister(
263
+ store,
264
+ getPersisted,
265
+ setPersisted,
266
+ addPersisterListener,
267
+ delPersisterListener,
268
+ onIgnoredError,
269
+ );
270
+ };
271
+
272
+ export {createIndexedDbPersister, objectStoreMatch};
@@ -181,7 +181,7 @@ const createRemotePersister = (
181
181
  store,
182
182
  loadUrl,
183
183
  saveUrl,
184
- autoLoadIntervalSeconds,
184
+ autoLoadIntervalSeconds = 5,
185
185
  onIgnoredError,
186
186
  ) => {
187
187
  let lastEtag;
@@ -1,6 +1,8 @@
1
1
  import {Map as Map$1} from 'yjs';
2
2
 
3
3
  const TINYBASE = 'tinybase';
4
+ const T = 't';
5
+ const V = 'v';
4
6
 
5
7
  const arrayForEach = (array, cb) => array.forEach(cb);
6
8
  const arrayMap = (array, cb) => array.map(cb);
@@ -189,28 +191,17 @@ const createCustomPersister = (
189
191
  return objFreeze(persister);
190
192
  };
191
193
 
192
- const tablesKey = 't';
193
- const valuesKey = 'v';
194
194
  const DELETE = 'delete';
195
- const ensureYContent = (yContent) => {
196
- if (!yContent.size) {
197
- yContent.set(tablesKey, new Map$1());
198
- yContent.set(valuesKey, new Map$1());
199
- }
200
- };
201
- const getYContent = (yContent) => [
202
- yContent.get(tablesKey),
203
- yContent.get(valuesKey),
204
- ];
195
+ const getYContent = (yContent) => [yContent.get(T), yContent.get(V)];
205
196
  const getTransactionChangesFromYDoc = (yContent, events) => {
206
197
  if (arrayLength(events) == 1 && arrayIsEmpty(events[0].path)) {
207
- return [yContent.get('t').toJSON(), yContent.get('v').toJSON()];
198
+ return [yContent.get(T).toJSON(), yContent.get(V).toJSON()];
208
199
  }
209
200
  const [yTables, yValues] = getYContent(yContent);
210
201
  const tables = {};
211
202
  const values = {};
212
203
  arrayForEach(events, ({path, changes: {keys}}) =>
213
- arrayShift(path) == tablesKey
204
+ arrayShift(path) == T
214
205
  ? ifNotUndefined(
215
206
  arrayShift(path),
216
207
  (yTableId) => {
@@ -257,7 +248,10 @@ const setTransactionChangesToYDoc = (
257
248
  getContent,
258
249
  getTransactionChanges,
259
250
  ) => {
260
- ensureYContent(yContent);
251
+ if (!yContent.size) {
252
+ yContent.set(T, new Map$1());
253
+ yContent.set(V, new Map$1());
254
+ }
261
255
  const [yTables, yValues] = getYContent(yContent);
262
256
  const transactionChangesDidFail = () => {
263
257
  transactionChangesFailed = 1;
@@ -349,7 +343,7 @@ const createYjsPersister = (
349
343
  const yContent = yDoc.getMap(yMapName);
350
344
  const getPersisted = async () =>
351
345
  yContent.size
352
- ? [yContent.get(tablesKey).toJSON(), yContent.get(valuesKey).toJSON()]
346
+ ? [yContent.get(T).toJSON(), yContent.get(V).toJSON()]
353
347
  : void 0;
354
348
  const setPersisted = async (getContent, getTransactionChanges) =>
355
349
  yDoc.transact(() =>
@@ -23,12 +23,14 @@ const VALUE = 'Value';
23
23
  const VALUES = VALUE + 's';
24
24
  const VALUE_IDS = VALUE + IDS;
25
25
 
26
+ const promise = Promise;
26
27
  const isFiniteNumber = isFinite;
27
28
  const isInstanceOf = (thing, cls) => thing instanceof cls;
28
29
  const isUndefined = (thing) => thing == void 0;
29
30
  const isTypeStringOrBoolean = (type) => type == STRING || type == BOOLEAN;
30
31
  const isString = (thing) => getTypeOf(thing) == STRING;
31
32
  const isArray = (thing) => Array.isArray(thing);
33
+ const promiseAll = async (promises) => promise.all(promises);
32
34
 
33
35
  const getCellOrValueType = (cell) => {
34
36
  const type = getTypeOf(cell);
@@ -2832,6 +2834,8 @@ const getStoreApi = (tablesSchema, valuesSchema, module) => {
2832
2834
 
2833
2835
  const jsonParse = JSON.parse;
2834
2836
 
2837
+ const PRETTIER = 'prettier/';
2838
+ const PRETTIER_PLUGINS = PRETTIER + 'plugins/';
2835
2839
  const prettierConfig = {
2836
2840
  parser: 'typescript',
2837
2841
  singleQuote: true,
@@ -2932,15 +2936,27 @@ const createTools = getCreateFunction((store) => {
2932
2936
  getStoreApi(getStoreTablesSchema(), getStoreValuesSchema(), module);
2933
2937
  const getPrettyStoreApi = async (module) => {
2934
2938
  const extensions = ['d.ts', 'ts', 'd.ts', 'tsx'];
2939
+ const plugins = [];
2935
2940
  let format;
2936
2941
  try {
2937
- format = (await import('prettier')).format;
2942
+ format = (await import(PRETTIER + 'standalone')).format;
2943
+ arrayPush(
2944
+ plugins,
2945
+ await import(PRETTIER_PLUGINS + 'estree'),
2946
+ await import(PRETTIER_PLUGINS + 'typescript'),
2947
+ );
2938
2948
  } catch (e) {
2939
- format = (str) => str;
2949
+ format = async (str) => str;
2940
2950
  }
2941
- return arrayMap(getStoreApi$1(module), (file, f) =>
2942
- formatJsDoc(
2943
- format(file, {...prettierConfig, filepath: `_.${extensions[f]}`}),
2951
+ return await promiseAll(
2952
+ arrayMap(getStoreApi$1(module), async (file, f) =>
2953
+ formatJsDoc(
2954
+ await format(file, {
2955
+ ...prettierConfig,
2956
+ plugins,
2957
+ filepath: `_.${extensions[f]}`,
2958
+ }),
2959
+ ),
2944
2960
  ),
2945
2961
  );
2946
2962
  };