@koolbase/core 12.10.0 → 12.11.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/cjs/collection-controller.d.ts +14 -0
- package/dist/cjs/collection-controller.js +29 -0
- package/dist/cjs/live-source.d.ts +6 -0
- package/dist/cjs/live-source.js +16 -0
- package/dist/cjs/realtime.js +3 -0
- package/dist/esm/collection-controller.d.ts +14 -0
- package/dist/esm/collection-controller.js +29 -0
- package/dist/esm/live-source.d.ts +6 -0
- package/dist/esm/live-source.js +12 -0
- package/dist/esm/realtime.js +3 -0
- package/package.json +1 -1
|
@@ -8,6 +8,13 @@ export interface CollectionQuery {
|
|
|
8
8
|
orderDesc?: boolean;
|
|
9
9
|
/** Page size; the server's default (20) when absent. */
|
|
10
10
|
limit?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Re-read page one, silently, when Koolbase realtime reports a record
|
|
13
|
+
* created, updated or deleted in this collection (debounced: a burst is one
|
|
14
|
+
* read). Realtime needs a signed-in user; until there is one, the list
|
|
15
|
+
* behaves as a normal list and goes live once the session exists.
|
|
16
|
+
*/
|
|
17
|
+
live?: boolean;
|
|
11
18
|
}
|
|
12
19
|
export interface CollectionState {
|
|
13
20
|
readonly status: CollectionStatus;
|
|
@@ -39,6 +46,8 @@ export declare class KoolbaseCollectionController {
|
|
|
39
46
|
private laterPages;
|
|
40
47
|
private nextOffset;
|
|
41
48
|
private unregister;
|
|
49
|
+
private unlive;
|
|
50
|
+
private liveTimer;
|
|
42
51
|
constructor(db: QueryReader, collection: string, query?: CollectionQuery);
|
|
43
52
|
getState(): CollectionState;
|
|
44
53
|
/** Called on every change. Returns the unsubscribe. */
|
|
@@ -53,6 +62,11 @@ export declare class KoolbaseCollectionController {
|
|
|
53
62
|
* shown stays while it runs, and stays if it fails.
|
|
54
63
|
*/
|
|
55
64
|
private refreshAfterWrite;
|
|
65
|
+
/**
|
|
66
|
+
* A change someone made, reported by realtime: page one again, silently, as
|
|
67
|
+
* after a write -- once per burst (250 ms), not once per event.
|
|
68
|
+
*/
|
|
69
|
+
private scheduleLiveRefresh;
|
|
56
70
|
/**
|
|
57
71
|
* The next page, appended. Does nothing unless loaded with more to load.
|
|
58
72
|
* If rows are added or removed on the server between pages, one can be
|
|
@@ -25,6 +25,7 @@
|
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
26
|
exports.KoolbaseCollectionController = exports.initialCollectionState = void 0;
|
|
27
27
|
exports.collectionQueryKey = collectionQueryKey;
|
|
28
|
+
const live_source_js_1 = require("./live-source.js");
|
|
28
29
|
const query_refresh_js_1 = require("./query-refresh.js");
|
|
29
30
|
exports.initialCollectionState = Object.freeze({
|
|
30
31
|
status: 'loading',
|
|
@@ -49,6 +50,8 @@ function collectionQueryKey(collection, query = {}) {
|
|
|
49
50
|
query.orderBy ?? null,
|
|
50
51
|
query.orderDesc === true,
|
|
51
52
|
query.limit ?? null,
|
|
53
|
+
// Only when live: every other query keeps the key it always had.
|
|
54
|
+
...(query.live === true ? ['live'] : []),
|
|
52
55
|
]);
|
|
53
56
|
}
|
|
54
57
|
/** Page one, then the later pages without any record already shown. */
|
|
@@ -76,6 +79,9 @@ class KoolbaseCollectionController {
|
|
|
76
79
|
this.nextOffset = 0;
|
|
77
80
|
// A write to this collection re-runs this query (query-refresh.ts).
|
|
78
81
|
this.unregister = null;
|
|
82
|
+
// A live list's realtime subscription, and its pending debounced re-read.
|
|
83
|
+
this.unlive = null;
|
|
84
|
+
this.liveTimer = null;
|
|
79
85
|
this.db = db;
|
|
80
86
|
this.collection = collection;
|
|
81
87
|
this.spec = query;
|
|
@@ -97,6 +103,9 @@ class KoolbaseCollectionController {
|
|
|
97
103
|
if (this.disposed)
|
|
98
104
|
return;
|
|
99
105
|
this.unregister ?? (this.unregister = (0, query_refresh_js_1.registerQueryRefresher)(this.collection, () => this.refreshAfterWrite()));
|
|
106
|
+
if (this.spec.live === true) {
|
|
107
|
+
this.unlive ?? (this.unlive = (0, live_source_js_1.liveSource)()?.subscribe(this.collection, () => this.scheduleLiveRefresh()) ?? null);
|
|
108
|
+
}
|
|
100
109
|
await this.firstPage('default');
|
|
101
110
|
}
|
|
102
111
|
/** Page one again, from the server. What is shown stays while it runs, and stays if it fails. */
|
|
@@ -118,6 +127,20 @@ class KoolbaseCollectionController {
|
|
|
118
127
|
return;
|
|
119
128
|
await this.firstPage('network-only');
|
|
120
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* A change someone made, reported by realtime: page one again, silently, as
|
|
132
|
+
* after a write -- once per burst (250 ms), not once per event.
|
|
133
|
+
*/
|
|
134
|
+
scheduleLiveRefresh() {
|
|
135
|
+
if (this.disposed || this.liveTimer)
|
|
136
|
+
return;
|
|
137
|
+
this.liveTimer = setTimeout(() => {
|
|
138
|
+
this.liveTimer = null;
|
|
139
|
+
void this.refreshAfterWrite();
|
|
140
|
+
}, 250);
|
|
141
|
+
// A pending re-read must not be what keeps a Node process alive.
|
|
142
|
+
this.liveTimer.unref?.();
|
|
143
|
+
}
|
|
121
144
|
/**
|
|
122
145
|
* The next page, appended. Does nothing unless loaded with more to load.
|
|
123
146
|
* If rows are added or removed on the server between pages, one can be
|
|
@@ -153,6 +176,12 @@ class KoolbaseCollectionController {
|
|
|
153
176
|
this.disposed = true;
|
|
154
177
|
this.unregister?.();
|
|
155
178
|
this.unregister = null;
|
|
179
|
+
this.unlive?.();
|
|
180
|
+
this.unlive = null;
|
|
181
|
+
if (this.liveTimer) {
|
|
182
|
+
clearTimeout(this.liveTimer);
|
|
183
|
+
this.liveTimer = null;
|
|
184
|
+
}
|
|
156
185
|
this.listeners.clear();
|
|
157
186
|
}
|
|
158
187
|
async firstPage(cache) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface LiveSource {
|
|
2
|
+
/** Calls back on every record event in the collection; returns the unsubscribe. */
|
|
3
|
+
subscribe(collection: string, callback: (event: unknown) => void): () => void;
|
|
4
|
+
}
|
|
5
|
+
export declare function setLiveSource(source: LiveSource | null): void;
|
|
6
|
+
export declare function liveSource(): LiveSource | null;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// The realtime client a live list subscribes through. KoolbaseRealtime
|
|
3
|
+
// registers itself when it is created, as query-refresh.ts registers the
|
|
4
|
+
// refreshers writes run: a list reaches realtime without the host packages
|
|
5
|
+
// passing it in. None registered (realtime never created): a live list is
|
|
6
|
+
// simply a list.
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.setLiveSource = setLiveSource;
|
|
9
|
+
exports.liveSource = liveSource;
|
|
10
|
+
let active = null;
|
|
11
|
+
function setLiveSource(source) {
|
|
12
|
+
active = source;
|
|
13
|
+
}
|
|
14
|
+
function liveSource() {
|
|
15
|
+
return active;
|
|
16
|
+
}
|
package/dist/cjs/realtime.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.KoolbaseRealtime = void 0;
|
|
4
4
|
const cache_store_js_1 = require("./cache-store.js");
|
|
5
5
|
const record_js_1 = require("./record.js");
|
|
6
|
+
const live_source_js_1 = require("./live-source.js");
|
|
6
7
|
const EVENT_TYPE_MAP = {
|
|
7
8
|
'db.record.created': 'created',
|
|
8
9
|
'db.record.updated': 'updated',
|
|
@@ -43,6 +44,8 @@ class KoolbaseRealtime {
|
|
|
43
44
|
this.config = config;
|
|
44
45
|
this.getToken = getToken;
|
|
45
46
|
this.getUserId = getUserId;
|
|
47
|
+
// Live lists (CollectionQuery.live) subscribe through this client.
|
|
48
|
+
(0, live_source_js_1.setLiveSource)(this);
|
|
46
49
|
}
|
|
47
50
|
/** Files a record seen over the socket, if we know whose it is. */
|
|
48
51
|
async cacheSeenRecord(collection, record) {
|
|
@@ -8,6 +8,13 @@ export interface CollectionQuery {
|
|
|
8
8
|
orderDesc?: boolean;
|
|
9
9
|
/** Page size; the server's default (20) when absent. */
|
|
10
10
|
limit?: number;
|
|
11
|
+
/**
|
|
12
|
+
* Re-read page one, silently, when Koolbase realtime reports a record
|
|
13
|
+
* created, updated or deleted in this collection (debounced: a burst is one
|
|
14
|
+
* read). Realtime needs a signed-in user; until there is one, the list
|
|
15
|
+
* behaves as a normal list and goes live once the session exists.
|
|
16
|
+
*/
|
|
17
|
+
live?: boolean;
|
|
11
18
|
}
|
|
12
19
|
export interface CollectionState {
|
|
13
20
|
readonly status: CollectionStatus;
|
|
@@ -39,6 +46,8 @@ export declare class KoolbaseCollectionController {
|
|
|
39
46
|
private laterPages;
|
|
40
47
|
private nextOffset;
|
|
41
48
|
private unregister;
|
|
49
|
+
private unlive;
|
|
50
|
+
private liveTimer;
|
|
42
51
|
constructor(db: QueryReader, collection: string, query?: CollectionQuery);
|
|
43
52
|
getState(): CollectionState;
|
|
44
53
|
/** Called on every change. Returns the unsubscribe. */
|
|
@@ -53,6 +62,11 @@ export declare class KoolbaseCollectionController {
|
|
|
53
62
|
* shown stays while it runs, and stays if it fails.
|
|
54
63
|
*/
|
|
55
64
|
private refreshAfterWrite;
|
|
65
|
+
/**
|
|
66
|
+
* A change someone made, reported by realtime: page one again, silently, as
|
|
67
|
+
* after a write -- once per burst (250 ms), not once per event.
|
|
68
|
+
*/
|
|
69
|
+
private scheduleLiveRefresh;
|
|
56
70
|
/**
|
|
57
71
|
* The next page, appended. Does nothing unless loaded with more to load.
|
|
58
72
|
* If rows are added or removed on the server between pages, one can be
|
|
@@ -21,6 +21,7 @@
|
|
|
21
21
|
// Known limit: if rows are added or removed on the server between pages,
|
|
22
22
|
// the pages shift and a row can be skipped until refresh(), which reloads
|
|
23
23
|
// from page one. Duplicates are removed; a skipped row cannot be detected.
|
|
24
|
+
import { liveSource } from './live-source.js';
|
|
24
25
|
import { registerQueryRefresher } from './query-refresh.js';
|
|
25
26
|
export const initialCollectionState = Object.freeze({
|
|
26
27
|
status: 'loading',
|
|
@@ -45,6 +46,8 @@ export function collectionQueryKey(collection, query = {}) {
|
|
|
45
46
|
query.orderBy ?? null,
|
|
46
47
|
query.orderDesc === true,
|
|
47
48
|
query.limit ?? null,
|
|
49
|
+
// Only when live: every other query keeps the key it always had.
|
|
50
|
+
...(query.live === true ? ['live'] : []),
|
|
48
51
|
]);
|
|
49
52
|
}
|
|
50
53
|
/** Page one, then the later pages without any record already shown. */
|
|
@@ -72,6 +75,9 @@ export class KoolbaseCollectionController {
|
|
|
72
75
|
this.nextOffset = 0;
|
|
73
76
|
// A write to this collection re-runs this query (query-refresh.ts).
|
|
74
77
|
this.unregister = null;
|
|
78
|
+
// A live list's realtime subscription, and its pending debounced re-read.
|
|
79
|
+
this.unlive = null;
|
|
80
|
+
this.liveTimer = null;
|
|
75
81
|
this.db = db;
|
|
76
82
|
this.collection = collection;
|
|
77
83
|
this.spec = query;
|
|
@@ -93,6 +99,9 @@ export class KoolbaseCollectionController {
|
|
|
93
99
|
if (this.disposed)
|
|
94
100
|
return;
|
|
95
101
|
this.unregister ?? (this.unregister = registerQueryRefresher(this.collection, () => this.refreshAfterWrite()));
|
|
102
|
+
if (this.spec.live === true) {
|
|
103
|
+
this.unlive ?? (this.unlive = liveSource()?.subscribe(this.collection, () => this.scheduleLiveRefresh()) ?? null);
|
|
104
|
+
}
|
|
96
105
|
await this.firstPage('default');
|
|
97
106
|
}
|
|
98
107
|
/** Page one again, from the server. What is shown stays while it runs, and stays if it fails. */
|
|
@@ -114,6 +123,20 @@ export class KoolbaseCollectionController {
|
|
|
114
123
|
return;
|
|
115
124
|
await this.firstPage('network-only');
|
|
116
125
|
}
|
|
126
|
+
/**
|
|
127
|
+
* A change someone made, reported by realtime: page one again, silently, as
|
|
128
|
+
* after a write -- once per burst (250 ms), not once per event.
|
|
129
|
+
*/
|
|
130
|
+
scheduleLiveRefresh() {
|
|
131
|
+
if (this.disposed || this.liveTimer)
|
|
132
|
+
return;
|
|
133
|
+
this.liveTimer = setTimeout(() => {
|
|
134
|
+
this.liveTimer = null;
|
|
135
|
+
void this.refreshAfterWrite();
|
|
136
|
+
}, 250);
|
|
137
|
+
// A pending re-read must not be what keeps a Node process alive.
|
|
138
|
+
this.liveTimer.unref?.();
|
|
139
|
+
}
|
|
117
140
|
/**
|
|
118
141
|
* The next page, appended. Does nothing unless loaded with more to load.
|
|
119
142
|
* If rows are added or removed on the server between pages, one can be
|
|
@@ -149,6 +172,12 @@ export class KoolbaseCollectionController {
|
|
|
149
172
|
this.disposed = true;
|
|
150
173
|
this.unregister?.();
|
|
151
174
|
this.unregister = null;
|
|
175
|
+
this.unlive?.();
|
|
176
|
+
this.unlive = null;
|
|
177
|
+
if (this.liveTimer) {
|
|
178
|
+
clearTimeout(this.liveTimer);
|
|
179
|
+
this.liveTimer = null;
|
|
180
|
+
}
|
|
152
181
|
this.listeners.clear();
|
|
153
182
|
}
|
|
154
183
|
async firstPage(cache) {
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export interface LiveSource {
|
|
2
|
+
/** Calls back on every record event in the collection; returns the unsubscribe. */
|
|
3
|
+
subscribe(collection: string, callback: (event: unknown) => void): () => void;
|
|
4
|
+
}
|
|
5
|
+
export declare function setLiveSource(source: LiveSource | null): void;
|
|
6
|
+
export declare function liveSource(): LiveSource | null;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// The realtime client a live list subscribes through. KoolbaseRealtime
|
|
2
|
+
// registers itself when it is created, as query-refresh.ts registers the
|
|
3
|
+
// refreshers writes run: a list reaches realtime without the host packages
|
|
4
|
+
// passing it in. None registered (realtime never created): a live list is
|
|
5
|
+
// simply a list.
|
|
6
|
+
let active = null;
|
|
7
|
+
export function setLiveSource(source) {
|
|
8
|
+
active = source;
|
|
9
|
+
}
|
|
10
|
+
export function liveSource() {
|
|
11
|
+
return active;
|
|
12
|
+
}
|
package/dist/esm/realtime.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { cacheRecord, removeCachedRecord } from './cache-store.js';
|
|
2
2
|
import { recordFromWire } from './record.js';
|
|
3
|
+
import { setLiveSource } from './live-source.js';
|
|
3
4
|
const EVENT_TYPE_MAP = {
|
|
4
5
|
'db.record.created': 'created',
|
|
5
6
|
'db.record.updated': 'updated',
|
|
@@ -40,6 +41,8 @@ export class KoolbaseRealtime {
|
|
|
40
41
|
this.config = config;
|
|
41
42
|
this.getToken = getToken;
|
|
42
43
|
this.getUserId = getUserId;
|
|
44
|
+
// Live lists (CollectionQuery.live) subscribe through this client.
|
|
45
|
+
setLiveSource(this);
|
|
43
46
|
}
|
|
44
47
|
/** Files a record seen over the socket, if we know whose it is. */
|
|
45
48
|
async cacheSeenRecord(collection, record) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@koolbase/core",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.11.0",
|
|
4
4
|
"description": "Koolbase SDK core \u2014 shared behaviour behind @koolbase/react-native and @koolbase/js. Install one of those, not this.",
|
|
5
5
|
"main": "./dist/cjs/index.js",
|
|
6
6
|
"types": "./dist/esm/index.d.ts",
|