@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.
@@ -1,5 +1,12 @@
1
1
  import type { SignedToken } from '@enkaku/token';
2
- export type ProcedureAccessRecord = Record<string, boolean | Array<string>>;
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,qBAAqB,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAA;AAE3E,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,CAiCf;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"}
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"}
@@ -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, access] of Object.entries(record)){
32
+ for (const [procedure, accessValue] of Object.entries(record)){
8
33
  if (hasPartsMatch(payload.prc, procedure)) {
9
- if (access === true) {
34
+ const allow = getAllowValue(accessValue);
35
+ if (allow === true) {
10
36
  // Procedure can be publicly accessed
11
37
  return;
12
38
  }
13
- if (access === false) {
39
+ if (allow === false) {
14
40
  continue;
15
41
  }
16
- if (access.includes(payload.iss)) {
42
+ if (allow.includes(payload.iss)) {
17
43
  // Issuer is allowed directly
18
44
  return;
19
45
  }
20
- if (payload.sub == null || !access.includes(payload.sub)) {
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;
@@ -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,CA0DvB"}
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"}
@@ -46,6 +46,17 @@ export function handleChannel(ctx, msg) {
46
46
  signal: controller.signal,
47
47
  writable: receiveStream.writable
48
48
  };
49
- // @ts-expect-error context and handler types
50
- return executeHandler(ctx, msg.payload, ()=>handler(handlerContext));
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,CAwCjG"}
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"}
@@ -32,6 +32,17 @@ export function handleStream(ctx, msg) {
32
32
  signal: controller.signal,
33
33
  writable: receiveStream.writable
34
34
  };
35
- // @ts-expect-error context and handler types
36
- return executeHandler(ctx, msg.payload, ()=>handler(handlerContext));
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
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,YAAY,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAChE,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"}
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 { Server, serve } from './server.js';
11
+ */ export { resolveEncryptionPolicy } from './access-control.js';
12
+ export { createResourceLimiter, DEFAULT_RESOURCE_LIMITS } from './limits.js';
13
+ export { Server, serve } from './server.js';
@@ -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 ProcedureAccessRecord } from './access-control.js';
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
- id?: string;
34
+ identity?: Identity;
35
+ limits?: Partial<ResourceLimits>;
28
36
  logger?: Logger;
29
37
  protocol?: Protocol;
30
38
  public?: boolean;
@@ -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;AAGvB,OAAO,EAAoB,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAA;AAMlF,OAAO,KAAK,EAIV,iBAAiB,EACjB,aAAa,EAEd,MAAM,YAAY,CAAA;AAQnB,MAAM,MAAM,mBAAmB,GAC3B;IAAE,MAAM,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,qBAAqB,CAAA;CAAE,GACnE;IAAE,MAAM,EAAE,KAAK,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,qBAAqB,CAAA;CAAE,CAAA;AAEtE,MAAM,MAAM,oBAAoB,CAAC,QAAQ,SAAS,kBAAkB,IAAI,mBAAmB,GAAG;IAC5F,MAAM,EAAE,aAAa,CAAA;IACrB,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACrC,MAAM,EAAE,MAAM,CAAA;IACd,MAAM,EAAE,WAAW,CAAA;IACnB,SAAS,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACtC,SAAS,CAAC,EAAE,SAAS,CAAC,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAA;CACpD,CAAA;AAyJD,MAAM,MAAM,YAAY,CAAC,QAAQ,SAAS,kBAAkB,IAAI;IAC9D,MAAM,CAAC,EAAE,qBAAqB,CAAA;IAC9B,QAAQ,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;IACrC,EAAE,CAAC,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,QAAQ,CAAC,EAAE,QAAQ,CAAA;IACnB,MAAM,CAAC,EAAE,OAAO,CAAA;IAChB,MAAM,CAAC,EAAE,WAAW,CAAA;IACpB,UAAU,CAAC,EAAE,KAAK,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC,CAAA;CAChD,CAAA;AAED,MAAM,MAAM,aAAa,GAAG;IAAE,MAAM,CAAC,EAAE,qBAAqB,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,OAAO,CAAA;CAAE,CAAA;AAEjG,qBAAa,MAAM,CAAC,QAAQ,SAAS,kBAAkB,CAAE,SAAQ,QAAQ;;gBAS3D,MAAM,EAAE,YAAY,CAAC,QAAQ,CAAC;IAgD1C,IAAI,MAAM,IAAI,aAAa,CAE1B;IAED,MAAM,CAAC,SAAS,EAAE,iBAAiB,CAAC,QAAQ,CAAC,EAAE,OAAO,GAAE,aAAkB,GAAG,OAAO,CAAC,IAAI,CAAC;CAiC3F;AAED,MAAM,MAAM,WAAW,CAAC,QAAQ,SAAS,kBAAkB,IAAI,IAAI,CACjE,YAAY,CAAC,QAAQ,CAAC,EACtB,YAAY,CACb,GAAG;IACF,SAAS,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAA;CACvC,CAAA;AAED,wBAAgB,KAAK,CAAC,QAAQ,SAAS,kBAAkB,EACvD,MAAM,EAAE,WAAW,CAAC,QAAQ,CAAC,GAC5B,MAAM,CAAC,QAAQ,CAAC,CAGlB"}
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
- const id = message.payload.typ === 'event' ? Math.random().toString(36).slice(2) : message.payload.rid;
67
- running[id] = returned;
131
+ running[rid] = returned;
68
132
  returned.then(()=>{
69
- delete running[id];
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 ? processHandler : async (message, handle)=>{
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?.writer.write(msg.payload.val);
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
- // Dispose of all handling transports
162
- await Promise.all(this.#handling.map(async (handling)=>{
163
- // Wait until all handlers are done - they might still need to flush messages to the transport
164
- await handling.done;
165
- // Dispose transport
166
- await handling.transport.dispose();
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: params.id ?? crypto.randomUUID()
351
+ serverID: serverID ?? this.#getRandomID()
176
352
  });
177
- if (params.id == null) {
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 "id" must be provided or the "public" parameter must be set to true');
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: params.id,
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: crypto.randomUUID()
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
  };
@@ -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":"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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: cause.message ?? 'Handler execution failed'
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.12.3",
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.12.2",
29
- "@enkaku/event": "^0.12.1",
30
- "@enkaku/log": "^0.12.1",
31
- "@enkaku/capability": "^0.12.1",
32
- "@enkaku/protocol": "^0.12.1",
33
- "@enkaku/stream": "^0.12.4",
34
- "@enkaku/token": "^0.12.3",
35
- "@enkaku/schema": "^0.12.1"
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.12.0"
38
+ "@enkaku/transport": "^0.13.1"
39
39
  },
40
40
  "scripts": {
41
41
  "build:clean": "del lib",