@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.
- package/lib/handler-error.d.ts +18 -0
- package/lib/handler-error.js +56 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.js +1 -0
- package/package.json +5 -4
|
@@ -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
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@kubun/protocol",
|
|
3
|
-
"version": "0.
|
|
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",
|