@kubun/protocol 0.13.1 → 0.14.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.
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Canonical, security-sensitive translator: turns a thrown value into a
3
+ * `HandlerError` ONLY when it carries a registered {@link KubunErrorCode}, so
4
+ * `HandlerError.from` in `@enkaku/server` forwards its `code`/`data`/`msg` to the
5
+ * remote caller instead of flattening it to `EK01` / "Handler execution failed".
6
+ *
7
+ * Anything else is returned UNCHANGED, and that default is the security property:
8
+ * an error with no registered code is internal and its message may carry DIDs,
9
+ * paths, or SQL, so it stays opaque on the wire. This is the one place that
10
+ * decides which codes may leave the device — GraphQL-shaped errors are handled by
11
+ * a caller-local branch (see plugin-p2p) that delegates the rest here.
12
+ */
13
+ export declare function toHandlerError(cause: unknown): unknown;
14
+ /**
15
+ * Applies {@link toHandlerError} to every handler in a procedure record, so the
16
+ * translation lives in one place rather than in each handler.
17
+ */
18
+ export declare function wrapHandlers(handlers: Record<string, unknown>): Record<string, unknown>;
@@ -0,0 +1,56 @@
1
+ import { HandlerError } from '@enkaku/server';
2
+ import { isKubunErrorCode } from './errors.js';
3
+ function isObject(value) {
4
+ return typeof value === 'object' && value != null && !Array.isArray(value);
5
+ }
6
+ /**
7
+ * Canonical, security-sensitive translator: turns a thrown value into a
8
+ * `HandlerError` ONLY when it carries a registered {@link KubunErrorCode}, so
9
+ * `HandlerError.from` in `@enkaku/server` forwards its `code`/`data`/`msg` to the
10
+ * remote caller instead of flattening it to `EK01` / "Handler execution failed".
11
+ *
12
+ * Anything else is returned UNCHANGED, and that default is the security property:
13
+ * an error with no registered code is internal and its message may carry DIDs,
14
+ * paths, or SQL, so it stays opaque on the wire. This is the one place that
15
+ * decides which codes may leave the device — GraphQL-shaped errors are handled by
16
+ * a caller-local branch (see plugin-p2p) that delegates the rest here.
17
+ */ export function toHandlerError(cause) {
18
+ if (cause instanceof HandlerError) {
19
+ return cause;
20
+ }
21
+ if (isObject(cause) && isKubunErrorCode(cause.code)) {
22
+ const message = typeof cause.message === 'string' ? cause.message : undefined;
23
+ const data = isObject(cause.data) ? cause.data : {};
24
+ return new HandlerError({
25
+ code: cause.code,
26
+ message,
27
+ data,
28
+ cause
29
+ });
30
+ }
31
+ return cause;
32
+ }
33
+ /**
34
+ * Applies {@link toHandlerError} to every handler in a procedure record, so the
35
+ * translation lives in one place rather than in each handler.
36
+ */ export function wrapHandlers(handlers) {
37
+ return Object.fromEntries(Object.entries(handlers).map(([name, handler])=>{
38
+ if (typeof handler !== 'function') {
39
+ return [
40
+ name,
41
+ handler
42
+ ];
43
+ }
44
+ const wrapped = async (...args)=>{
45
+ try {
46
+ return await handler(...args);
47
+ } catch (cause) {
48
+ throw toHandlerError(cause);
49
+ }
50
+ };
51
+ return [
52
+ name,
53
+ wrapped
54
+ ];
55
+ }));
56
+ }
package/lib/index.d.ts CHANGED
@@ -2,6 +2,7 @@ import type { AnyClientMessageOf, AnyServerMessageOf, ClientTransportOf, ServerT
2
2
  import type { GraphProtocol } from './services/graph.js';
3
3
  export { isKubunErrorCode, type KubunErrorCode, KubunErrorCodes } from './errors.js';
4
4
  export type { GraphQLOperationParams, GraphQLSource, GraphQLSourceParams, GraphQLSourceProvider, GraphsProvider, } from './executor.js';
5
+ export { toHandlerError, wrapHandlers } from './handler-error.js';
5
6
  export * from './models/catalog.js';
6
7
  export * from './models/cluster.js';
7
8
  export * from './models/document.js';
package/lib/index.js CHANGED
@@ -1,4 +1,5 @@
1
1
  export { isKubunErrorCode, KubunErrorCodes } from './errors.js';
2
+ export { toHandlerError, wrapHandlers } from './handler-error.js';
2
3
  export * from './models/catalog.js';
3
4
  export * from './models/cluster.js';
4
5
  export * from './models/document.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kubun/protocol",
3
- "version": "0.13.1",
3
+ "version": "0.14.0",
4
4
  "keywords": [],
5
5
  "license": "see LICENSE.md",
6
6
  "sideEffects": false,
@@ -16,11 +16,12 @@
16
16
  ],
17
17
  "dependencies": {
18
18
  "@enkaku/protocol": "^0.21.0",
19
+ "@enkaku/server": "^0.21.2",
20
+ "@kubun/id": "^0.14.0",
21
+ "@kubun/logger": "^0.14.0",
19
22
  "@sozai/codec": "^0.4.0",
20
23
  "@sozai/schema": "^0.1.1",
21
- "change-case": "^5.4.4",
22
- "@kubun/id": "^0.13.0",
23
- "@kubun/logger": "^0.13.0"
24
+ "change-case": "^5.4.4"
24
25
  },
25
26
  "devDependencies": {
26
27
  "graphql": "^16.14.2",