@kumiai/hub-server 0.9.0 → 0.10.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.
- package/README.md +4 -0
- package/lib/hub.d.ts +5 -1
- package/lib/hub.js +5 -0
- package/lib/index.d.ts +1 -1
- package/lib/memoryStore.js +4 -3
- package/package.json +10 -10
package/README.md
CHANGED
|
@@ -16,6 +16,10 @@ client registry for push fan-out, and an in-memory `HubStore` for development an
|
|
|
16
16
|
`DEFAULT_HUB_ACCESS_RULES`.
|
|
17
17
|
- `HubStoreErrorEvent`, `HubStoreErrorHook` — the `onStoreError` event and hook types.
|
|
18
18
|
|
|
19
|
+
`createHub` accepts `replay` with a cache and tuning (`maxAge`, `leeway`, `maxEntries`).
|
|
20
|
+
The hub always enables replay checks and rejects stale tokens. Supply a persistent `replay.cache`
|
|
21
|
+
to keep replay protection across restarts; omitted, it uses a per-process memory cache.
|
|
22
|
+
|
|
19
23
|
```ts
|
|
20
24
|
import { createHub, createMemoryStore } from '@kumiai/hub-server'
|
|
21
25
|
|
package/lib/hub.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ServerTransportOf } from '@enkaku/protocol';
|
|
2
|
-
import type { AccessRules, ResourceLimits, Server } from '@enkaku/server';
|
|
2
|
+
import type { AccessRules, ReplayOptions, ResourceLimits, Server } from '@enkaku/server';
|
|
3
3
|
import type { Identity } from '@kokuin/token';
|
|
4
4
|
import type { HubProtocol, HubStore, WakeRegistry, WakeSender } from '@kumiai/hub-protocol';
|
|
5
5
|
import { type AuthorizeHook, type HubRateLimits, type HubStoreErrorHook, type KeyPackageFetchLimits } from './handlers.js';
|
|
@@ -20,6 +20,8 @@ export type HubPurgeOptions = {
|
|
|
20
20
|
*/
|
|
21
21
|
olderThan?: number;
|
|
22
22
|
};
|
|
23
|
+
/** Replay settings a host may tune. The hub always enables replay checks and rejects stale tokens. */
|
|
24
|
+
export type HubReplayOptions = Omit<ReplayOptions, 'enabled' | 'rejectStale'>;
|
|
23
25
|
export type CreateHubParams = {
|
|
24
26
|
transport: ServerTransportOf<HubProtocol>;
|
|
25
27
|
store: HubStore;
|
|
@@ -30,6 +32,8 @@ export type CreateHubParams = {
|
|
|
30
32
|
identity: Identity;
|
|
31
33
|
/** Access rules enforced by the server. Defaults to {@link DEFAULT_HUB_ACCESS_RULES}. */
|
|
32
34
|
accessRules?: AccessRules;
|
|
35
|
+
/** Omitted: per-process memory cache. Only a persistent `cache` survives a hub restart. */
|
|
36
|
+
replay?: HubReplayOptions;
|
|
33
37
|
/**
|
|
34
38
|
* Per-action authorization hook. Consulted for publish, subscribe, topic/fetch, keypackage/*,
|
|
35
39
|
* wake/*, and receive — the coarse `receive` gate at channel open plus a per-frame
|
package/lib/hub.js
CHANGED
|
@@ -56,6 +56,11 @@ export function createHub(params) {
|
|
|
56
56
|
transport: params.transport,
|
|
57
57
|
identity: params.identity,
|
|
58
58
|
accessRules: params.accessRules ?? DEFAULT_HUB_ACCESS_RULES,
|
|
59
|
+
replay: {
|
|
60
|
+
...params.replay,
|
|
61
|
+
enabled: true,
|
|
62
|
+
rejectStale: true
|
|
63
|
+
},
|
|
59
64
|
limits
|
|
60
65
|
});
|
|
61
66
|
if (params.purge !== false) {
|
package/lib/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
export type { AuthorizeDecision, AuthorizeHook, AuthorizeRequest, CreateHandlersParams, HubRateLimits, HubStoreErrorEvent, HubStoreErrorHook, KeyPackageFetchLimits, } from './handlers.js';
|
|
2
2
|
export { createHandlers, DEFAULT_KEYPACKAGE_FETCH_LIMITS, DEFAULT_RATE_LIMITS, DEFAULT_RECEIVE_BUFFER_LIMIT, } from './handlers.js';
|
|
3
|
-
export type { CreateHubParams, HubInstance, HubPurgeOptions } from './hub.js';
|
|
3
|
+
export type { CreateHubParams, HubInstance, HubPurgeOptions, HubReplayOptions } from './hub.js';
|
|
4
4
|
export { createHub, DEFAULT_HUB_ACCESS_RULES } from './hub.js';
|
|
5
5
|
export { createMemoryStore, type MemoryStoreOptions } from './memoryStore.js';
|
|
6
6
|
export { createRateLimiter, type RateLimitConfig, type RateLimiter } from './rateLimit.js';
|
package/lib/memoryStore.js
CHANGED
|
@@ -241,7 +241,8 @@ function isLive(entry, nowSeconds) {
|
|
|
241
241
|
startIndex = 0;
|
|
242
242
|
} else {
|
|
243
243
|
for(let index = 0; index < pending.length; index++){
|
|
244
|
-
|
|
244
|
+
const sequenceID = pending[index];
|
|
245
|
+
if (sequenceID !== undefined && sequenceID > params.after) {
|
|
245
246
|
startIndex = index;
|
|
246
247
|
break;
|
|
247
248
|
}
|
|
@@ -258,7 +259,7 @@ function isLive(entry, nowSeconds) {
|
|
|
258
259
|
resultMessages.push(asStoredMessage(entry));
|
|
259
260
|
}
|
|
260
261
|
}
|
|
261
|
-
const cursor = resultMessages.
|
|
262
|
+
const cursor = resultMessages.at(-1)?.sequenceID ?? null;
|
|
262
263
|
const result = {
|
|
263
264
|
messages: resultMessages,
|
|
264
265
|
cursor
|
|
@@ -294,7 +295,7 @@ function isLive(entry, nowSeconds) {
|
|
|
294
295
|
return {
|
|
295
296
|
messages,
|
|
296
297
|
head: heads.get(params.topicID) ?? null,
|
|
297
|
-
oldest: log
|
|
298
|
+
oldest: log[0] ?? null
|
|
298
299
|
};
|
|
299
300
|
},
|
|
300
301
|
async trim (params) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kumiai/hub-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"description": "Hub server for Enkaku E2EE group message routing",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"hub",
|
|
@@ -25,19 +25,19 @@
|
|
|
25
25
|
"lib/*"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@enkaku/protocol": "^0.21.
|
|
29
|
-
"@enkaku/server": "^0.21.
|
|
28
|
+
"@enkaku/protocol": "^0.21.3",
|
|
29
|
+
"@enkaku/server": "^0.21.3",
|
|
30
30
|
"@kokuin/token": "^0.5.0",
|
|
31
|
-
"@kumiai/hub-protocol": "^0.
|
|
31
|
+
"@kumiai/hub-protocol": "^0.10.0",
|
|
32
32
|
"@sozai/codec": "^0.4.0",
|
|
33
33
|
"@sozai/event": "^0.1.3",
|
|
34
34
|
"@sozai/log": "^0.3.1"
|
|
35
35
|
},
|
|
36
36
|
"devDependencies": {
|
|
37
|
-
"@enkaku/client": "^0.21.
|
|
38
|
-
"@enkaku/transport": "^0.21.
|
|
39
|
-
"@kumiai/hub-conformance": "^0.
|
|
40
|
-
"@kumiai/hub-wake": "^0.
|
|
37
|
+
"@enkaku/client": "^0.21.3",
|
|
38
|
+
"@enkaku/transport": "^0.21.3",
|
|
39
|
+
"@kumiai/hub-conformance": "^0.10.0",
|
|
40
|
+
"@kumiai/hub-wake": "^0.10.0"
|
|
41
41
|
},
|
|
42
42
|
"publishConfig": {
|
|
43
43
|
"access": "public"
|
|
@@ -45,8 +45,8 @@
|
|
|
45
45
|
"scripts": {
|
|
46
46
|
"build": "pnpm run build:clean && pnpm run build:js && pnpm run build:types",
|
|
47
47
|
"build:clean": "del lib",
|
|
48
|
-
"build:js": "swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
|
|
49
|
-
"build:types": "tsc --emitDeclarationOnly --skipLibCheck",
|
|
48
|
+
"build:js": "del 'lib/**/*.js' && swc src -d ./lib --config-file ../../node_modules/@kigu/dev/swc.json --strip-leading-paths",
|
|
49
|
+
"build:types": "del 'lib/**/*.d.ts' 'lib/**/*.d.ts.map' && tsc --emitDeclarationOnly --skipLibCheck",
|
|
50
50
|
"test": "pnpm run test:types && pnpm run test:unit",
|
|
51
51
|
"test:types": "tsc --noEmit --skipLibCheck -p tsconfig.test.json",
|
|
52
52
|
"test:unit": "vitest run"
|