@enkaku/server 0.12.3 → 0.13.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/lib/access-control.d.ts +8 -1
- package/lib/access-control.d.ts.map +1 -1
- package/lib/access-control.js +31 -5
- package/lib/error.d.ts +10 -0
- package/lib/error.d.ts.map +1 -1
- package/lib/handlers/channel.d.ts.map +1 -1
- package/lib/handlers/channel.js +13 -2
- package/lib/handlers/stream.d.ts.map +1 -1
- package/lib/handlers/stream.js +13 -2
- package/lib/index.d.ts +3 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +3 -1
- package/lib/limits.d.ts +26 -0
- package/lib/limits.d.ts.map +1 -0
- package/lib/limits.js +56 -0
- package/lib/server.d.ts +10 -3
- package/lib/server.d.ts.map +1 -1
- package/lib/server.js +202 -22
- package/lib/types.d.ts +4 -0
- package/lib/types.d.ts.map +1 -1
- package/lib/utils.js +1 -1
- package/package.json +10 -10
package/lib/access-control.d.ts
CHANGED
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
import type { SignedToken } from '@enkaku/token';
|
|
2
|
-
export type
|
|
2
|
+
export type EncryptionPolicy = 'required' | 'optional' | 'none';
|
|
3
|
+
export type ProcedureAccessConfig = {
|
|
4
|
+
allow?: boolean | Array<string>;
|
|
5
|
+
encryption?: EncryptionPolicy;
|
|
6
|
+
};
|
|
7
|
+
export type ProcedureAccessValue = boolean | Array<string> | ProcedureAccessConfig;
|
|
8
|
+
export type ProcedureAccessRecord = Record<string, ProcedureAccessValue>;
|
|
9
|
+
export declare function resolveEncryptionPolicy(procedure: string, record: ProcedureAccessRecord | undefined, globalPolicy: EncryptionPolicy): EncryptionPolicy;
|
|
3
10
|
export type ProcedureAccessPayload = {
|
|
4
11
|
iss: string;
|
|
5
12
|
sub?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"access-control.d.ts","sourceRoot":"","sources":["../src/access-control.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"access-control.d.ts","sourceRoot":"","sources":["../src/access-control.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,eAAe,CAAA;AAEhD,MAAM,MAAM,gBAAgB,GAAG,UAAU,GAAG,UAAU,GAAG,MAAM,CAAA;AAE/D,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,CAAC,EAAE,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAA;IAC/B,UAAU,CAAC,EAAE,gBAAgB,CAAA;CAC9B,CAAA;AAED,MAAM,MAAM,oBAAoB,GAAG,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,GAAG,qBAAqB,CAAA;AAElF,MAAM,MAAM,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,oBAAoB,CAAC,CAAA;AAgBxE,wBAAgB,uBAAuB,CACrC,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,qBAAqB,GAAG,SAAS,EACzC,YAAY,EAAE,gBAAgB,GAC7B,gBAAgB,CAYlB;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,GAAG,EAAE,MAAM,CAAA;IACX,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;IACZ,GAAG,CAAC,EAAE,MAAM,CAAA;CACb,CAAA;AAED,wBAAsB,oBAAoB,CACxC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,WAAW,CAAC,sBAAsB,CAAC,EAC1C,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CAkCf;AAED,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,qBAAqB,EAC7B,KAAK,EAAE,WAAW,EAClB,MAAM,CAAC,EAAE,MAAM,GACd,OAAO,CAAC,IAAI,CAAC,CA4Bf"}
|
package/lib/access-control.js
CHANGED
|
@@ -1,23 +1,49 @@
|
|
|
1
1
|
import { assertNonExpired, checkCapability, hasPartsMatch } from '@enkaku/capability';
|
|
2
|
+
function getAllowValue(access) {
|
|
3
|
+
if (typeof access === 'boolean' || Array.isArray(access)) {
|
|
4
|
+
return access;
|
|
5
|
+
}
|
|
6
|
+
return access.allow ?? false;
|
|
7
|
+
}
|
|
8
|
+
function getEncryptionPolicy(access) {
|
|
9
|
+
if (typeof access === 'boolean' || Array.isArray(access)) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
return access.encryption;
|
|
13
|
+
}
|
|
14
|
+
export function resolveEncryptionPolicy(procedure, record, globalPolicy) {
|
|
15
|
+
if (record != null) {
|
|
16
|
+
for (const [pattern, accessValue] of Object.entries(record)){
|
|
17
|
+
if (hasPartsMatch(procedure, pattern)) {
|
|
18
|
+
const procedurePolicy = getEncryptionPolicy(accessValue);
|
|
19
|
+
if (procedurePolicy != null) {
|
|
20
|
+
return procedurePolicy;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return globalPolicy;
|
|
26
|
+
}
|
|
2
27
|
export async function checkProcedureAccess(serverID, record, token, atTime) {
|
|
3
28
|
const payload = token.payload;
|
|
4
29
|
if (payload.prc == null) {
|
|
5
30
|
throw new Error('No procedure to check');
|
|
6
31
|
}
|
|
7
|
-
for (const [procedure,
|
|
32
|
+
for (const [procedure, accessValue] of Object.entries(record)){
|
|
8
33
|
if (hasPartsMatch(payload.prc, procedure)) {
|
|
9
|
-
|
|
34
|
+
const allow = getAllowValue(accessValue);
|
|
35
|
+
if (allow === true) {
|
|
10
36
|
// Procedure can be publicly accessed
|
|
11
37
|
return;
|
|
12
38
|
}
|
|
13
|
-
if (
|
|
39
|
+
if (allow === false) {
|
|
14
40
|
continue;
|
|
15
41
|
}
|
|
16
|
-
if (
|
|
42
|
+
if (allow.includes(payload.iss)) {
|
|
17
43
|
// Issuer is allowed directly
|
|
18
44
|
return;
|
|
19
45
|
}
|
|
20
|
-
if (payload.sub == null || !
|
|
46
|
+
if (payload.sub == null || !allow.includes(payload.sub)) {
|
|
21
47
|
continue;
|
|
22
48
|
}
|
|
23
49
|
try {
|
package/lib/error.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
1
|
import type { ErrorReplyPayload } from '@enkaku/protocol';
|
|
2
|
+
/**
|
|
3
|
+
* Error codes:
|
|
4
|
+
* - EK01: Handler execution failed
|
|
5
|
+
* - EK02: Access denied (authorization failure)
|
|
6
|
+
* - EK03: Server controller limit reached
|
|
7
|
+
* - EK04: Server handler concurrency limit reached
|
|
8
|
+
* - EK05: Request timeout (controller expired)
|
|
9
|
+
* - EK06: Message exceeds maximum size
|
|
10
|
+
* - EK07: Encryption required but message is not encrypted
|
|
11
|
+
*/
|
|
2
12
|
export type HandlerErrorParams<Code extends string = string, Data extends Record<string, unknown> = Record<string, unknown>> = {
|
|
3
13
|
cause?: unknown;
|
|
4
14
|
code: Code;
|
package/lib/error.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD,MAAM,MAAM,kBAAkB,CAC5B,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC5D;IACF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,qBAAa,YAAY,CACvB,IAAI,SAAS,MAAM,EACnB,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAC9D,SAAQ,KAAK;;IACb,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7F,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,GACrC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC;gBAWf,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC;IAOlD,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC;CAStD"}
|
|
1
|
+
{"version":3,"file":"error.d.ts","sourceRoot":"","sources":["../src/error.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAA;AAEzD;;;;;;;;;GASG;AAEH,MAAM,MAAM,kBAAkB,CAC5B,IAAI,SAAS,MAAM,GAAG,MAAM,EAC5B,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,IAC5D;IACF,KAAK,CAAC,EAAE,OAAO,CAAA;IACf,IAAI,EAAE,IAAI,CAAA;IACV,IAAI,CAAC,EAAE,IAAI,CAAA;IACX,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB,CAAA;AAED,qBAAa,YAAY,CACvB,IAAI,SAAS,MAAM,EACnB,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAC9D,SAAQ,KAAK;;IACb,MAAM,CAAC,IAAI,CAAC,IAAI,SAAS,MAAM,EAAE,IAAI,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7F,KAAK,EAAE,OAAO,EACd,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC,GACrC,YAAY,CAAC,IAAI,EAAE,IAAI,CAAC;gBAWf,MAAM,EAAE,kBAAkB,CAAC,IAAI,EAAE,IAAI,CAAC;IAOlD,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,IAAI,IAAI,IAAI,IAAI,CAEf;IAED,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,iBAAiB,CAAC,IAAI,EAAE,IAAI,CAAC;CAStD"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/handlers/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EACnB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAGV,cAAc,EAGf,MAAM,aAAa,CAAA;AAGpB,MAAM,MAAM,gBAAgB,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAEnE,wBAAgB,aAAa,CAC3B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EAEzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAC7B,GAAG,EAAE,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,GACzC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../../src/handlers/channel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EACnB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAGV,cAAc,EAGf,MAAM,aAAa,CAAA;AAGpB,MAAM,MAAM,gBAAgB,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,gBAAgB,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAEnE,wBAAgB,aAAa,CAC3B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EAEzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAC7B,GAAG,EAAE,gBAAgB,CAAC,QAAQ,EAAE,SAAS,CAAC,GACzC,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAsEvB"}
|
package/lib/handlers/channel.js
CHANGED
|
@@ -46,6 +46,17 @@ export function handleChannel(ctx, msg) {
|
|
|
46
46
|
signal: controller.signal,
|
|
47
47
|
writable: receiveStream.writable
|
|
48
48
|
};
|
|
49
|
-
//
|
|
50
|
-
return
|
|
49
|
+
// Wrap execution to ensure stream cleanup on handler crash
|
|
50
|
+
return (async ()=>{
|
|
51
|
+
try {
|
|
52
|
+
// @ts-expect-error context and handler types
|
|
53
|
+
await executeHandler(ctx, msg.payload, ()=>handler(handlerContext));
|
|
54
|
+
} finally{
|
|
55
|
+
try {
|
|
56
|
+
await receiveStream.writable.close();
|
|
57
|
+
} catch {
|
|
58
|
+
// Stream may already be closed
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
})();
|
|
51
62
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/handlers/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EACb,kBAAkB,EAClB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAAE,cAAc,EAA8B,MAAM,aAAa,CAAA;AAG7E,MAAM,MAAM,eAAe,CACzB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAElE,wBAAgB,YAAY,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EACzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../src/handlers/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAEV,aAAa,EACb,kBAAkB,EAClB,eAAe,EAChB,MAAM,kBAAkB,CAAA;AAGzB,OAAO,KAAK,EAAE,cAAc,EAA8B,MAAM,aAAa,CAAA;AAG7E,MAAM,MAAM,eAAe,CACzB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,GAAG,MAAM,QAAQ,GAAG,MAAM,IACjE,aAAa,CAAC,eAAe,CAAC,SAAS,EAAE,QAAQ,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;AAElE,wBAAgB,YAAY,CAC1B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,EACzC,GAAG,EAAE,cAAc,CAAC,QAAQ,CAAC,EAAE,GAAG,EAAE,eAAe,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC,IAAI,CAAC,CAoDjG"}
|
package/lib/handlers/stream.js
CHANGED
|
@@ -32,6 +32,17 @@ export function handleStream(ctx, msg) {
|
|
|
32
32
|
signal: controller.signal,
|
|
33
33
|
writable: receiveStream.writable
|
|
34
34
|
};
|
|
35
|
-
//
|
|
36
|
-
return
|
|
35
|
+
// Wrap execution to ensure stream cleanup on handler crash
|
|
36
|
+
return (async ()=>{
|
|
37
|
+
try {
|
|
38
|
+
// @ts-expect-error context and handler types
|
|
39
|
+
await executeHandler(ctx, msg.payload, ()=>handler(handlerContext));
|
|
40
|
+
} finally{
|
|
41
|
+
try {
|
|
42
|
+
await receiveStream.writable.close();
|
|
43
|
+
} catch {
|
|
44
|
+
// Stream may already be closed
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
})();
|
|
37
48
|
}
|
package/lib/index.d.ts
CHANGED
|
@@ -9,7 +9,9 @@
|
|
|
9
9
|
*
|
|
10
10
|
* @module server
|
|
11
11
|
*/
|
|
12
|
-
export type { ProcedureAccessRecord } from './access-control.js';
|
|
12
|
+
export type { EncryptionPolicy, ProcedureAccessConfig, ProcedureAccessRecord, ProcedureAccessValue, } from './access-control.js';
|
|
13
|
+
export { resolveEncryptionPolicy } from './access-control.js';
|
|
14
|
+
export { createResourceLimiter, DEFAULT_RESOURCE_LIMITS, type ResourceLimiter, type ResourceLimits, } from './limits.js';
|
|
13
15
|
export { type ServeParams, Server, type ServerParams, serve } from './server.js';
|
|
14
16
|
export type { ChannelHandler, ChannelHandlerContext, EventHandler, EventHandlerContext, HandlerReturn, ProcedureHandlers, RequestHandler, RequestHandlerContext, ServerEmitter, ServerEvents, StreamHandler, StreamHandlerContext, } from './types.js';
|
|
15
17
|
//# sourceMappingURL=index.d.ts.map
|
package/lib/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,EACV,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,oBAAoB,GACrB,MAAM,qBAAqB,CAAA;AAC5B,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EACL,qBAAqB,EACrB,uBAAuB,EACvB,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,EAAE,KAAK,YAAY,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAChF,YAAY,EACV,cAAc,EACd,qBAAqB,EACrB,YAAY,EACZ,mBAAmB,EACnB,aAAa,EACb,iBAAiB,EACjB,cAAc,EACd,qBAAqB,EACrB,aAAa,EACb,YAAY,EACZ,aAAa,EACb,oBAAoB,GACrB,MAAM,YAAY,CAAA"}
|
package/lib/index.js
CHANGED
|
@@ -8,4 +8,6 @@
|
|
|
8
8
|
* ```
|
|
9
9
|
*
|
|
10
10
|
* @module server
|
|
11
|
-
*/ export {
|
|
11
|
+
*/ export { resolveEncryptionPolicy } from './access-control.js';
|
|
12
|
+
export { createResourceLimiter, DEFAULT_RESOURCE_LIMITS } from './limits.js';
|
|
13
|
+
export { Server, serve } from './server.js';
|
package/lib/limits.d.ts
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export type ResourceLimits = {
|
|
2
|
+
/** Maximum number of concurrent controllers (in-flight requests). Default: 10000 */
|
|
3
|
+
maxControllers: number;
|
|
4
|
+
/** Maximum number of concurrent handler executions. Default: 100 */
|
|
5
|
+
maxConcurrentHandlers: number;
|
|
6
|
+
/** Controller timeout in milliseconds. Default: 300000 (5 min) */
|
|
7
|
+
controllerTimeoutMs: number;
|
|
8
|
+
/** Cleanup timeout in milliseconds when disposing. Default: 30000 (30 sec) */
|
|
9
|
+
cleanupTimeoutMs: number;
|
|
10
|
+
/** Maximum size in bytes for any individual message payload. Default: 10485760 (10 MB) */
|
|
11
|
+
maxMessageSize: number;
|
|
12
|
+
};
|
|
13
|
+
export declare const DEFAULT_RESOURCE_LIMITS: ResourceLimits;
|
|
14
|
+
export type ResourceLimiter = {
|
|
15
|
+
limits: ResourceLimits;
|
|
16
|
+
controllerCount: number;
|
|
17
|
+
activeHandlers: number;
|
|
18
|
+
canAddController: () => boolean;
|
|
19
|
+
addController: (rid: string) => void;
|
|
20
|
+
removeController: (rid: string) => void;
|
|
21
|
+
getExpiredControllers: () => Array<string>;
|
|
22
|
+
acquireHandler: () => boolean;
|
|
23
|
+
releaseHandler: () => void;
|
|
24
|
+
};
|
|
25
|
+
export declare function createResourceLimiter(options?: Partial<ResourceLimits>): ResourceLimiter;
|
|
26
|
+
//# sourceMappingURL=limits.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"limits.d.ts","sourceRoot":"","sources":["../src/limits.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,cAAc,GAAG;IAC3B,oFAAoF;IACpF,cAAc,EAAE,MAAM,CAAA;IACtB,oEAAoE;IACpE,qBAAqB,EAAE,MAAM,CAAA;IAC7B,kEAAkE;IAClE,mBAAmB,EAAE,MAAM,CAAA;IAC3B,8EAA8E;IAC9E,gBAAgB,EAAE,MAAM,CAAA;IACxB,0FAA0F;IAC1F,cAAc,EAAE,MAAM,CAAA;CACvB,CAAA;AAED,eAAO,MAAM,uBAAuB,EAAE,cAMrC,CAAA;AAED,MAAM,MAAM,eAAe,GAAG;IAC5B,MAAM,EAAE,cAAc,CAAA;IACtB,eAAe,EAAE,MAAM,CAAA;IACvB,cAAc,EAAE,MAAM,CAAA;IACtB,gBAAgB,EAAE,MAAM,OAAO,CAAA;IAC/B,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACpC,gBAAgB,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,qBAAqB,EAAE,MAAM,KAAK,CAAC,MAAM,CAAC,CAAA;IAC1C,cAAc,EAAE,MAAM,OAAO,CAAA;IAC7B,cAAc,EAAE,MAAM,IAAI,CAAA;CAC3B,CAAA;AAED,wBAAgB,qBAAqB,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,GAAG,eAAe,CAiDxF"}
|
package/lib/limits.js
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
export const DEFAULT_RESOURCE_LIMITS = {
|
|
2
|
+
maxControllers: 10000,
|
|
3
|
+
maxConcurrentHandlers: 100,
|
|
4
|
+
controllerTimeoutMs: 300000,
|
|
5
|
+
cleanupTimeoutMs: 30000,
|
|
6
|
+
maxMessageSize: 10485760
|
|
7
|
+
};
|
|
8
|
+
export function createResourceLimiter(options) {
|
|
9
|
+
const limits = {
|
|
10
|
+
...DEFAULT_RESOURCE_LIMITS,
|
|
11
|
+
...options
|
|
12
|
+
};
|
|
13
|
+
const controllers = new Map() // rid -> timestamp
|
|
14
|
+
;
|
|
15
|
+
let handlerCount = 0;
|
|
16
|
+
return {
|
|
17
|
+
limits,
|
|
18
|
+
get controllerCount () {
|
|
19
|
+
return controllers.size;
|
|
20
|
+
},
|
|
21
|
+
get activeHandlers () {
|
|
22
|
+
return handlerCount;
|
|
23
|
+
},
|
|
24
|
+
canAddController () {
|
|
25
|
+
return controllers.size < limits.maxControllers;
|
|
26
|
+
},
|
|
27
|
+
addController (rid) {
|
|
28
|
+
controllers.set(rid, Date.now());
|
|
29
|
+
},
|
|
30
|
+
removeController (rid) {
|
|
31
|
+
controllers.delete(rid);
|
|
32
|
+
},
|
|
33
|
+
getExpiredControllers () {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
const expired = [];
|
|
36
|
+
for (const [rid, timestamp] of controllers){
|
|
37
|
+
if (now - timestamp > limits.controllerTimeoutMs) {
|
|
38
|
+
expired.push(rid);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return expired;
|
|
42
|
+
},
|
|
43
|
+
acquireHandler () {
|
|
44
|
+
if (handlerCount >= limits.maxConcurrentHandlers) {
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
handlerCount++;
|
|
48
|
+
return true;
|
|
49
|
+
},
|
|
50
|
+
releaseHandler () {
|
|
51
|
+
if (handlerCount > 0) {
|
|
52
|
+
handlerCount--;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
}
|
package/lib/server.d.ts
CHANGED
|
@@ -2,9 +2,11 @@ import { Disposer } from '@enkaku/async';
|
|
|
2
2
|
import { type Logger } from '@enkaku/log';
|
|
3
3
|
import { type AnyClientMessageOf, type ProtocolDefinition, type ServerTransportOf } from '@enkaku/protocol';
|
|
4
4
|
import { type Validator } from '@enkaku/schema';
|
|
5
|
-
import { type
|
|
5
|
+
import { type Identity } from '@enkaku/token';
|
|
6
|
+
import { type EncryptionPolicy, type ProcedureAccessRecord } from './access-control.js';
|
|
7
|
+
import { type ResourceLimiter, type ResourceLimits } from './limits.js';
|
|
6
8
|
import type { ProcedureHandlers, ServerEmitter } from './types.js';
|
|
7
|
-
export type AccessControlParams = {
|
|
9
|
+
export type AccessControlParams = ({
|
|
8
10
|
public: true;
|
|
9
11
|
serverID?: string;
|
|
10
12
|
access?: ProcedureAccessRecord;
|
|
@@ -12,10 +14,13 @@ export type AccessControlParams = {
|
|
|
12
14
|
public: false;
|
|
13
15
|
serverID: string;
|
|
14
16
|
access: ProcedureAccessRecord;
|
|
17
|
+
}) & {
|
|
18
|
+
encryptionPolicy?: EncryptionPolicy;
|
|
15
19
|
};
|
|
16
20
|
export type HandleMessagesParams<Protocol extends ProtocolDefinition> = AccessControlParams & {
|
|
17
21
|
events: ServerEmitter;
|
|
18
22
|
handlers: ProcedureHandlers<Protocol>;
|
|
23
|
+
limiter: ResourceLimiter;
|
|
19
24
|
logger: Logger;
|
|
20
25
|
signal: AbortSignal;
|
|
21
26
|
transport: ServerTransportOf<Protocol>;
|
|
@@ -23,8 +28,10 @@ export type HandleMessagesParams<Protocol extends ProtocolDefinition> = AccessCo
|
|
|
23
28
|
};
|
|
24
29
|
export type ServerParams<Protocol extends ProtocolDefinition> = {
|
|
25
30
|
access?: ProcedureAccessRecord;
|
|
31
|
+
encryptionPolicy?: EncryptionPolicy;
|
|
26
32
|
handlers: ProcedureHandlers<Protocol>;
|
|
27
|
-
|
|
33
|
+
identity?: Identity;
|
|
34
|
+
limits?: Partial<ResourceLimits>;
|
|
28
35
|
logger?: Logger;
|
|
29
36
|
protocol?: Protocol;
|
|
30
37
|
public?: boolean;
|
package/lib/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAuB,QAAQ,EAAE,MAAM,eAAe,CAAA;AAE7D,OAAO,EAAmB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAA;AAC1D,OAAO,EACL,KAAK,kBAAkB,EAGvB,KAAK,kBAAkB,EACvB,KAAK,iBAAiB,EACvB,MAAM,kBAAkB,CAAA;AACzB,OAAO,EAIL,KAAK,SAAS,EACf,MAAM,gBAAgB,CAAA;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/lib/server.js
CHANGED
|
@@ -4,14 +4,15 @@ import { getEnkakuLogger } from '@enkaku/log';
|
|
|
4
4
|
import { createClientMessageSchema } from '@enkaku/protocol';
|
|
5
5
|
import { createValidator, ValidationError } from '@enkaku/schema';
|
|
6
6
|
import { createUnsignedToken, isSignedToken } from '@enkaku/token';
|
|
7
|
-
import { checkClientToken } from './access-control.js';
|
|
7
|
+
import { checkClientToken, resolveEncryptionPolicy } from './access-control.js';
|
|
8
8
|
import { HandlerError } from './error.js';
|
|
9
9
|
import { handleChannel } from './handlers/channel.js';
|
|
10
10
|
import { handleEvent } from './handlers/event.js';
|
|
11
11
|
import { handleRequest } from './handlers/request.js';
|
|
12
12
|
import { handleStream } from './handlers/stream.js';
|
|
13
|
+
import { createResourceLimiter } from './limits.js';
|
|
13
14
|
async function handleMessages(params) {
|
|
14
|
-
const { events, handlers, logger, signal, transport, validator } = params;
|
|
15
|
+
const { events, handlers, limiter, logger, signal, transport, validator } = params;
|
|
15
16
|
const controllers = Object.create(null);
|
|
16
17
|
const context = {
|
|
17
18
|
controllers,
|
|
@@ -21,8 +22,34 @@ async function handleMessages(params) {
|
|
|
21
22
|
send: (payload)=>transport.write(createUnsignedToken(payload))
|
|
22
23
|
};
|
|
23
24
|
const running = Object.create(null);
|
|
25
|
+
const encoder = new TextEncoder();
|
|
26
|
+
// Periodic cleanup of expired controllers
|
|
27
|
+
const cleanupInterval = setInterval(()=>{
|
|
28
|
+
const expired = limiter.getExpiredControllers();
|
|
29
|
+
for (const rid of expired){
|
|
30
|
+
const controller = controllers[rid];
|
|
31
|
+
if (controller != null) {
|
|
32
|
+
controller.abort('Timeout');
|
|
33
|
+
const error = new HandlerError({
|
|
34
|
+
code: 'EK05',
|
|
35
|
+
message: 'Request timeout'
|
|
36
|
+
});
|
|
37
|
+
context.send(error.toPayload(rid));
|
|
38
|
+
events.emit('handlerTimeout', {
|
|
39
|
+
rid
|
|
40
|
+
});
|
|
41
|
+
limiter.removeController(rid);
|
|
42
|
+
limiter.releaseHandler();
|
|
43
|
+
delete controllers[rid];
|
|
44
|
+
delete running[rid];
|
|
45
|
+
} else {
|
|
46
|
+
limiter.removeController(rid);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}, Math.min(limiter.limits.controllerTimeoutMs, 10000));
|
|
24
50
|
const disposer = new Disposer({
|
|
25
51
|
dispose: async ()=>{
|
|
52
|
+
clearInterval(cleanupInterval);
|
|
26
53
|
const interruption = new DisposeInterruption();
|
|
27
54
|
// Abort all currently running handlers
|
|
28
55
|
for (const controller of Object.values(controllers)){
|
|
@@ -54,8 +81,43 @@ async function handleMessages(params) {
|
|
|
54
81
|
return result.value;
|
|
55
82
|
} : (message)=>message;
|
|
56
83
|
function processHandler(message, handle) {
|
|
84
|
+
const rid = message.payload.typ === 'event' ? Math.random().toString(36).slice(2) : message.payload.rid;
|
|
85
|
+
// Check controller limit
|
|
86
|
+
if (!limiter.canAddController()) {
|
|
87
|
+
const error = new HandlerError({
|
|
88
|
+
code: 'EK03',
|
|
89
|
+
message: 'Server controller limit reached'
|
|
90
|
+
});
|
|
91
|
+
if (message.payload.typ !== 'event') {
|
|
92
|
+
context.send(error.toPayload(rid));
|
|
93
|
+
}
|
|
94
|
+
events.emit('handlerError', {
|
|
95
|
+
error,
|
|
96
|
+
payload: message.payload
|
|
97
|
+
});
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
// Check handler concurrency (synchronous fast path)
|
|
101
|
+
if (limiter.activeHandlers >= limiter.limits.maxConcurrentHandlers) {
|
|
102
|
+
const error = new HandlerError({
|
|
103
|
+
code: 'EK04',
|
|
104
|
+
message: 'Server handler limit reached'
|
|
105
|
+
});
|
|
106
|
+
if (message.payload.typ !== 'event') {
|
|
107
|
+
context.send(error.toPayload(rid));
|
|
108
|
+
}
|
|
109
|
+
events.emit('handlerError', {
|
|
110
|
+
error,
|
|
111
|
+
payload: message.payload
|
|
112
|
+
});
|
|
113
|
+
return;
|
|
114
|
+
}
|
|
115
|
+
limiter.addController(rid);
|
|
116
|
+
limiter.acquireHandler();
|
|
57
117
|
const returned = handle();
|
|
58
118
|
if (returned instanceof Error) {
|
|
119
|
+
limiter.removeController(rid);
|
|
120
|
+
limiter.releaseHandler();
|
|
59
121
|
events.emit('handlerError', {
|
|
60
122
|
error: HandlerError.from(returned, {
|
|
61
123
|
code: 'EK01'
|
|
@@ -63,14 +125,52 @@ async function handleMessages(params) {
|
|
|
63
125
|
payload: message.payload
|
|
64
126
|
});
|
|
65
127
|
} else {
|
|
66
|
-
|
|
67
|
-
running[id] = returned;
|
|
128
|
+
running[rid] = returned;
|
|
68
129
|
returned.then(()=>{
|
|
69
|
-
|
|
130
|
+
// Guard against double-release if timeout cleanup already handled this rid
|
|
131
|
+
if (running[rid] === returned) {
|
|
132
|
+
limiter.removeController(rid);
|
|
133
|
+
limiter.releaseHandler();
|
|
134
|
+
delete running[rid];
|
|
135
|
+
}
|
|
70
136
|
});
|
|
71
137
|
}
|
|
72
138
|
}
|
|
73
|
-
|
|
139
|
+
function checkMessageEncryption(message) {
|
|
140
|
+
const globalPolicy = params.encryptionPolicy ?? 'none';
|
|
141
|
+
if (globalPolicy === 'none') {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
const procedure = message.payload.prc;
|
|
145
|
+
const effectivePolicy = procedure != null ? resolveEncryptionPolicy(procedure, params.access, globalPolicy) : globalPolicy;
|
|
146
|
+
if (effectivePolicy !== 'required') {
|
|
147
|
+
return true;
|
|
148
|
+
}
|
|
149
|
+
// Detect if message was encrypted: jwe-in-jws mode has a 'jwe' field in the payload
|
|
150
|
+
const payload = message.payload;
|
|
151
|
+
return 'jwe' in payload && typeof payload.jwe === 'string';
|
|
152
|
+
}
|
|
153
|
+
function handleEncryptionViolation(message) {
|
|
154
|
+
const error = new HandlerError({
|
|
155
|
+
code: 'EK07',
|
|
156
|
+
message: 'Encryption required but message is not encrypted'
|
|
157
|
+
});
|
|
158
|
+
if (message.payload.typ === 'event') {
|
|
159
|
+
events.emit('handlerError', {
|
|
160
|
+
error,
|
|
161
|
+
payload: message.payload
|
|
162
|
+
});
|
|
163
|
+
} else {
|
|
164
|
+
context.send(error.toPayload(message.payload.rid));
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
const process = params.public ? (message, handle)=>{
|
|
168
|
+
if (!checkMessageEncryption(message)) {
|
|
169
|
+
handleEncryptionViolation(message);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
processHandler(message, handle);
|
|
173
|
+
} : async (message, handle)=>{
|
|
74
174
|
try {
|
|
75
175
|
if (!params.public) {
|
|
76
176
|
if (!isSignedToken(message)) {
|
|
@@ -85,6 +185,10 @@ async function handleMessages(params) {
|
|
|
85
185
|
message: cause.message ?? 'Access denied'
|
|
86
186
|
});
|
|
87
187
|
if (message.payload.typ === 'event') {
|
|
188
|
+
events.emit('eventAuthError', {
|
|
189
|
+
error,
|
|
190
|
+
payload: message.payload
|
|
191
|
+
});
|
|
88
192
|
events.emit('handlerError', {
|
|
89
193
|
error,
|
|
90
194
|
payload: message.payload
|
|
@@ -94,6 +198,10 @@ async function handleMessages(params) {
|
|
|
94
198
|
}
|
|
95
199
|
return;
|
|
96
200
|
}
|
|
201
|
+
if (!checkMessageEncryption(message)) {
|
|
202
|
+
handleEncryptionViolation(message);
|
|
203
|
+
return;
|
|
204
|
+
}
|
|
97
205
|
processHandler(message, handle);
|
|
98
206
|
};
|
|
99
207
|
async function handleNext() {
|
|
@@ -104,6 +212,22 @@ async function handleMessages(params) {
|
|
|
104
212
|
}
|
|
105
213
|
const msg = processMessage(next.value);
|
|
106
214
|
if (msg != null) {
|
|
215
|
+
const msgSize = encoder.encode(JSON.stringify(msg.payload)).byteLength;
|
|
216
|
+
if (msgSize > limiter.limits.maxMessageSize) {
|
|
217
|
+
const error = new HandlerError({
|
|
218
|
+
code: 'EK06',
|
|
219
|
+
message: 'Message exceeds maximum size'
|
|
220
|
+
});
|
|
221
|
+
if ('rid' in msg.payload && msg.payload.rid != null) {
|
|
222
|
+
context.send(error.toPayload(msg.payload.rid));
|
|
223
|
+
}
|
|
224
|
+
events.emit('handlerError', {
|
|
225
|
+
error,
|
|
226
|
+
payload: msg.payload
|
|
227
|
+
});
|
|
228
|
+
handleNext();
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
107
231
|
switch(msg.payload.typ){
|
|
108
232
|
case 'abort':
|
|
109
233
|
controllers[msg.payload.rid]?.abort(msg.payload.rsn);
|
|
@@ -129,7 +253,35 @@ async function handleMessages(params) {
|
|
|
129
253
|
case 'send':
|
|
130
254
|
{
|
|
131
255
|
const controller = controllers[msg.payload.rid];
|
|
132
|
-
controller
|
|
256
|
+
if (controller == null) {
|
|
257
|
+
logger.debug('received send for unknown channel {rid}', {
|
|
258
|
+
rid: msg.payload.rid
|
|
259
|
+
});
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
// In non-public mode, validate send messages
|
|
263
|
+
if (!params.public) {
|
|
264
|
+
if (!isSignedToken(msg)) {
|
|
265
|
+
const error = new HandlerError({
|
|
266
|
+
code: 'EK02',
|
|
267
|
+
message: 'Channel send message must be signed'
|
|
268
|
+
});
|
|
269
|
+
context.send(error.toPayload(msg.payload.rid));
|
|
270
|
+
break;
|
|
271
|
+
}
|
|
272
|
+
try {
|
|
273
|
+
await checkClientToken(params.serverID, params.access, msg);
|
|
274
|
+
} catch (cause) {
|
|
275
|
+
const error = new HandlerError({
|
|
276
|
+
cause,
|
|
277
|
+
code: 'EK02',
|
|
278
|
+
message: cause.message ?? 'Send authorization denied'
|
|
279
|
+
});
|
|
280
|
+
context.send(error.toPayload(msg.payload.rid));
|
|
281
|
+
break;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
controller.writer.write(msg.payload.val);
|
|
133
285
|
break;
|
|
134
286
|
}
|
|
135
287
|
case 'stream':
|
|
@@ -151,6 +303,7 @@ export class Server extends Disposer {
|
|
|
151
303
|
#events;
|
|
152
304
|
#handlers;
|
|
153
305
|
#handling = [];
|
|
306
|
+
#limiter;
|
|
154
307
|
#logger;
|
|
155
308
|
#validator;
|
|
156
309
|
constructor(params){
|
|
@@ -158,40 +311,63 @@ export class Server extends Disposer {
|
|
|
158
311
|
dispose: async ()=>{
|
|
159
312
|
// Signal messages handler to stop execution and run cleanup logic
|
|
160
313
|
this.#abortController.abort();
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
314
|
+
const cleanupTimeout = this.#limiter.limits.cleanupTimeoutMs;
|
|
315
|
+
const timeoutPromise = new Promise((resolve)=>{
|
|
316
|
+
setTimeout(resolve, cleanupTimeout);
|
|
317
|
+
});
|
|
318
|
+
// Race between graceful cleanup and timeout
|
|
319
|
+
const gracefulDone = await Promise.race([
|
|
320
|
+
Promise.all(this.#handling.map(async (handling)=>{
|
|
321
|
+
// Wait until all handlers are done - they might still need to flush messages to the transport
|
|
322
|
+
await handling.done;
|
|
323
|
+
// Dispose transport
|
|
324
|
+
await handling.transport.dispose();
|
|
325
|
+
})).then(()=>true),
|
|
326
|
+
timeoutPromise.then(()=>false)
|
|
327
|
+
]);
|
|
328
|
+
// Force dispose any remaining transports only if timed out
|
|
329
|
+
if (!gracefulDone) {
|
|
330
|
+
for (const handling of this.#handling){
|
|
331
|
+
try {
|
|
332
|
+
await handling.transport.dispose();
|
|
333
|
+
} catch {
|
|
334
|
+
// Ignore errors during forced cleanup
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
168
338
|
},
|
|
169
339
|
signal: params.signal
|
|
170
340
|
});
|
|
171
341
|
this.#abortController = new AbortController();
|
|
172
342
|
this.#events = new EventEmitter();
|
|
173
343
|
this.#handlers = params.handlers;
|
|
344
|
+
const serverID = params.identity?.id;
|
|
174
345
|
this.#logger = params.logger ?? getEnkakuLogger('server', {
|
|
175
|
-
serverID:
|
|
346
|
+
serverID: serverID ?? crypto.randomUUID()
|
|
176
347
|
});
|
|
177
|
-
if (
|
|
348
|
+
if (serverID == null) {
|
|
178
349
|
if (params.public) {
|
|
179
350
|
this.#accessControl = {
|
|
180
351
|
public: true,
|
|
181
|
-
access: params.access
|
|
352
|
+
access: params.access,
|
|
353
|
+
encryptionPolicy: params.encryptionPolicy
|
|
182
354
|
};
|
|
183
355
|
} else {
|
|
184
|
-
throw new Error('Invalid server parameters: either the server "
|
|
356
|
+
throw new Error('Invalid server parameters: either the server "identity" must be provided or the "public" parameter must be set to true');
|
|
185
357
|
}
|
|
186
358
|
} else {
|
|
187
359
|
this.#accessControl = {
|
|
188
360
|
public: !!params.public,
|
|
189
|
-
serverID
|
|
190
|
-
access: params.access ?? {}
|
|
361
|
+
serverID,
|
|
362
|
+
access: params.access ?? {},
|
|
363
|
+
encryptionPolicy: params.encryptionPolicy
|
|
191
364
|
};
|
|
192
365
|
}
|
|
366
|
+
this.#limiter = createResourceLimiter(params.limits);
|
|
193
367
|
if (params.protocol != null) {
|
|
194
368
|
this.#validator = createValidator(createClientMessageSchema(params.protocol));
|
|
369
|
+
} else {
|
|
370
|
+
this.#logger.warn('No protocol provided: message validation is disabled. Pass a protocol definition to enable runtime type checking.');
|
|
195
371
|
}
|
|
196
372
|
for (const transport of params.transports ?? []){
|
|
197
373
|
this.handle(transport);
|
|
@@ -206,11 +382,13 @@ export class Server extends Disposer {
|
|
|
206
382
|
const logger = options.logger ?? this.#logger.getChild('handler').with({
|
|
207
383
|
transportID: crypto.randomUUID()
|
|
208
384
|
});
|
|
385
|
+
const encryptionPolicy = this.#accessControl.encryptionPolicy;
|
|
209
386
|
let accessControl;
|
|
210
387
|
if (publicAccess) {
|
|
211
388
|
accessControl = {
|
|
212
389
|
public: true,
|
|
213
|
-
access
|
|
390
|
+
access,
|
|
391
|
+
encryptionPolicy
|
|
214
392
|
};
|
|
215
393
|
} else {
|
|
216
394
|
const serverID = this.#accessControl.serverID;
|
|
@@ -220,12 +398,14 @@ export class Server extends Disposer {
|
|
|
220
398
|
accessControl = {
|
|
221
399
|
public: false,
|
|
222
400
|
serverID,
|
|
223
|
-
access
|
|
401
|
+
access,
|
|
402
|
+
encryptionPolicy
|
|
224
403
|
};
|
|
225
404
|
}
|
|
226
405
|
const done = handleMessages({
|
|
227
406
|
events: this.#events,
|
|
228
407
|
handlers: this.#handlers,
|
|
408
|
+
limiter: this.#limiter,
|
|
229
409
|
logger,
|
|
230
410
|
signal: this.#abortController.signal,
|
|
231
411
|
transport,
|
package/lib/types.d.ts
CHANGED
|
@@ -36,6 +36,10 @@ export type ReceiveType<Protocol extends ProtocolDefinition, Procedure extends k
|
|
|
36
36
|
export type ResultType<Protocol extends ProtocolDefinition, Procedure extends keyof Protocol & string> = Protocol[Procedure] extends AnyRequestProcedureDefinition ? DataOf<Protocol[Procedure]['result']> : never;
|
|
37
37
|
export type SendType<Protocol extends ProtocolDefinition, Procedure extends keyof Protocol & string> = Protocol[Procedure] extends ChannelProcedureDefinition ? DataOf<Protocol[Procedure]['send']> : never;
|
|
38
38
|
export type ServerEvents = {
|
|
39
|
+
eventAuthError: {
|
|
40
|
+
error: HandlerError<string>;
|
|
41
|
+
payload: Record<string, unknown>;
|
|
42
|
+
};
|
|
39
43
|
handlerAbort: {
|
|
40
44
|
rid: string;
|
|
41
45
|
};
|
package/lib/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/lib/utils.js
CHANGED
|
@@ -24,7 +24,7 @@ export async function executeHandler(context, payload, execute) {
|
|
|
24
24
|
} catch (cause) {
|
|
25
25
|
const error = HandlerError.from(cause, {
|
|
26
26
|
code: 'EK01',
|
|
27
|
-
message:
|
|
27
|
+
message: 'Handler execution failed'
|
|
28
28
|
});
|
|
29
29
|
if (canSend(controller.signal)) {
|
|
30
30
|
context.logger.trace('send error to {type} {procedure} with ID {rid}', {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@enkaku/server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"homepage": "https://enkaku.dev",
|
|
6
6
|
"description": "Server logic for Enkaku RPC",
|
|
@@ -25,17 +25,17 @@
|
|
|
25
25
|
],
|
|
26
26
|
"sideEffects": false,
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@enkaku/
|
|
29
|
-
"@enkaku/
|
|
30
|
-
"@enkaku/
|
|
31
|
-
"@enkaku/
|
|
32
|
-
"@enkaku/
|
|
33
|
-
"@enkaku/
|
|
34
|
-
"@enkaku/token": "^0.
|
|
35
|
-
"@enkaku/
|
|
28
|
+
"@enkaku/capability": "^0.13.0",
|
|
29
|
+
"@enkaku/async": "^0.13.0",
|
|
30
|
+
"@enkaku/protocol": "^0.13.0",
|
|
31
|
+
"@enkaku/log": "^0.13.0",
|
|
32
|
+
"@enkaku/event": "^0.13.0",
|
|
33
|
+
"@enkaku/schema": "^0.13.0",
|
|
34
|
+
"@enkaku/token": "^0.13.0",
|
|
35
|
+
"@enkaku/stream": "^0.13.0"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
|
-
"@enkaku/transport": "^0.
|
|
38
|
+
"@enkaku/transport": "^0.13.0"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build:clean": "del lib",
|