@enkaku/server 0.12.3 → 0.13.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/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 +11 -3
- package/lib/server.d.ts.map +1 -1
- package/lib/server.js +208 -23
- 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,11 @@ export type HandleMessagesParams<Protocol extends ProtocolDefinition> = AccessCo
|
|
|
23
28
|
};
|
|
24
29
|
export type ServerParams<Protocol extends ProtocolDefinition> = {
|
|
25
30
|
access?: ProcedureAccessRecord;
|
|
31
|
+
encryptionPolicy?: EncryptionPolicy;
|
|
32
|
+
getRandomID?: () => string;
|
|
26
33
|
handlers: ProcedureHandlers<Protocol>;
|
|
27
|
-
|
|
34
|
+
identity?: Identity;
|
|
35
|
+
limits?: Partial<ResourceLimits>;
|
|
28
36
|
logger?: Logger;
|
|
29
37
|
protocol?: Protocol;
|
|
30
38
|
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,18 @@ 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';
|
|
14
|
+
function defaultRandomID() {
|
|
15
|
+
return globalThis.crypto.randomUUID();
|
|
16
|
+
}
|
|
13
17
|
async function handleMessages(params) {
|
|
14
|
-
const { events, handlers, logger, signal, transport, validator } = params;
|
|
18
|
+
const { events, handlers, limiter, logger, signal, transport, validator } = params;
|
|
15
19
|
const controllers = Object.create(null);
|
|
16
20
|
const context = {
|
|
17
21
|
controllers,
|
|
@@ -21,8 +25,34 @@ async function handleMessages(params) {
|
|
|
21
25
|
send: (payload)=>transport.write(createUnsignedToken(payload))
|
|
22
26
|
};
|
|
23
27
|
const running = Object.create(null);
|
|
28
|
+
const encoder = new TextEncoder();
|
|
29
|
+
// Periodic cleanup of expired controllers
|
|
30
|
+
const cleanupInterval = setInterval(()=>{
|
|
31
|
+
const expired = limiter.getExpiredControllers();
|
|
32
|
+
for (const rid of expired){
|
|
33
|
+
const controller = controllers[rid];
|
|
34
|
+
if (controller != null) {
|
|
35
|
+
controller.abort('Timeout');
|
|
36
|
+
const error = new HandlerError({
|
|
37
|
+
code: 'EK05',
|
|
38
|
+
message: 'Request timeout'
|
|
39
|
+
});
|
|
40
|
+
context.send(error.toPayload(rid));
|
|
41
|
+
events.emit('handlerTimeout', {
|
|
42
|
+
rid
|
|
43
|
+
});
|
|
44
|
+
limiter.removeController(rid);
|
|
45
|
+
limiter.releaseHandler();
|
|
46
|
+
delete controllers[rid];
|
|
47
|
+
delete running[rid];
|
|
48
|
+
} else {
|
|
49
|
+
limiter.removeController(rid);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}, Math.min(limiter.limits.controllerTimeoutMs, 10000));
|
|
24
53
|
const disposer = new Disposer({
|
|
25
54
|
dispose: async ()=>{
|
|
55
|
+
clearInterval(cleanupInterval);
|
|
26
56
|
const interruption = new DisposeInterruption();
|
|
27
57
|
// Abort all currently running handlers
|
|
28
58
|
for (const controller of Object.values(controllers)){
|
|
@@ -54,8 +84,43 @@ async function handleMessages(params) {
|
|
|
54
84
|
return result.value;
|
|
55
85
|
} : (message)=>message;
|
|
56
86
|
function processHandler(message, handle) {
|
|
87
|
+
const rid = message.payload.typ === 'event' ? Math.random().toString(36).slice(2) : message.payload.rid;
|
|
88
|
+
// Check controller limit
|
|
89
|
+
if (!limiter.canAddController()) {
|
|
90
|
+
const error = new HandlerError({
|
|
91
|
+
code: 'EK03',
|
|
92
|
+
message: 'Server controller limit reached'
|
|
93
|
+
});
|
|
94
|
+
if (message.payload.typ !== 'event') {
|
|
95
|
+
context.send(error.toPayload(rid));
|
|
96
|
+
}
|
|
97
|
+
events.emit('handlerError', {
|
|
98
|
+
error,
|
|
99
|
+
payload: message.payload
|
|
100
|
+
});
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
// Check handler concurrency (synchronous fast path)
|
|
104
|
+
if (limiter.activeHandlers >= limiter.limits.maxConcurrentHandlers) {
|
|
105
|
+
const error = new HandlerError({
|
|
106
|
+
code: 'EK04',
|
|
107
|
+
message: 'Server handler limit reached'
|
|
108
|
+
});
|
|
109
|
+
if (message.payload.typ !== 'event') {
|
|
110
|
+
context.send(error.toPayload(rid));
|
|
111
|
+
}
|
|
112
|
+
events.emit('handlerError', {
|
|
113
|
+
error,
|
|
114
|
+
payload: message.payload
|
|
115
|
+
});
|
|
116
|
+
return;
|
|
117
|
+
}
|
|
118
|
+
limiter.addController(rid);
|
|
119
|
+
limiter.acquireHandler();
|
|
57
120
|
const returned = handle();
|
|
58
121
|
if (returned instanceof Error) {
|
|
122
|
+
limiter.removeController(rid);
|
|
123
|
+
limiter.releaseHandler();
|
|
59
124
|
events.emit('handlerError', {
|
|
60
125
|
error: HandlerError.from(returned, {
|
|
61
126
|
code: 'EK01'
|
|
@@ -63,14 +128,52 @@ async function handleMessages(params) {
|
|
|
63
128
|
payload: message.payload
|
|
64
129
|
});
|
|
65
130
|
} else {
|
|
66
|
-
|
|
67
|
-
running[id] = returned;
|
|
131
|
+
running[rid] = returned;
|
|
68
132
|
returned.then(()=>{
|
|
69
|
-
|
|
133
|
+
// Guard against double-release if timeout cleanup already handled this rid
|
|
134
|
+
if (running[rid] === returned) {
|
|
135
|
+
limiter.removeController(rid);
|
|
136
|
+
limiter.releaseHandler();
|
|
137
|
+
delete running[rid];
|
|
138
|
+
}
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
function checkMessageEncryption(message) {
|
|
143
|
+
const globalPolicy = params.encryptionPolicy ?? 'none';
|
|
144
|
+
if (globalPolicy === 'none') {
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
const procedure = message.payload.prc;
|
|
148
|
+
const effectivePolicy = procedure != null ? resolveEncryptionPolicy(procedure, params.access, globalPolicy) : globalPolicy;
|
|
149
|
+
if (effectivePolicy !== 'required') {
|
|
150
|
+
return true;
|
|
151
|
+
}
|
|
152
|
+
// Detect if message was encrypted: jwe-in-jws mode has a 'jwe' field in the payload
|
|
153
|
+
const payload = message.payload;
|
|
154
|
+
return 'jwe' in payload && typeof payload.jwe === 'string';
|
|
155
|
+
}
|
|
156
|
+
function handleEncryptionViolation(message) {
|
|
157
|
+
const error = new HandlerError({
|
|
158
|
+
code: 'EK07',
|
|
159
|
+
message: 'Encryption required but message is not encrypted'
|
|
160
|
+
});
|
|
161
|
+
if (message.payload.typ === 'event') {
|
|
162
|
+
events.emit('handlerError', {
|
|
163
|
+
error,
|
|
164
|
+
payload: message.payload
|
|
70
165
|
});
|
|
166
|
+
} else {
|
|
167
|
+
context.send(error.toPayload(message.payload.rid));
|
|
71
168
|
}
|
|
72
169
|
}
|
|
73
|
-
const process = params.public ?
|
|
170
|
+
const process = params.public ? (message, handle)=>{
|
|
171
|
+
if (!checkMessageEncryption(message)) {
|
|
172
|
+
handleEncryptionViolation(message);
|
|
173
|
+
return;
|
|
174
|
+
}
|
|
175
|
+
processHandler(message, handle);
|
|
176
|
+
} : async (message, handle)=>{
|
|
74
177
|
try {
|
|
75
178
|
if (!params.public) {
|
|
76
179
|
if (!isSignedToken(message)) {
|
|
@@ -85,6 +188,10 @@ async function handleMessages(params) {
|
|
|
85
188
|
message: cause.message ?? 'Access denied'
|
|
86
189
|
});
|
|
87
190
|
if (message.payload.typ === 'event') {
|
|
191
|
+
events.emit('eventAuthError', {
|
|
192
|
+
error,
|
|
193
|
+
payload: message.payload
|
|
194
|
+
});
|
|
88
195
|
events.emit('handlerError', {
|
|
89
196
|
error,
|
|
90
197
|
payload: message.payload
|
|
@@ -94,6 +201,10 @@ async function handleMessages(params) {
|
|
|
94
201
|
}
|
|
95
202
|
return;
|
|
96
203
|
}
|
|
204
|
+
if (!checkMessageEncryption(message)) {
|
|
205
|
+
handleEncryptionViolation(message);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
97
208
|
processHandler(message, handle);
|
|
98
209
|
};
|
|
99
210
|
async function handleNext() {
|
|
@@ -104,6 +215,22 @@ async function handleMessages(params) {
|
|
|
104
215
|
}
|
|
105
216
|
const msg = processMessage(next.value);
|
|
106
217
|
if (msg != null) {
|
|
218
|
+
const msgSize = encoder.encode(JSON.stringify(msg.payload)).byteLength;
|
|
219
|
+
if (msgSize > limiter.limits.maxMessageSize) {
|
|
220
|
+
const error = new HandlerError({
|
|
221
|
+
code: 'EK06',
|
|
222
|
+
message: 'Message exceeds maximum size'
|
|
223
|
+
});
|
|
224
|
+
if ('rid' in msg.payload && msg.payload.rid != null) {
|
|
225
|
+
context.send(error.toPayload(msg.payload.rid));
|
|
226
|
+
}
|
|
227
|
+
events.emit('handlerError', {
|
|
228
|
+
error,
|
|
229
|
+
payload: msg.payload
|
|
230
|
+
});
|
|
231
|
+
handleNext();
|
|
232
|
+
return;
|
|
233
|
+
}
|
|
107
234
|
switch(msg.payload.typ){
|
|
108
235
|
case 'abort':
|
|
109
236
|
controllers[msg.payload.rid]?.abort(msg.payload.rsn);
|
|
@@ -129,7 +256,35 @@ async function handleMessages(params) {
|
|
|
129
256
|
case 'send':
|
|
130
257
|
{
|
|
131
258
|
const controller = controllers[msg.payload.rid];
|
|
132
|
-
controller
|
|
259
|
+
if (controller == null) {
|
|
260
|
+
logger.debug('received send for unknown channel {rid}', {
|
|
261
|
+
rid: msg.payload.rid
|
|
262
|
+
});
|
|
263
|
+
break;
|
|
264
|
+
}
|
|
265
|
+
// In non-public mode, validate send messages
|
|
266
|
+
if (!params.public) {
|
|
267
|
+
if (!isSignedToken(msg)) {
|
|
268
|
+
const error = new HandlerError({
|
|
269
|
+
code: 'EK02',
|
|
270
|
+
message: 'Channel send message must be signed'
|
|
271
|
+
});
|
|
272
|
+
context.send(error.toPayload(msg.payload.rid));
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
try {
|
|
276
|
+
await checkClientToken(params.serverID, params.access, msg);
|
|
277
|
+
} catch (cause) {
|
|
278
|
+
const error = new HandlerError({
|
|
279
|
+
cause,
|
|
280
|
+
code: 'EK02',
|
|
281
|
+
message: cause.message ?? 'Send authorization denied'
|
|
282
|
+
});
|
|
283
|
+
context.send(error.toPayload(msg.payload.rid));
|
|
284
|
+
break;
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
controller.writer.write(msg.payload.val);
|
|
133
288
|
break;
|
|
134
289
|
}
|
|
135
290
|
case 'stream':
|
|
@@ -149,8 +304,10 @@ export class Server extends Disposer {
|
|
|
149
304
|
#abortController;
|
|
150
305
|
#accessControl;
|
|
151
306
|
#events;
|
|
307
|
+
#getRandomID;
|
|
152
308
|
#handlers;
|
|
153
309
|
#handling = [];
|
|
310
|
+
#limiter;
|
|
154
311
|
#logger;
|
|
155
312
|
#validator;
|
|
156
313
|
constructor(params){
|
|
@@ -158,40 +315,64 @@ export class Server extends Disposer {
|
|
|
158
315
|
dispose: async ()=>{
|
|
159
316
|
// Signal messages handler to stop execution and run cleanup logic
|
|
160
317
|
this.#abortController.abort();
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
318
|
+
const cleanupTimeout = this.#limiter.limits.cleanupTimeoutMs;
|
|
319
|
+
const timeoutPromise = new Promise((resolve)=>{
|
|
320
|
+
setTimeout(resolve, cleanupTimeout);
|
|
321
|
+
});
|
|
322
|
+
// Race between graceful cleanup and timeout
|
|
323
|
+
const gracefulDone = await Promise.race([
|
|
324
|
+
Promise.all(this.#handling.map(async (handling)=>{
|
|
325
|
+
// Wait until all handlers are done - they might still need to flush messages to the transport
|
|
326
|
+
await handling.done;
|
|
327
|
+
// Dispose transport
|
|
328
|
+
await handling.transport.dispose();
|
|
329
|
+
})).then(()=>true),
|
|
330
|
+
timeoutPromise.then(()=>false)
|
|
331
|
+
]);
|
|
332
|
+
// Force dispose any remaining transports only if timed out
|
|
333
|
+
if (!gracefulDone) {
|
|
334
|
+
for (const handling of this.#handling){
|
|
335
|
+
try {
|
|
336
|
+
await handling.transport.dispose();
|
|
337
|
+
} catch {
|
|
338
|
+
// Ignore errors during forced cleanup
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
168
342
|
},
|
|
169
343
|
signal: params.signal
|
|
170
344
|
});
|
|
171
345
|
this.#abortController = new AbortController();
|
|
172
346
|
this.#events = new EventEmitter();
|
|
347
|
+
this.#getRandomID = params.getRandomID ?? defaultRandomID;
|
|
173
348
|
this.#handlers = params.handlers;
|
|
349
|
+
const serverID = params.identity?.id;
|
|
174
350
|
this.#logger = params.logger ?? getEnkakuLogger('server', {
|
|
175
|
-
serverID:
|
|
351
|
+
serverID: serverID ?? this.#getRandomID()
|
|
176
352
|
});
|
|
177
|
-
if (
|
|
353
|
+
if (serverID == null) {
|
|
178
354
|
if (params.public) {
|
|
179
355
|
this.#accessControl = {
|
|
180
356
|
public: true,
|
|
181
|
-
access: params.access
|
|
357
|
+
access: params.access,
|
|
358
|
+
encryptionPolicy: params.encryptionPolicy
|
|
182
359
|
};
|
|
183
360
|
} else {
|
|
184
|
-
throw new Error('Invalid server parameters: either the server "
|
|
361
|
+
throw new Error('Invalid server parameters: either the server "identity" must be provided or the "public" parameter must be set to true');
|
|
185
362
|
}
|
|
186
363
|
} else {
|
|
187
364
|
this.#accessControl = {
|
|
188
365
|
public: !!params.public,
|
|
189
|
-
serverID
|
|
190
|
-
access: params.access ?? {}
|
|
366
|
+
serverID,
|
|
367
|
+
access: params.access ?? {},
|
|
368
|
+
encryptionPolicy: params.encryptionPolicy
|
|
191
369
|
};
|
|
192
370
|
}
|
|
371
|
+
this.#limiter = createResourceLimiter(params.limits);
|
|
193
372
|
if (params.protocol != null) {
|
|
194
373
|
this.#validator = createValidator(createClientMessageSchema(params.protocol));
|
|
374
|
+
} else {
|
|
375
|
+
this.#logger.warn('No protocol provided: message validation is disabled. Pass a protocol definition to enable runtime type checking.');
|
|
195
376
|
}
|
|
196
377
|
for (const transport of params.transports ?? []){
|
|
197
378
|
this.handle(transport);
|
|
@@ -204,13 +385,15 @@ export class Server extends Disposer {
|
|
|
204
385
|
const publicAccess = options.public ?? this.#accessControl.public;
|
|
205
386
|
const access = options.access ?? this.#accessControl.access ?? {};
|
|
206
387
|
const logger = options.logger ?? this.#logger.getChild('handler').with({
|
|
207
|
-
transportID:
|
|
388
|
+
transportID: this.#getRandomID()
|
|
208
389
|
});
|
|
390
|
+
const encryptionPolicy = this.#accessControl.encryptionPolicy;
|
|
209
391
|
let accessControl;
|
|
210
392
|
if (publicAccess) {
|
|
211
393
|
accessControl = {
|
|
212
394
|
public: true,
|
|
213
|
-
access
|
|
395
|
+
access,
|
|
396
|
+
encryptionPolicy
|
|
214
397
|
};
|
|
215
398
|
} else {
|
|
216
399
|
const serverID = this.#accessControl.serverID;
|
|
@@ -220,12 +403,14 @@ export class Server extends Disposer {
|
|
|
220
403
|
accessControl = {
|
|
221
404
|
public: false,
|
|
222
405
|
serverID,
|
|
223
|
-
access
|
|
406
|
+
access,
|
|
407
|
+
encryptionPolicy
|
|
224
408
|
};
|
|
225
409
|
}
|
|
226
410
|
const done = handleMessages({
|
|
227
411
|
events: this.#events,
|
|
228
412
|
handlers: this.#handlers,
|
|
413
|
+
limiter: this.#limiter,
|
|
229
414
|
logger,
|
|
230
415
|
signal: this.#abortController.signal,
|
|
231
416
|
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":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EACV,6BAA6B,EAC7B,kBAAkB,EAClB,0BAA0B,EAC1B,MAAM,EACN,gBAAgB,EAChB,wBAAwB,EACxB,OAAO,EACP,kBAAkB,EAClB,kBAAkB,EAClB,0BAA0B,EAC1B,QAAQ,EACR,yBAAyB,EAC1B,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,MAAM,MAAM,iBAAiB,GAAG,eAAe,CAAA;AAE/C,MAAM,MAAM,iBAAiB,CAAC,IAAI,GAAG,OAAO,IAAI,eAAe,GAAG;IAChE,MAAM,EAAE,2BAA2B,CAAC,IAAI,CAAC,CAAA;CAC1C,CAAA;AAED,MAAM,MAAM,iBAAiB,CAAC,IAAI,GAAG,OAAO,IAAI,iBAAiB,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA;AAE3F,MAAM,MAAM,mBAAmB,CAC7B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,wBAAwB,GACpD;IACE,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IAClF,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;CAC1C,GACD,KAAK,CAAA;AAET,MAAM,MAAM,YAAY,CACtB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,CAAC,OAAO,EAAE,mBAAmB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAE/E,MAAM,MAAM,qBAAqB,CAC/B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,6BAA6B,GACzD;IACE,OAAO,EAAE,OAAO,CACd,kBAAkB,CAChB,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAC3B,SAAS,EACT,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CACrC,CACF,CAAA;IACD,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;IAC3C,MAAM,EAAE,WAAW,CAAA;CACpB,GACD,KAAK,CAAA;AAET,MAAM,MAAM,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AAEnG,MAAM,MAAM,cAAc,CACxB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,6BAA6B,GACzD,CACE,OAAO,EAAE,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAChD,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,KAAK,CAAA;AAET,MAAM,MAAM,oBAAoB,CAC9B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,yBAAyB,GAAG,0BAA0B,GAClF,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG;IAC3C,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;CACjE,GACD,KAAK,CAAA;AAET,MAAM,MAAM,aAAa,CACvB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,yBAAyB,GAAG,0BAA0B,GAClF,CACE,OAAO,EAAE,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAC/C,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,KAAK,CAAA;AAET,MAAM,MAAM,qBAAqB,CAC/B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACtD,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG;IAC1C,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;CAC9D,GACD,KAAK,CAAA;AAET,MAAM,MAAM,cAAc,CACxB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACtD,CACE,OAAO,EAAE,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAChD,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,KAAK,CAAA;AAET,MAAM,MAAM,iBAAiB,CAAC,QAAQ,SAAS,kBAAkB,IAAI;KAClE,SAAS,IAAI,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,SAAS,wBAAwB,GACxF,CAAC,OAAO,EAAE,mBAAmB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAAK,IAAI,GAC3D,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACpD,CACE,OAAO,EAAE,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAChD,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,QAAQ,CAAC,SAAS,CAAC,SAAS,yBAAyB,GACnD,CACE,OAAO,EAAE,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAC/C,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACpD,CACE,OAAO,EAAE,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAChD,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,KAAK;CAChB,CAAA;AAED,MAAM,MAAM,aAAa,CACvB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,wBAAwB,GACpD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,GACnC,KAAK,CAAA;AAET,MAAM,MAAM,SAAS,CACnB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,6BAA6B,GACzD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,GACpC,KAAK,CAAA;AAET,MAAM,MAAM,WAAW,CACrB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,yBAAyB,GACrD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,GACtC,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACpD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,GACtC,KAAK,CAAA;AAEX,MAAM,MAAM,UAAU,CACpB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,6BAA6B,GACzD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACrC,KAAK,CAAA;AAET,MAAM,MAAM,QAAQ,CAClB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACtD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,GACnC,KAAK,CAAA;AAET,MAAM,MAAM,YAAY,GAAG;IACzB,YAAY,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7B,YAAY,EAAE;QACZ,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,CAAA;QAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACjC,CAAA;IACD,cAAc,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/B,cAAc,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;CACnD,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC,YAAY,CAAC,CAAA;AAEtD,MAAM,MAAM,cAAc,CAAC,QAAQ,SAAS,kBAAkB,IAAI;IAChE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;IAC9C,MAAM,EAAE,aAAa,CAAA;IACrB,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/D,CAAA"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AACjD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAA;AACzC,OAAO,KAAK,EACV,6BAA6B,EAC7B,kBAAkB,EAClB,0BAA0B,EAC1B,MAAM,EACN,gBAAgB,EAChB,wBAAwB,EACxB,OAAO,EACP,kBAAkB,EAClB,kBAAkB,EAClB,0BAA0B,EAC1B,QAAQ,EACR,yBAAyB,EAC1B,MAAM,kBAAkB,CAAA;AAEzB,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,YAAY,CAAA;AAE9C,MAAM,MAAM,iBAAiB,GAAG,eAAe,CAAA;AAE/C,MAAM,MAAM,iBAAiB,CAAC,IAAI,GAAG,OAAO,IAAI,eAAe,GAAG;IAChE,MAAM,EAAE,2BAA2B,CAAC,IAAI,CAAC,CAAA;CAC1C,CAAA;AAED,MAAM,MAAM,iBAAiB,CAAC,IAAI,GAAG,OAAO,IAAI,iBAAiB,GAAG,iBAAiB,CAAC,IAAI,CAAC,CAAA;AAE3F,MAAM,MAAM,mBAAmB,CAC7B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,wBAAwB,GACpD;IACE,OAAO,EAAE,OAAO,CAAC,gBAAgB,CAAC,SAAS,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAA;IAClF,IAAI,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAA;CAC1C,GACD,KAAK,CAAA;AAET,MAAM,MAAM,YAAY,CACtB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,CAAC,OAAO,EAAE,mBAAmB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAA;AAE/E,MAAM,MAAM,qBAAqB,CAC/B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,6BAA6B,GACzD;IACE,OAAO,EAAE,OAAO,CACd,kBAAkB,CAChB,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,EAC3B,SAAS,EACT,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CACrC,CACF,CAAA;IACD,KAAK,EAAE,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,CAAA;IAC3C,MAAM,EAAE,WAAW,CAAA;CACpB,GACD,KAAK,CAAA;AAET,MAAM,MAAM,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,QAAQ,CAAC,YAAY,CAAC,IAAI,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAA;AAEnG,MAAM,MAAM,cAAc,CACxB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,6BAA6B,GACzD,CACE,OAAO,EAAE,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAChD,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,KAAK,CAAA;AAET,MAAM,MAAM,oBAAoB,CAC9B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,yBAAyB,GAAG,0BAA0B,GAClF,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG;IAC3C,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAA;CACjE,GACD,KAAK,CAAA;AAET,MAAM,MAAM,aAAa,CACvB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,yBAAyB,GAAG,0BAA0B,GAClF,CACE,OAAO,EAAE,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAC/C,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,KAAK,CAAA;AAET,MAAM,MAAM,qBAAqB,CAC/B,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACtD,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,GAAG;IAC1C,QAAQ,EAAE,cAAc,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAA;CAC9D,GACD,KAAK,CAAA;AAET,MAAM,MAAM,cAAc,CACxB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACtD,CACE,OAAO,EAAE,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAChD,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,KAAK,CAAA;AAET,MAAM,MAAM,iBAAiB,CAAC,QAAQ,SAAS,kBAAkB,IAAI;KAClE,SAAS,IAAI,MAAM,QAAQ,GAAG,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC,SAAS,wBAAwB,GACxF,CAAC,OAAO,EAAE,mBAAmB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAAK,IAAI,GAC3D,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACpD,CACE,OAAO,EAAE,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAChD,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,QAAQ,CAAC,SAAS,CAAC,SAAS,yBAAyB,GACnD,CACE,OAAO,EAAE,oBAAoB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAC/C,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACpD,CACE,OAAO,EAAE,qBAAqB,CAAC,QAAQ,EAAE,SAAS,CAAC,KAChD,aAAa,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACjD,KAAK;CAChB,CAAA;AAED,MAAM,MAAM,aAAa,CACvB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,wBAAwB,GACpD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,GACnC,KAAK,CAAA;AAET,MAAM,MAAM,SAAS,CACnB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,6BAA6B,GACzD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,OAAO,CAAC,CAAC,GACpC,KAAK,CAAA;AAET,MAAM,MAAM,WAAW,CACrB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,yBAAyB,GACrD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,GACtC,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACpD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,SAAS,CAAC,CAAC,GACtC,KAAK,CAAA;AAEX,MAAM,MAAM,UAAU,CACpB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,6BAA6B,GACzD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,GACrC,KAAK,CAAA;AAET,MAAM,MAAM,QAAQ,CAClB,QAAQ,SAAS,kBAAkB,EACnC,SAAS,SAAS,MAAM,QAAQ,GAAG,MAAM,IACvC,QAAQ,CAAC,SAAS,CAAC,SAAS,0BAA0B,GACtD,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC,GACnC,KAAK,CAAA;AAET,MAAM,MAAM,YAAY,GAAG;IACzB,cAAc,EAAE;QACd,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,CAAA;QAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACjC,CAAA;IACD,YAAY,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IAC7B,YAAY,EAAE;QACZ,KAAK,EAAE,YAAY,CAAC,MAAM,CAAC,CAAA;QAC3B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KACjC,CAAA;IACD,cAAc,EAAE;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IAC/B,cAAc,EAAE;QAAE,KAAK,EAAE,KAAK,CAAC;QAAC,OAAO,EAAE,OAAO,CAAA;KAAE,CAAA;CACnD,CAAA;AAED,MAAM,MAAM,aAAa,GAAG,YAAY,CAAC,YAAY,CAAC,CAAA;AAEtD,MAAM,MAAM,cAAc,CAAC,QAAQ,SAAS,kBAAkB,IAAI;IAChE,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAA;IAC9C,MAAM,EAAE,aAAa,CAAA;IACrB,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,IAAI,EAAE,CAAC,OAAO,EAAE,kBAAkB,CAAC,QAAQ,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAC/D,CAAA"}
|
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.1",
|
|
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/async": "^0.
|
|
29
|
-
"@enkaku/
|
|
30
|
-
"@enkaku/log": "^0.
|
|
31
|
-
"@enkaku/
|
|
32
|
-
"@enkaku/
|
|
33
|
-
"@enkaku/
|
|
34
|
-
"@enkaku/token": "^0.
|
|
35
|
-
"@enkaku/
|
|
28
|
+
"@enkaku/async": "^0.13.0",
|
|
29
|
+
"@enkaku/capability": "^0.13.0",
|
|
30
|
+
"@enkaku/log": "^0.13.0",
|
|
31
|
+
"@enkaku/event": "^0.13.0",
|
|
32
|
+
"@enkaku/schema": "^0.13.0",
|
|
33
|
+
"@enkaku/protocol": "^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.1"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"build:clean": "del lib",
|