sliftutils 0.85.0 → 0.87.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/index.d.ts CHANGED
@@ -127,6 +127,8 @@ declare module "sliftutils/misc/random" {
127
127
 
128
128
  declare module "sliftutils/misc/types" {
129
129
  export declare function isDefined<T>(value: T | undefined | null): value is T;
130
+ export declare function freezeObject(value: unknown): unknown;
131
+ export declare function deepFreezeObject(value: unknown): void;
130
132
 
131
133
  }
132
134
 
@@ -658,6 +660,8 @@ declare module "sliftutils/storage/DiskCollection" {
658
660
  writeDelay?: number | undefined;
659
661
  cbor?: boolean | undefined;
660
662
  noPrompt?: boolean | undefined;
663
+ freeze?: "deep" | "shallow" | undefined;
664
+ beforeWrite?: ((newValue: T) => void) | undefined;
661
665
  } | undefined);
662
666
  transactionStorage: TransactionStorage | undefined;
663
667
  initStorage(): Promise<IStorage<T>>;
@@ -969,6 +973,7 @@ declare module "sliftutils/storage/StorageObservable" {
969
973
  import { IStorage, IStorageSync } from "./IStorage";
970
974
  export declare class StorageSync<T> implements IStorageSync<T> {
971
975
  storage: IStorage<T>;
976
+ private config?;
972
977
  cached: import("mobx").ObservableMap<string, T | undefined>;
973
978
  infoCached: import("mobx").ObservableMap<string, {
974
979
  size: number;
@@ -978,7 +983,10 @@ declare module "sliftutils/storage/StorageObservable" {
978
983
  synced: {
979
984
  keySeqNum: number;
980
985
  };
981
- constructor(storage: IStorage<T>);
986
+ constructor(storage: IStorage<T>, config?: {
987
+ freeze?: "deep" | "shallow" | undefined;
988
+ beforeWrite?: ((newValue: T) => void) | undefined;
989
+ } | undefined);
982
990
  get(key: string): T | undefined;
983
991
  set(key: string, value: T): void;
984
992
  remove(key: string): void;
package/misc/types.d.ts CHANGED
@@ -1 +1,3 @@
1
1
  export declare function isDefined<T>(value: T | undefined | null): value is T;
2
+ export declare function freezeObject(value: unknown): unknown;
3
+ export declare function deepFreezeObject(value: unknown): void;
package/misc/types.ts CHANGED
@@ -1,3 +1,24 @@
1
1
  export function isDefined<T>(value: T | undefined | null): value is T {
2
2
  return value !== undefined && value !== null;
3
+ }
4
+
5
+
6
+ export function freezeObject(value: unknown) {
7
+ if (!value) return value;
8
+ Object.freeze(value);
9
+ }
10
+
11
+ export function deepFreezeObject(value: unknown) {
12
+ if (!value) return;
13
+ if (typeof value !== "object") return;
14
+ if (Object.isFrozen(value)) return;
15
+
16
+ Object.freeze(value);
17
+
18
+ Object.getOwnPropertyNames(value).forEach(prop => {
19
+ const propValue = (value as any)[prop];
20
+ if (propValue && typeof propValue === "object") {
21
+ deepFreezeObject(propValue);
22
+ }
23
+ });
3
24
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sliftutils",
3
- "version": "0.85.0",
3
+ "version": "0.87.0",
4
4
  "main": "index.js",
5
5
  "license": "MIT",
6
6
  "files": [
@@ -48,7 +48,7 @@
48
48
  "mobx": "^6.13.3",
49
49
  "preact-old-types": "^10.28.1",
50
50
  "shell-quote": "^1.8.3",
51
- "socket-function": "^0.164.0",
51
+ "socket-function": "^0.165.0",
52
52
  "typenode": "^6.0.0",
53
53
  "typesafecss": "*",
54
54
  "ws": "^8.18.3",
@@ -10,6 +10,8 @@ export declare class DiskCollection<T> implements IStorageSync<T> {
10
10
  writeDelay?: number | undefined;
11
11
  cbor?: boolean | undefined;
12
12
  noPrompt?: boolean | undefined;
13
+ freeze?: "deep" | "shallow" | undefined;
14
+ beforeWrite?: ((newValue: T) => void) | undefined;
13
15
  } | undefined);
14
16
  transactionStorage: TransactionStorage | undefined;
15
17
  initStorage(): Promise<IStorage<T>>;
@@ -18,6 +18,9 @@ export class DiskCollection<T> implements IStorageSync<T> {
18
18
  writeDelay?: number;
19
19
  cbor?: boolean;
20
20
  noPrompt?: boolean;
21
+ freeze?: "shallow" | "deep";
22
+ // May mutate newValue in order to change what will be written
23
+ beforeWrite?: (newValue: T) => void;
21
24
  }
22
25
  ) {
23
26
  }
@@ -41,7 +44,8 @@ export class DiskCollection<T> implements IStorageSync<T> {
41
44
  private synced = new StorageSync(
42
45
  new PendingStorage(`Collection (${this.collectionName})`,
43
46
  new DelayedStorage<T>(this.baseStorage)
44
- )
47
+ ),
48
+ this.config
45
49
  );
46
50
 
47
51
  public get(key: string): T | undefined {
@@ -1,6 +1,7 @@
1
1
  import { IStorage, IStorageSync } from "./IStorage";
2
2
  export declare class StorageSync<T> implements IStorageSync<T> {
3
3
  storage: IStorage<T>;
4
+ private config?;
4
5
  cached: import("mobx").ObservableMap<string, T | undefined>;
5
6
  infoCached: import("mobx").ObservableMap<string, {
6
7
  size: number;
@@ -10,7 +11,10 @@ export declare class StorageSync<T> implements IStorageSync<T> {
10
11
  synced: {
11
12
  keySeqNum: number;
12
13
  };
13
- constructor(storage: IStorage<T>);
14
+ constructor(storage: IStorage<T>, config?: {
15
+ freeze?: "deep" | "shallow" | undefined;
16
+ beforeWrite?: ((newValue: T) => void) | undefined;
17
+ } | undefined);
14
18
  get(key: string): T | undefined;
15
19
  set(key: string, value: T): void;
16
20
  remove(key: string): void;
@@ -1,5 +1,5 @@
1
1
  import { observable } from "mobx";
2
- import { isDefined } from "../misc/types";
2
+ import { deepFreezeObject, freezeObject, isDefined } from "../misc/types";
3
3
  import { IStorage, IStorageSync } from "./IStorage";
4
4
 
5
5
  // NOTE: At around 500K values (depending on their size to some degree), this will take about 2 minutes to load. But once it does it will be fast. So... keep that in mind. I recommend not exceeding 100K
@@ -11,7 +11,11 @@ export class StorageSync<T> implements IStorageSync<T> {
11
11
  keySeqNum: 0,
12
12
  }, undefined, { deep: false });
13
13
 
14
- constructor(public storage: IStorage<T>) {
14
+ constructor(public storage: IStorage<T>, private config?: {
15
+ freeze?: "shallow" | "deep";
16
+ // May mutate newValue in order to change what will be written
17
+ beforeWrite?: (newValue: T) => void;
18
+ }) {
15
19
  storage.watchResync?.(async () => {
16
20
  // NOTE: If there's multiple tabs open, this'll trigger a lot, so we can't just clear all the values, as that'll cause a render where nothing's loaded.
17
21
  this.loadedKeys = false;
@@ -33,6 +37,9 @@ export class StorageSync<T> implements IStorageSync<T> {
33
37
  return this.cached.get(key);
34
38
  }
35
39
  public set(key: string, value: T): void {
40
+ if (this.config?.beforeWrite) {
41
+ this.config.beforeWrite(value);
42
+ }
36
43
  if (!this.keys.has(key)) {
37
44
  this.keys.add(key);
38
45
  this.synced.keySeqNum++;
@@ -79,7 +86,12 @@ export class StorageSync<T> implements IStorageSync<T> {
79
86
  let value = this.cached.get(key);
80
87
  if (value === undefined) {
81
88
  value = await this.storage.get(key);
82
- if (this.cached.get(key) === undefined) {
89
+ if (value !== undefined && this.cached.get(key) === undefined) {
90
+ if (this.config?.freeze === "shallow") {
91
+ freezeObject(value);
92
+ } else if (this.config?.freeze === "deep") {
93
+ deepFreezeObject(value);
94
+ }
83
95
  this.cached.set(key, value);
84
96
  }
85
97
  }
@@ -401,26 +401,20 @@ export class TransactionStorage implements IStorage<Buffer> {
401
401
  this.cache.delete(entry.key);
402
402
  } else {
403
403
  if (!anyChanged && !initialLoad) {
404
- let prev = this.cache.get(entry.key);
405
- if (!prev) {
406
- anyChanged = true;
407
- } else {
408
- if (!prev.value) {
409
- if (entry.value) {
410
- anyChanged = true;
411
- }
412
- } else {
413
- if (!entry.value) {
414
- anyChanged = true;
415
- } else {
416
- // Both values, so... it might not have changed
417
- if (!prev.value.equals(entry.value)) {
418
- anyChanged = true;
419
- }
420
- }
404
+ const hasChanged = () => {
405
+ let prev = this.cache.get(entry.key);
406
+ if (!prev) {
407
+ return true;
421
408
  }
422
- }
409
+ if (!!prev.value !== !!entry.value) return true;
410
+ if (prev.value && entry.value && !prev.value.equals(entry.value)) {
411
+ return true;
412
+ }
413
+ return false;
414
+ };
415
+ anyChanged = hasChanged() || anyChanged;
423
416
  }
417
+
424
418
  this.cache.set(entry.key, entry);
425
419
  }
426
420
  }
@@ -13,24 +13,6 @@ export class ExamplePage extends preact.Component {
13
13
  count: 0,
14
14
  });
15
15
 
16
- onKeyDown = (e: KeyboardEvent) => {
17
- // Skip if the current target is an ipnut
18
- if (e.target instanceof HTMLInputElement || e.target instanceof HTMLTextAreaElement) {
19
- return;
20
- }
21
- let hotkeySelector = `[data-hotkey="${e.code}"]`;
22
- let elements = document.querySelectorAll(hotkeySelector);
23
- for (let element of elements) {
24
- (element as HTMLElement).click();
25
- }
26
- };
27
- componentDidMount(): void {
28
- document.addEventListener("keydown", this.onKeyDown);
29
- }
30
- componentWillUnmount(): void {
31
- document.removeEventListener("keydown", this.onKeyDown);
32
- }
33
-
34
16
  render() {
35
17
  return (
36
18
  <div className={css.pad2(20)}>
package/yarn.lock CHANGED
@@ -1349,7 +1349,7 @@ preact-old-types@^10.28.1:
1349
1349
  resolved "https://registry.yarnpkg.com/preact-old-types/-/preact-old-types-10.28.1.tgz#58f9400aa1b80768809c296534ec7b49f6f09a0d"
1350
1350
  integrity sha512-7r64HwL/PJtzE7jUMFkYVec+vSUf3z8Uozd8Bhl4HMvhcWINFzJsIEHKLAlkeCbzv+jTQl0UwVeMJQ26jK5bDg==
1351
1351
 
1352
- preact@10.28.1, "preact@npm:preact-old-types@*":
1352
+ preact@10.24.3, "preact@npm:preact-old-types@*":
1353
1353
  version "10.28.1"
1354
1354
  resolved "https://registry.yarnpkg.com/preact-old-types/-/preact-old-types-10.28.1.tgz#58f9400aa1b80768809c296534ec7b49f6f09a0d"
1355
1355
  integrity sha512-7r64HwL/PJtzE7jUMFkYVec+vSUf3z8Uozd8Bhl4HMvhcWINFzJsIEHKLAlkeCbzv+jTQl0UwVeMJQ26jK5bDg==
@@ -1494,17 +1494,17 @@ slash@^3.0.0:
1494
1494
  resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634"
1495
1495
  integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==
1496
1496
 
1497
- socket-function@^0.164.0:
1498
- version "0.164.0"
1499
- resolved "https://registry.yarnpkg.com/socket-function/-/socket-function-0.164.0.tgz#81b12ad687aaf7455159ab7e8788b1f8a5a7f513"
1500
- integrity sha512-+aQg9T4zJVFqHed5WuyBOtfW4MfdkdE2I3IWqEaeOv8+/e3CEtg5X/kqiFoyzCcx1efDS/eC0J6+WxODynBjXA==
1497
+ socket-function@^0.165.0:
1498
+ version "0.165.0"
1499
+ resolved "https://registry.yarnpkg.com/socket-function/-/socket-function-0.165.0.tgz#2c262c5cc75a79233d08538517030c504745a94c"
1500
+ integrity sha512-VfpljEyUEjQD4flTboGwgcerK2vuVvDM0iPNL4L4Qyo76G5DQVGcHCaYDwZuuAJ8gvTXDq9j7P7vgdjElNAhXw==
1501
1501
  dependencies:
1502
1502
  "@types/pako" "^2.0.3"
1503
1503
  "@types/ws" "^8.5.3"
1504
1504
  cbor-x "^1.6.0"
1505
1505
  mobx "^6.6.2"
1506
1506
  pako "^2.1.0"
1507
- preact "10.28.1"
1507
+ preact "10.24.3"
1508
1508
  typedev "^0.4.0"
1509
1509
  typenode "^5.13.0"
1510
1510
  ws "^8.17.1"