@proteinjs/db 1.14.0 → 1.14.1

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.
@@ -3,6 +3,7 @@ import { getDb } from '../Db';
3
3
  import { Record } from '../Record';
4
4
  import { tableByName } from '../Table';
5
5
  import { ReferenceSerializerId } from '../serializers/ReferenceSerializer';
6
+ import { ReferenceCache } from './ReferenceCache';
6
7
 
7
8
  /**
8
9
  * The object returned by Db functions for each field of type ReferenceColumn in a record.
@@ -30,6 +31,15 @@ export class Reference<T extends Record> implements CustomSerializableObject {
30
31
 
31
32
  async get(): Promise<T | undefined> {
32
33
  if (!this._object && this._id) {
34
+ const cachedObject = ReferenceCache.get().get<T>(this._table, this._id);
35
+ if (cachedObject) {
36
+ /**
37
+ * We don't want to cache this reference in `this._object` in case the reference
38
+ * is replaced in `ReferenceCache`.
39
+ */
40
+ return cachedObject;
41
+ }
42
+
33
43
  const table = tableByName(this._table);
34
44
  const db = getDb();
35
45
  this._object = await db.get(table, { id: this._id });
@@ -39,6 +49,13 @@ export class Reference<T extends Record> implements CustomSerializableObject {
39
49
  }
40
50
 
41
51
  getIfExists(): T | undefined {
52
+ if (!this._object && this._id) {
53
+ const cachedObject = ReferenceCache.get().get<T>(this._table, this._id);
54
+ if (cachedObject) {
55
+ return cachedObject;
56
+ }
57
+ }
58
+
42
59
  return this._object;
43
60
  }
44
61
 
@@ -0,0 +1,117 @@
1
+ /**
2
+ * A way to cache referenced objects. Cached objects are consumed within `Reference`.
3
+ *
4
+ * A common way to use this would be to cache shared reference data on the client. Without
5
+ * this, reference data would be unique per `Reference` object, since `Reference.get` fetches
6
+ * a new instance of an object over the wire.
7
+ */
8
+ export class ReferenceCache {
9
+ private cache: { [table: string]: { [id: string]: any } } = {};
10
+
11
+ /**
12
+ * Returns the singleton instance of ReferenceCache
13
+ *
14
+ * @returns The global ReferenceCache instance
15
+ */
16
+ static get(): ReferenceCache {
17
+ if (!ReferenceCache.getGlobal().__proteinjs_db_ReferenceCache) {
18
+ ReferenceCache.getGlobal().__proteinjs_db_ReferenceCache = new ReferenceCache();
19
+ }
20
+
21
+ return ReferenceCache.getGlobal().__proteinjs_db_ReferenceCache;
22
+ }
23
+
24
+ /**
25
+ * Returns the global object based on environment
26
+ *
27
+ * @returns The global object (window in browser, globalThis elsewhere)
28
+ */
29
+ private static getGlobal(): any {
30
+ if (typeof window !== 'undefined') {
31
+ return window;
32
+ }
33
+
34
+ return globalThis;
35
+ }
36
+
37
+ /**
38
+ * Gets a record from the cache for a specific table by ID
39
+ *
40
+ * @param table Name of the table containing the record
41
+ * @param id ID of the record to retrieve
42
+ * @returns The cached record or undefined if not found
43
+ */
44
+ get<T>(table: string, id: string): T | undefined {
45
+ return this.cache[table]?.[id];
46
+ }
47
+
48
+ /**
49
+ * Sets a single record in the cache
50
+ *
51
+ * @param table Name of the table to add the record to
52
+ * @param id ID of the record
53
+ * @param record The record data to store
54
+ */
55
+ set(table: string, id: string, record: any): void {
56
+ this.ensureTableExists(table);
57
+ this.cache[table][id] = record;
58
+ }
59
+
60
+ /**
61
+ * Ensures a table exists in the cache
62
+ *
63
+ * @param table Name of the table to initialize if needed
64
+ */
65
+ private ensureTableExists(table: string): void {
66
+ if (!this.cache[table]) {
67
+ this.cache[table] = {};
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Clears all cached records for a specific table
73
+ *
74
+ * @param table Name of the table to clear from cache
75
+ */
76
+ clearTable(table: string): void {
77
+ if (this.cache[table]) {
78
+ delete this.cache[table];
79
+ }
80
+ }
81
+
82
+ /**
83
+ * Sets multiple records for a specific table at once
84
+ *
85
+ * @param table Name of the table to add records to
86
+ * @param records Either an array of records or an object mapping record IDs to their values
87
+ */
88
+ setMultiple<T extends { [key: string]: any } & { id: string }>(
89
+ table: string,
90
+ records: T[] | { [id: string]: any }
91
+ ): void {
92
+ this.ensureTableExists(table);
93
+
94
+ if (Array.isArray(records)) {
95
+ // Handle array input
96
+ for (const record of records) {
97
+ this.cache[table][record.id] = record;
98
+ }
99
+ } else {
100
+ // Handle map/object input
101
+ for (const [id, record] of Object.entries(records)) {
102
+ this.cache[table][id] = record;
103
+ }
104
+ }
105
+ }
106
+
107
+ /**
108
+ * Reloads a table by clearing it and then setting the provided records
109
+ *
110
+ * @param table Name of the table to reload
111
+ * @param records Either an array of records or an object mapping record IDs to their values
112
+ */
113
+ reloadTable<T extends { [key: string]: any }>(table: string, records: T[] | { [id: string]: any }): void {
114
+ this.clearTable(table);
115
+ this.setMultiple(table, records);
116
+ }
117
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2023 Brent Bahry
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.