@fuzdev/fuz_app 0.4.0 → 0.6.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/dist/actions/action_bridge.d.ts +3 -3
- package/dist/actions/action_bridge.d.ts.map +1 -1
- package/dist/actions/action_bridge.js +5 -4
- package/dist/actions/action_rpc.d.ts +89 -0
- package/dist/actions/action_rpc.d.ts.map +1 -0
- package/dist/actions/action_rpc.js +248 -0
- package/dist/actions/action_spec.d.ts +8 -8
- package/dist/actions/action_spec.d.ts.map +1 -1
- package/dist/actions/action_spec.js +2 -2
- package/dist/http/db_routes.d.ts.map +1 -1
- package/dist/http/db_routes.js +4 -2
- package/dist/http/jsonrpc.d.ts +62 -0
- package/dist/http/jsonrpc.d.ts.map +1 -0
- package/dist/http/jsonrpc.js +49 -0
- package/dist/http/jsonrpc_errors.d.ts +132 -0
- package/dist/http/jsonrpc_errors.d.ts.map +1 -0
- package/dist/http/jsonrpc_errors.js +197 -0
- package/dist/http/route_spec.d.ts +2 -1
- package/dist/http/route_spec.d.ts.map +1 -1
- package/dist/http/route_spec.js +43 -7
- package/dist/http/schema_helpers.d.ts +3 -3
- package/dist/http/schema_helpers.d.ts.map +1 -1
- package/dist/http/schema_helpers.js +5 -10
- package/dist/http/surface.d.ts +25 -0
- package/dist/http/surface.d.ts.map +1 -1
- package/dist/http/surface.js +16 -1
- package/dist/server/app_server.d.ts +3 -1
- package/dist/server/app_server.d.ts.map +1 -1
- package/dist/server/app_server.js +2 -1
- package/dist/testing/adversarial_input.d.ts.map +1 -1
- package/dist/testing/adversarial_input.js +22 -7
- package/dist/testing/stubs.d.ts +3 -1
- package/dist/testing/stubs.d.ts.map +1 -1
- package/dist/testing/stubs.js +2 -1
- package/dist/testing/surface_invariants.d.ts +4 -0
- package/dist/testing/surface_invariants.d.ts.map +1 -1
- package/dist/testing/surface_invariants.js +4 -0
- package/package.json +1 -1
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON-RPC 2.0 envelope schemas for the single RPC endpoint dispatcher.
|
|
3
|
+
*
|
|
4
|
+
* Minimal subset extracted from zzz's `jsonrpc.ts` — only what the
|
|
5
|
+
* `create_rpc_endpoint` dispatcher needs to parse incoming requests
|
|
6
|
+
* and format outgoing responses. Full JSON-RPC schemas (batching,
|
|
7
|
+
* MCP extensions, notification types) remain in zzz.
|
|
8
|
+
*
|
|
9
|
+
* Following MCP, params and result are object-only (no positional arrays).
|
|
10
|
+
*
|
|
11
|
+
* @source https://github.com/modelcontextprotocol/typescript-sdk
|
|
12
|
+
* @see https://www.jsonrpc.org/specification
|
|
13
|
+
* @module
|
|
14
|
+
*/
|
|
15
|
+
import { z } from 'zod';
|
|
16
|
+
export const JSONRPC_VERSION = '2.0';
|
|
17
|
+
/** A uniquely identifying id for a request in JSON-RPC. Like MCP, excludes null. */
|
|
18
|
+
export const JsonrpcRequestId = z.union([z.string(), z.number()]);
|
|
19
|
+
/** A JSON-RPC method name. */
|
|
20
|
+
export const JsonrpcMethod = z.string();
|
|
21
|
+
/** Request params — loose object to allow additional properties. */
|
|
22
|
+
export const JsonrpcRequestParams = z.looseObject({});
|
|
23
|
+
/** Result — loose object to allow additional properties. */
|
|
24
|
+
export const JsonrpcResult = z.looseObject({});
|
|
25
|
+
/** A request that expects a response. */
|
|
26
|
+
export const JsonrpcRequest = z.looseObject({
|
|
27
|
+
jsonrpc: z.literal(JSONRPC_VERSION),
|
|
28
|
+
id: JsonrpcRequestId,
|
|
29
|
+
method: JsonrpcMethod,
|
|
30
|
+
params: JsonrpcRequestParams.optional(),
|
|
31
|
+
});
|
|
32
|
+
/** A successful (non-error) response to a request. */
|
|
33
|
+
export const JsonrpcResponse = z.looseObject({
|
|
34
|
+
jsonrpc: z.literal(JSONRPC_VERSION),
|
|
35
|
+
id: JsonrpcRequestId,
|
|
36
|
+
result: JsonrpcResult,
|
|
37
|
+
});
|
|
38
|
+
/** Error object within a JSON-RPC error response. */
|
|
39
|
+
export const JsonrpcErrorObject = z.looseObject({
|
|
40
|
+
code: z.number(),
|
|
41
|
+
message: z.string(),
|
|
42
|
+
data: z.unknown().optional(),
|
|
43
|
+
});
|
|
44
|
+
/** A response that indicates an error occurred. */
|
|
45
|
+
export const JsonrpcErrorResponse = z.looseObject({
|
|
46
|
+
jsonrpc: z.literal(JSONRPC_VERSION),
|
|
47
|
+
id: JsonrpcRequestId.nullable(),
|
|
48
|
+
error: JsonrpcErrorObject,
|
|
49
|
+
});
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON-RPC error infrastructure for fuz_app routes.
|
|
3
|
+
*
|
|
4
|
+
* Provides error types, named constructors, and HTTP status mapping
|
|
5
|
+
* for the throw/catch error pattern used by `apply_route_specs`.
|
|
6
|
+
* Extracted from zzz's `jsonrpc_errors.ts` — only core error codes
|
|
7
|
+
* (5 standard + 8 general application). Domain-specific codes stay
|
|
8
|
+
* in consumers. `JSONRPC_ERROR_CODES` is extensible — consumers
|
|
9
|
+
* add their own codes by casting `as JsonrpcErrorCode`.
|
|
10
|
+
*
|
|
11
|
+
* Complementary to `error_schemas.ts`: that module is declarative
|
|
12
|
+
* (Zod schemas for surface introspection), this one is runtime
|
|
13
|
+
* (throw + catch + map).
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
/** Branded number type for JSON-RPC error codes. */
|
|
18
|
+
export type JsonrpcErrorCode = number & {
|
|
19
|
+
readonly __brand: 'JsonrpcErrorCode';
|
|
20
|
+
};
|
|
21
|
+
/** JSON-RPC error response object — code, message, and optional data. */
|
|
22
|
+
export interface JsonrpcErrorJson {
|
|
23
|
+
code: JsonrpcErrorCode;
|
|
24
|
+
message: string;
|
|
25
|
+
data?: unknown;
|
|
26
|
+
}
|
|
27
|
+
/** Names of standard and general application JSON-RPC error codes. */
|
|
28
|
+
export type JsonrpcErrorName = 'parse_error' | 'invalid_request' | 'method_not_found' | 'invalid_params' | 'internal_error' | 'unauthenticated' | 'forbidden' | 'not_found' | 'conflict' | 'validation_error' | 'rate_limited' | 'service_unavailable' | 'timeout';
|
|
29
|
+
/**
|
|
30
|
+
* Standard JSON-RPC error codes (5) plus general application codes (8).
|
|
31
|
+
*
|
|
32
|
+
* Extensible — consumers add domain-specific codes to their own objects
|
|
33
|
+
* by casting `as JsonrpcErrorCode`. Application codes use the -32000 to
|
|
34
|
+
* -32099 range reserved by the JSON-RPC spec.
|
|
35
|
+
*/
|
|
36
|
+
export declare const JSONRPC_ERROR_CODES: {
|
|
37
|
+
/** -32700 */
|
|
38
|
+
readonly parse_error: JsonrpcErrorCode;
|
|
39
|
+
/** -32600 */
|
|
40
|
+
readonly invalid_request: JsonrpcErrorCode;
|
|
41
|
+
/** -32601 */
|
|
42
|
+
readonly method_not_found: JsonrpcErrorCode;
|
|
43
|
+
/** -32602 */
|
|
44
|
+
readonly invalid_params: JsonrpcErrorCode;
|
|
45
|
+
/** -32603 */
|
|
46
|
+
readonly internal_error: JsonrpcErrorCode;
|
|
47
|
+
/**
|
|
48
|
+
* Same as HTTP 401 "unauthorized", but correctly named.
|
|
49
|
+
*
|
|
50
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status#client_error_responses
|
|
51
|
+
*/
|
|
52
|
+
readonly unauthenticated: JsonrpcErrorCode;
|
|
53
|
+
/**
|
|
54
|
+
* Named to match HTTP 403 — avoids confusion with 401 which
|
|
55
|
+
* is incorrectly named "unauthorized" in HTTP.
|
|
56
|
+
*/
|
|
57
|
+
readonly forbidden: JsonrpcErrorCode;
|
|
58
|
+
readonly not_found: JsonrpcErrorCode;
|
|
59
|
+
readonly conflict: JsonrpcErrorCode;
|
|
60
|
+
/**
|
|
61
|
+
* Application-level validation failures (business logic).
|
|
62
|
+
* Use `invalid_params` (-32602) for schema/parsing failures.
|
|
63
|
+
*/
|
|
64
|
+
readonly validation_error: JsonrpcErrorCode;
|
|
65
|
+
readonly rate_limited: JsonrpcErrorCode;
|
|
66
|
+
readonly service_unavailable: JsonrpcErrorCode;
|
|
67
|
+
readonly timeout: JsonrpcErrorCode;
|
|
68
|
+
};
|
|
69
|
+
/**
|
|
70
|
+
* Named constructors for `JsonrpcErrorJson` objects.
|
|
71
|
+
*
|
|
72
|
+
* Each function creates a JSON-RPC error response object with the correct
|
|
73
|
+
* code and a sensible default message. Used by the catch layer in
|
|
74
|
+
* `apply_route_specs` to build response bodies.
|
|
75
|
+
*/
|
|
76
|
+
export declare const jsonrpc_error_messages: {
|
|
77
|
+
readonly parse_error: (data?: unknown) => JsonrpcErrorJson;
|
|
78
|
+
readonly invalid_request: (data?: unknown) => JsonrpcErrorJson;
|
|
79
|
+
readonly method_not_found: (method?: string, data?: unknown) => JsonrpcErrorJson;
|
|
80
|
+
readonly invalid_params: (message?: string, data?: unknown) => JsonrpcErrorJson;
|
|
81
|
+
readonly internal_error: (message?: string, data?: unknown) => JsonrpcErrorJson;
|
|
82
|
+
readonly unauthenticated: (message?: string, data?: unknown) => JsonrpcErrorJson;
|
|
83
|
+
readonly forbidden: (message?: string, data?: unknown) => JsonrpcErrorJson;
|
|
84
|
+
readonly not_found: (resource?: string, data?: unknown) => JsonrpcErrorJson;
|
|
85
|
+
readonly conflict: (message?: string, data?: unknown) => JsonrpcErrorJson;
|
|
86
|
+
readonly validation_error: (message?: string, data?: unknown) => JsonrpcErrorJson;
|
|
87
|
+
readonly rate_limited: (message?: string, data?: unknown) => JsonrpcErrorJson;
|
|
88
|
+
readonly service_unavailable: (message?: string, data?: unknown) => JsonrpcErrorJson;
|
|
89
|
+
readonly timeout: (message?: string, data?: unknown) => JsonrpcErrorJson;
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Error class carrying a JSON-RPC error code — thrown by handlers,
|
|
93
|
+
* caught by `apply_route_specs` and mapped to HTTP status + JSON-RPC error response.
|
|
94
|
+
*
|
|
95
|
+
* Named for what it is: an error with a JSON-RPC error code that gets thrown.
|
|
96
|
+
*/
|
|
97
|
+
export declare class ThrownJsonrpcError extends Error {
|
|
98
|
+
code: JsonrpcErrorCode;
|
|
99
|
+
data?: unknown;
|
|
100
|
+
constructor(code: JsonrpcErrorCode, message: string, data?: unknown, options?: ErrorOptions);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Named constructors for `ThrownJsonrpcError`.
|
|
104
|
+
*
|
|
105
|
+
* Usage: `throw jsonrpc_errors.not_found('user')` or `throw jsonrpc_errors.forbidden()`.
|
|
106
|
+
*/
|
|
107
|
+
export declare const jsonrpc_errors: {
|
|
108
|
+
readonly parse_error: (data?: unknown) => ThrownJsonrpcError;
|
|
109
|
+
readonly invalid_request: (data?: unknown) => ThrownJsonrpcError;
|
|
110
|
+
readonly method_not_found: (method?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
111
|
+
readonly invalid_params: (message?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
112
|
+
readonly internal_error: (message?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
113
|
+
readonly unauthenticated: (message?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
114
|
+
readonly forbidden: (message?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
115
|
+
readonly not_found: (resource?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
116
|
+
readonly conflict: (message?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
117
|
+
readonly validation_error: (message?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
118
|
+
readonly rate_limited: (message?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
119
|
+
readonly service_unavailable: (message?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
120
|
+
readonly timeout: (message?: string | undefined, data?: unknown) => ThrownJsonrpcError;
|
|
121
|
+
};
|
|
122
|
+
/**
|
|
123
|
+
* Map a JSON-RPC error code to an HTTP status code.
|
|
124
|
+
*
|
|
125
|
+
* Returns 500 for unrecognized codes (consumer-defined codes
|
|
126
|
+
* without a mapping default to internal server error).
|
|
127
|
+
*
|
|
128
|
+
* @param code - the JSON-RPC error code
|
|
129
|
+
* @returns the corresponding HTTP status code
|
|
130
|
+
*/
|
|
131
|
+
export declare const jsonrpc_error_code_to_http_status: (code: JsonrpcErrorCode) => number;
|
|
132
|
+
//# sourceMappingURL=jsonrpc_errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jsonrpc_errors.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/jsonrpc_errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,oDAAoD;AACpD,MAAM,MAAM,gBAAgB,GAAG,MAAM,GAAG;IAAC,QAAQ,CAAC,OAAO,EAAE,kBAAkB,CAAA;CAAC,CAAC;AAE/E,yEAAyE;AACzE,MAAM,WAAW,gBAAgB;IAChC,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,OAAO,CAAC;CACf;AAED,sEAAsE;AACtE,MAAM,MAAM,gBAAgB,GACzB,aAAa,GACb,iBAAiB,GACjB,kBAAkB,GAClB,gBAAgB,GAChB,gBAAgB,GAChB,iBAAiB,GACjB,WAAW,GACX,WAAW,GACX,UAAU,GACV,kBAAkB,GAClB,cAAc,GACd,qBAAqB,GACrB,SAAS,CAAC;AAEb;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB;IAE/B,aAAa;0BACU,gBAAgB;IACvC,aAAa;8BACc,gBAAgB;IAC3C,aAAa;+BACe,gBAAgB;IAC5C,aAAa;6BACa,gBAAgB;IAC1C,aAAa;6BACa,gBAAgB;IAG1C;;;;OAIG;8BACwB,gBAAgB;IAC3C;;;OAGG;wBACkB,gBAAgB;wBAChB,gBAAgB;uBACjB,gBAAgB;IACpC;;;OAGG;+BACyB,gBAAgB;2BACpB,gBAAgB;kCACT,gBAAgB;sBAC5B,gBAAgB;CAC2B,CAAC;AAEhE;;;;;;GAMG;AACH,eAAO,MAAM,sBAAsB;kCACb,OAAO,KAAG,gBAAgB;sCAMtB,OAAO,KAAG,gBAAgB;yCAMvB,MAAM,SAAS,OAAO,KAAG,gBAAgB;wCAM1C,MAAM,SAAS,OAAO,KAAG,gBAAgB;wCAO1D,MAAM,SACR,OAAO,KACZ,gBAAgB;yCAMQ,MAAM,SAA6B,OAAO,KAAG,gBAAgB;mCAMnE,MAAM,SAAuB,OAAO,KAAG,gBAAgB;oCAMrD,MAAM,SAAS,OAAO,KAAG,gBAAgB;kCAM5C,MAAM,SAAsB,OAAO,KAAG,gBAAgB;0CAM9C,MAAM,SAA8B,OAAO,KAAG,gBAAgB;sCAMlE,MAAM,SAA0B,OAAO,KAAG,gBAAgB;6CAOxE,MAAM,SACR,OAAO,KACZ,gBAAgB;iCAMA,MAAM,SAAqB,OAAO,KAAG,gBAAgB;CAKe,CAAC;AAEzF;;;;;GAKG;AACH,qBAAa,kBAAmB,SAAQ,KAAK;IAC5C,IAAI,EAAE,gBAAgB,CAAC;IACvB,IAAI,CAAC,EAAE,OAAO,CAAC;gBAEH,IAAI,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,YAAY;CAK3F;AAWD;;;;GAIG;AACH,eAAO,MAAM,cAAc;8CAXQ,kBAAkB;kDAAlB,kBAAkB;gFAAlB,kBAAkB;+EAAlB,kBAAkB;+EAAlB,kBAAkB;gFAAlB,kBAAkB;0EAAlB,kBAAkB;2EAAlB,kBAAkB;yEAAlB,kBAAkB;iFAAlB,kBAAkB;6EAAlB,kBAAkB;oFAAlB,kBAAkB;wEAAlB,kBAAkB;CAyBqC,CAAC;AAoB3F;;;;;;;;GAQG;AACH,eAAO,MAAM,iCAAiC,GAAI,MAAM,gBAAgB,KAAG,MACjB,CAAC"}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JSON-RPC error infrastructure for fuz_app routes.
|
|
3
|
+
*
|
|
4
|
+
* Provides error types, named constructors, and HTTP status mapping
|
|
5
|
+
* for the throw/catch error pattern used by `apply_route_specs`.
|
|
6
|
+
* Extracted from zzz's `jsonrpc_errors.ts` — only core error codes
|
|
7
|
+
* (5 standard + 8 general application). Domain-specific codes stay
|
|
8
|
+
* in consumers. `JSONRPC_ERROR_CODES` is extensible — consumers
|
|
9
|
+
* add their own codes by casting `as JsonrpcErrorCode`.
|
|
10
|
+
*
|
|
11
|
+
* Complementary to `error_schemas.ts`: that module is declarative
|
|
12
|
+
* (Zod schemas for surface introspection), this one is runtime
|
|
13
|
+
* (throw + catch + map).
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
/**
|
|
18
|
+
* Standard JSON-RPC error codes (5) plus general application codes (8).
|
|
19
|
+
*
|
|
20
|
+
* Extensible — consumers add domain-specific codes to their own objects
|
|
21
|
+
* by casting `as JsonrpcErrorCode`. Application codes use the -32000 to
|
|
22
|
+
* -32099 range reserved by the JSON-RPC spec.
|
|
23
|
+
*/
|
|
24
|
+
export const JSONRPC_ERROR_CODES = {
|
|
25
|
+
// Standard JSON-RPC errors — https://www.jsonrpc.org/specification
|
|
26
|
+
/** -32700 */
|
|
27
|
+
parse_error: -32700,
|
|
28
|
+
/** -32600 */
|
|
29
|
+
invalid_request: -32600,
|
|
30
|
+
/** -32601 */
|
|
31
|
+
method_not_found: -32601,
|
|
32
|
+
/** -32602 */
|
|
33
|
+
invalid_params: -32602,
|
|
34
|
+
/** -32603 */
|
|
35
|
+
internal_error: -32603,
|
|
36
|
+
// General application errors (-32000 to -32099)
|
|
37
|
+
/**
|
|
38
|
+
* Same as HTTP 401 "unauthorized", but correctly named.
|
|
39
|
+
*
|
|
40
|
+
* @see https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Status#client_error_responses
|
|
41
|
+
*/
|
|
42
|
+
unauthenticated: -32001,
|
|
43
|
+
/**
|
|
44
|
+
* Named to match HTTP 403 — avoids confusion with 401 which
|
|
45
|
+
* is incorrectly named "unauthorized" in HTTP.
|
|
46
|
+
*/
|
|
47
|
+
forbidden: -32002,
|
|
48
|
+
not_found: -32003,
|
|
49
|
+
conflict: -32004,
|
|
50
|
+
/**
|
|
51
|
+
* Application-level validation failures (business logic).
|
|
52
|
+
* Use `invalid_params` (-32602) for schema/parsing failures.
|
|
53
|
+
*/
|
|
54
|
+
validation_error: -32005,
|
|
55
|
+
rate_limited: -32006,
|
|
56
|
+
service_unavailable: -32007,
|
|
57
|
+
timeout: -32008,
|
|
58
|
+
};
|
|
59
|
+
/**
|
|
60
|
+
* Named constructors for `JsonrpcErrorJson` objects.
|
|
61
|
+
*
|
|
62
|
+
* Each function creates a JSON-RPC error response object with the correct
|
|
63
|
+
* code and a sensible default message. Used by the catch layer in
|
|
64
|
+
* `apply_route_specs` to build response bodies.
|
|
65
|
+
*/
|
|
66
|
+
export const jsonrpc_error_messages = {
|
|
67
|
+
parse_error: (data) => ({
|
|
68
|
+
code: JSONRPC_ERROR_CODES.parse_error,
|
|
69
|
+
message: 'parse error',
|
|
70
|
+
data,
|
|
71
|
+
}),
|
|
72
|
+
invalid_request: (data) => ({
|
|
73
|
+
code: JSONRPC_ERROR_CODES.invalid_request,
|
|
74
|
+
message: 'invalid request',
|
|
75
|
+
data,
|
|
76
|
+
}),
|
|
77
|
+
method_not_found: (method, data) => ({
|
|
78
|
+
code: JSONRPC_ERROR_CODES.method_not_found,
|
|
79
|
+
message: method ? `method not found: ${method}` : 'method not found',
|
|
80
|
+
data,
|
|
81
|
+
}),
|
|
82
|
+
invalid_params: (message, data) => ({
|
|
83
|
+
code: JSONRPC_ERROR_CODES.invalid_params,
|
|
84
|
+
message: message ?? 'invalid params',
|
|
85
|
+
data,
|
|
86
|
+
}),
|
|
87
|
+
internal_error: (message = 'internal server error', data) => ({
|
|
88
|
+
code: JSONRPC_ERROR_CODES.internal_error,
|
|
89
|
+
message,
|
|
90
|
+
data,
|
|
91
|
+
}),
|
|
92
|
+
unauthenticated: (message = 'unauthenticated', data) => ({
|
|
93
|
+
code: JSONRPC_ERROR_CODES.unauthenticated,
|
|
94
|
+
message,
|
|
95
|
+
data,
|
|
96
|
+
}),
|
|
97
|
+
forbidden: (message = 'forbidden', data) => ({
|
|
98
|
+
code: JSONRPC_ERROR_CODES.forbidden,
|
|
99
|
+
message,
|
|
100
|
+
data,
|
|
101
|
+
}),
|
|
102
|
+
not_found: (resource, data) => ({
|
|
103
|
+
code: JSONRPC_ERROR_CODES.not_found,
|
|
104
|
+
message: resource ? `${resource} not found` : 'not found',
|
|
105
|
+
data,
|
|
106
|
+
}),
|
|
107
|
+
conflict: (message = 'conflict', data) => ({
|
|
108
|
+
code: JSONRPC_ERROR_CODES.conflict,
|
|
109
|
+
message,
|
|
110
|
+
data,
|
|
111
|
+
}),
|
|
112
|
+
validation_error: (message = 'validation error', data) => ({
|
|
113
|
+
code: JSONRPC_ERROR_CODES.validation_error,
|
|
114
|
+
message,
|
|
115
|
+
data,
|
|
116
|
+
}),
|
|
117
|
+
rate_limited: (message = 'rate limited', data) => ({
|
|
118
|
+
code: JSONRPC_ERROR_CODES.rate_limited,
|
|
119
|
+
message,
|
|
120
|
+
data,
|
|
121
|
+
}),
|
|
122
|
+
service_unavailable: (message = 'service unavailable', data) => ({
|
|
123
|
+
code: JSONRPC_ERROR_CODES.service_unavailable,
|
|
124
|
+
message,
|
|
125
|
+
data,
|
|
126
|
+
}),
|
|
127
|
+
timeout: (message = 'timeout', data) => ({
|
|
128
|
+
code: JSONRPC_ERROR_CODES.timeout,
|
|
129
|
+
message,
|
|
130
|
+
data,
|
|
131
|
+
}),
|
|
132
|
+
};
|
|
133
|
+
/**
|
|
134
|
+
* Error class carrying a JSON-RPC error code — thrown by handlers,
|
|
135
|
+
* caught by `apply_route_specs` and mapped to HTTP status + JSON-RPC error response.
|
|
136
|
+
*
|
|
137
|
+
* Named for what it is: an error with a JSON-RPC error code that gets thrown.
|
|
138
|
+
*/
|
|
139
|
+
export class ThrownJsonrpcError extends Error {
|
|
140
|
+
code;
|
|
141
|
+
data;
|
|
142
|
+
constructor(code, message, data, options) {
|
|
143
|
+
super(message, options);
|
|
144
|
+
this.code = code;
|
|
145
|
+
this.data = data;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
const create_error_thrower = (error_fn) => (...args) => {
|
|
149
|
+
const m = error_fn(...args);
|
|
150
|
+
return new ThrownJsonrpcError(m.code, m.message, m.data);
|
|
151
|
+
};
|
|
152
|
+
/**
|
|
153
|
+
* Named constructors for `ThrownJsonrpcError`.
|
|
154
|
+
*
|
|
155
|
+
* Usage: `throw jsonrpc_errors.not_found('user')` or `throw jsonrpc_errors.forbidden()`.
|
|
156
|
+
*/
|
|
157
|
+
export const jsonrpc_errors = {
|
|
158
|
+
parse_error: create_error_thrower(jsonrpc_error_messages.parse_error),
|
|
159
|
+
invalid_request: create_error_thrower(jsonrpc_error_messages.invalid_request),
|
|
160
|
+
method_not_found: create_error_thrower(jsonrpc_error_messages.method_not_found),
|
|
161
|
+
invalid_params: create_error_thrower(jsonrpc_error_messages.invalid_params),
|
|
162
|
+
internal_error: create_error_thrower(jsonrpc_error_messages.internal_error),
|
|
163
|
+
unauthenticated: create_error_thrower(jsonrpc_error_messages.unauthenticated),
|
|
164
|
+
forbidden: create_error_thrower(jsonrpc_error_messages.forbidden),
|
|
165
|
+
not_found: create_error_thrower(jsonrpc_error_messages.not_found),
|
|
166
|
+
conflict: create_error_thrower(jsonrpc_error_messages.conflict),
|
|
167
|
+
validation_error: create_error_thrower(jsonrpc_error_messages.validation_error),
|
|
168
|
+
rate_limited: create_error_thrower(jsonrpc_error_messages.rate_limited),
|
|
169
|
+
service_unavailable: create_error_thrower(jsonrpc_error_messages.service_unavailable),
|
|
170
|
+
timeout: create_error_thrower(jsonrpc_error_messages.timeout),
|
|
171
|
+
};
|
|
172
|
+
// --- HTTP status mapping ---
|
|
173
|
+
const JSONRPC_ERROR_CODE_HTTP_STATUS = new Map([
|
|
174
|
+
[-32700, 400], // parse_error
|
|
175
|
+
[-32600, 400], // invalid_request
|
|
176
|
+
[-32601, 404], // method_not_found
|
|
177
|
+
[-32602, 400], // invalid_params
|
|
178
|
+
[-32603, 500], // internal_error
|
|
179
|
+
[-32001, 401], // unauthenticated
|
|
180
|
+
[-32002, 403], // forbidden
|
|
181
|
+
[-32003, 404], // not_found
|
|
182
|
+
[-32004, 409], // conflict
|
|
183
|
+
[-32005, 422], // validation_error
|
|
184
|
+
[-32006, 429], // rate_limited
|
|
185
|
+
[-32007, 503], // service_unavailable
|
|
186
|
+
[-32008, 504], // timeout
|
|
187
|
+
]);
|
|
188
|
+
/**
|
|
189
|
+
* Map a JSON-RPC error code to an HTTP status code.
|
|
190
|
+
*
|
|
191
|
+
* Returns 500 for unrecognized codes (consumer-defined codes
|
|
192
|
+
* without a mapping default to internal server error).
|
|
193
|
+
*
|
|
194
|
+
* @param code - the JSON-RPC error code
|
|
195
|
+
* @returns the corresponding HTTP status code
|
|
196
|
+
*/
|
|
197
|
+
export const jsonrpc_error_code_to_http_status = (code) => JSONRPC_ERROR_CODE_HTTP_STATUS.get(code) ?? 500;
|
|
@@ -171,7 +171,8 @@ export declare const apply_middleware_specs: (app: Hono, specs: Array<Middleware
|
|
|
171
171
|
*
|
|
172
172
|
* For each spec: resolves auth to guards via the provided resolver,
|
|
173
173
|
* adds input validation middleware (for routes with non-null input schemas),
|
|
174
|
-
* wraps handler with DEV-only output and error validation,
|
|
174
|
+
* wraps handler with DEV-only output and error validation, wraps with error
|
|
175
|
+
* catch layer (catches `ThrownJsonrpcError` and generic errors), and registers the route.
|
|
175
176
|
*
|
|
176
177
|
* Each handler receives a `RouteContext` with:
|
|
177
178
|
* - `db`: transaction-scoped (for non-GET) or pool-level (for GET)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route_spec.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/route_spec.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EAAC,OAAO,EAAW,IAAI,EAAE,iBAAiB,EAAC,MAAM,MAAM,CAAC;AACpE,OAAO,KAAK,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAE3B,OAAO,KAAK,EAAC,MAAM,EAAC,MAAM,yBAAyB,CAAC;AAEpD,OAAO,KAAK,EAAC,EAAE,EAAC,MAAM,aAAa,CAAC;AACpC,OAAO,EACN,KAAK,iBAAiB,EACtB,KAAK,YAAY,EAKjB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"route_spec.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/route_spec.ts"],"names":[],"mappings":"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"}
|
package/dist/http/route_spec.js
CHANGED
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { DEV } from 'esm-env';
|
|
16
16
|
import { ERROR_INVALID_JSON_BODY, ERROR_INVALID_REQUEST_BODY, ERROR_INVALID_ROUTE_PARAMS, ERROR_INVALID_QUERY_PARAMS, } from './error_schemas.js';
|
|
17
|
+
import { ThrownJsonrpcError, JSONRPC_ERROR_CODES, jsonrpc_error_code_to_http_status, } from './jsonrpc_errors.js';
|
|
17
18
|
import { is_null_schema, merge_error_schemas } from './schema_helpers.js';
|
|
18
19
|
/**
|
|
19
20
|
* Get validated input from the Hono context.
|
|
@@ -54,11 +55,15 @@ export const get_route_query = (c) => {
|
|
|
54
55
|
/**
|
|
55
56
|
* Create input validation middleware for a route spec.
|
|
56
57
|
*
|
|
57
|
-
* Returns an empty array for
|
|
58
|
-
*
|
|
59
|
-
*
|
|
58
|
+
* Returns an empty array for GET routes (no body to parse — GET input is
|
|
59
|
+
* validated elsewhere, e.g. from `?params=` query string in RPC handlers)
|
|
60
|
+
* and for null-input routes (no body expected). For other routes with input
|
|
61
|
+
* schemas, returns a middleware that parses and validates the JSON body,
|
|
62
|
+
* storing the result on the context as `validated_input`.
|
|
60
63
|
*/
|
|
61
|
-
const create_input_validation = (input_schema) => {
|
|
64
|
+
const create_input_validation = (input_schema, method) => {
|
|
65
|
+
if (method === 'GET')
|
|
66
|
+
return [];
|
|
62
67
|
if (is_null_schema(input_schema))
|
|
63
68
|
return [];
|
|
64
69
|
const validate = async (c, next) => {
|
|
@@ -185,12 +190,41 @@ export const apply_middleware_specs = (app, specs) => {
|
|
|
185
190
|
app.use(spec.path, spec.handler);
|
|
186
191
|
}
|
|
187
192
|
};
|
|
193
|
+
/**
|
|
194
|
+
* Wrap a handler with error catch logic.
|
|
195
|
+
*
|
|
196
|
+
* Catches `ThrownJsonrpcError` and maps to HTTP status + JSON-RPC error response.
|
|
197
|
+
* Catches generic `Error` and maps to `internal_error` (-32603 → 500), including
|
|
198
|
+
* the error message in DEV only. Existing handlers that return `c.json()` directly
|
|
199
|
+
* are unaffected — the catch layer only activates when something is thrown.
|
|
200
|
+
*/
|
|
201
|
+
const wrap_error_catch = (handler, log) => {
|
|
202
|
+
return async (c, next) => {
|
|
203
|
+
try {
|
|
204
|
+
return await handler(c, next);
|
|
205
|
+
}
|
|
206
|
+
catch (err) {
|
|
207
|
+
if (err instanceof ThrownJsonrpcError) {
|
|
208
|
+
const status = jsonrpc_error_code_to_http_status(err.code);
|
|
209
|
+
const error = { code: err.code, message: err.message };
|
|
210
|
+
if (err.data !== undefined)
|
|
211
|
+
error.data = err.data;
|
|
212
|
+
return c.json({ error }, status);
|
|
213
|
+
}
|
|
214
|
+
// generic error — internal_error
|
|
215
|
+
log.error('Unhandled handler error', err);
|
|
216
|
+
const message = DEV && err instanceof Error ? err.message : 'internal server error';
|
|
217
|
+
return c.json({ error: { code: JSONRPC_ERROR_CODES.internal_error, message } }, 500);
|
|
218
|
+
}
|
|
219
|
+
};
|
|
220
|
+
};
|
|
188
221
|
/**
|
|
189
222
|
* Apply route specs to a Hono app.
|
|
190
223
|
*
|
|
191
224
|
* For each spec: resolves auth to guards via the provided resolver,
|
|
192
225
|
* adds input validation middleware (for routes with non-null input schemas),
|
|
193
|
-
* wraps handler with DEV-only output and error validation,
|
|
226
|
+
* wraps handler with DEV-only output and error validation, wraps with error
|
|
227
|
+
* catch layer (catches `ThrownJsonrpcError` and generic errors), and registers the route.
|
|
194
228
|
*
|
|
195
229
|
* Each handler receives a `RouteContext` with:
|
|
196
230
|
* - `db`: transaction-scoped (for non-GET) or pool-level (for GET)
|
|
@@ -215,7 +249,7 @@ export const apply_route_specs = (app, specs, resolve_auth_guards, log, db) => {
|
|
|
215
249
|
const guards = resolve_auth_guards(spec.auth);
|
|
216
250
|
const params_validation = create_params_validation(spec.params);
|
|
217
251
|
const query_validation = create_query_validation(spec.query);
|
|
218
|
-
const
|
|
252
|
+
const input_validation = create_input_validation(spec.input, spec.method);
|
|
219
253
|
const merged_errors = merge_error_schemas(spec);
|
|
220
254
|
// Step 1: adapt RouteHandler → Handler (construct RouteContext, call spec.handler)
|
|
221
255
|
const use_transaction = spec.transaction ?? spec.method !== 'GET';
|
|
@@ -225,7 +259,9 @@ export const apply_route_specs = (app, specs, resolve_auth_guards, log, db) => {
|
|
|
225
259
|
: (c) => inner(c, { db, background_db: db, pending_effects: c.var.pending_effects });
|
|
226
260
|
// Step 2: output validation
|
|
227
261
|
handler = wrap_output_validation(handler, spec.output, merged_errors, log);
|
|
228
|
-
|
|
262
|
+
// Step 3: error catch layer
|
|
263
|
+
handler = wrap_error_catch(handler, log);
|
|
264
|
+
app.on(spec.method, [spec.path], ...guards, ...params_validation, ...query_validation, ...input_validation, handler);
|
|
229
265
|
}
|
|
230
266
|
};
|
|
231
267
|
/**
|
|
@@ -13,9 +13,9 @@ import { type RateLimitKey, type RouteErrorSchemas } from './error_schemas.js';
|
|
|
13
13
|
/**
|
|
14
14
|
* Check if a schema is exactly `z.null()`.
|
|
15
15
|
*
|
|
16
|
-
* Uses
|
|
17
|
-
*
|
|
18
|
-
*
|
|
16
|
+
* Uses `instanceof` rather than runtime parsing to avoid false positives
|
|
17
|
+
* from `z.nullable(z.string())` or similar schemas that accept null
|
|
18
|
+
* but also accept other values.
|
|
19
19
|
*/
|
|
20
20
|
export declare const is_null_schema: (schema: z.ZodType) => boolean;
|
|
21
21
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/schema_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAuB,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAEnG;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,
|
|
1
|
+
{"version":3,"file":"schema_helpers.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/schema_helpers.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAuB,KAAK,YAAY,EAAE,KAAK,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;AAEnG;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAAsC,CAAC;AAE1F;;;;;GAKG;AACH,eAAO,MAAM,uBAAuB,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OACe,CAAC;AAE5E;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,GAAI,QAAQ,CAAC,CAAC,OAAO,KAAG,OAcrD,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,GAAI,SAAS,MAAM,EAAE,YAAY,MAAM,KAAG,OAQxE,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,mBAAmB,GAC/B,MAAM;IACL,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,CAAC,CAAC,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC;IACrB,KAAK,CAAC,EAAE,CAAC,CAAC,SAAS,CAAC;IACpB,UAAU,CAAC,EAAE,YAAY,CAAC;IAC1B,MAAM,CAAC,EAAE,iBAAiB,CAAC;CAC3B,EACD,oBAAoB,iBAAiB,GAAG,IAAI,KAC1C,iBAAiB,GAAG,IAUtB,CAAC"}
|
|
@@ -12,23 +12,18 @@ import { derive_error_schemas } from './error_schemas.js';
|
|
|
12
12
|
/**
|
|
13
13
|
* Check if a schema is exactly `z.null()`.
|
|
14
14
|
*
|
|
15
|
-
* Uses
|
|
16
|
-
*
|
|
17
|
-
*
|
|
15
|
+
* Uses `instanceof` rather than runtime parsing to avoid false positives
|
|
16
|
+
* from `z.nullable(z.string())` or similar schemas that accept null
|
|
17
|
+
* but also accept other values.
|
|
18
18
|
*/
|
|
19
|
-
export const is_null_schema = (schema) => schema
|
|
19
|
+
export const is_null_schema = (schema) => schema instanceof z.ZodNull;
|
|
20
20
|
/**
|
|
21
21
|
* Check if a schema is a strict object (`z.strictObject()`).
|
|
22
22
|
*
|
|
23
23
|
* Strict objects set `catchall` to `ZodNever` to reject unknown keys.
|
|
24
24
|
* Regular `z.object()` has `catchall: undefined` (strips unknown keys in Zod 4).
|
|
25
25
|
*/
|
|
26
|
-
export const is_strict_object_schema = (schema) =>
|
|
27
|
-
if (schema._zod.def.type !== 'object')
|
|
28
|
-
return false;
|
|
29
|
-
const catchall = schema._zod.def.catchall;
|
|
30
|
-
return catchall?._zod.def.type === 'never';
|
|
31
|
-
};
|
|
26
|
+
export const is_strict_object_schema = (schema) => schema instanceof z.ZodObject && schema.def.catchall instanceof z.ZodNever;
|
|
32
27
|
/**
|
|
33
28
|
* Convert a Zod schema to a JSON-serializable representation for the surface.
|
|
34
29
|
*
|
package/dist/http/surface.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import type { SseEventSpec } from '../realtime/sse.js';
|
|
|
11
11
|
import type { MiddlewareSpec } from './middleware_spec.js';
|
|
12
12
|
import type { RouteAuth, RouteSpec } from './route_spec.js';
|
|
13
13
|
import type { RateLimitKey, RouteErrorSchemas } from './error_schemas.js';
|
|
14
|
+
import type { RpcAction } from '../actions/action_rpc.js';
|
|
14
15
|
import type { Sensitivity } from '../sensitivity.js';
|
|
15
16
|
/** A route in the generated attack surface (JSON-serializable). */
|
|
16
17
|
export interface AppSurfaceRoute {
|
|
@@ -59,6 +60,22 @@ export interface AppSurfaceEvent {
|
|
|
59
60
|
channel: string | null;
|
|
60
61
|
params_schema: unknown;
|
|
61
62
|
}
|
|
63
|
+
/** A method within an RPC endpoint in the generated attack surface (JSON-serializable). */
|
|
64
|
+
export interface AppSurfaceRpcMethod {
|
|
65
|
+
name: string;
|
|
66
|
+
auth: RouteAuth;
|
|
67
|
+
/** JSON Schema representation of the input schema. `null` for null-input methods. */
|
|
68
|
+
input_schema: unknown;
|
|
69
|
+
/** JSON Schema representation of the output schema. */
|
|
70
|
+
output_schema: unknown;
|
|
71
|
+
side_effects: boolean;
|
|
72
|
+
description: string;
|
|
73
|
+
}
|
|
74
|
+
/** An RPC endpoint in the generated attack surface (JSON-serializable). */
|
|
75
|
+
export interface AppSurfaceRpcEndpoint {
|
|
76
|
+
path: string;
|
|
77
|
+
methods: Array<AppSurfaceRpcMethod>;
|
|
78
|
+
}
|
|
62
79
|
/** Assembly-time diagnostic collected during surface generation or server assembly. */
|
|
63
80
|
export interface AppSurfaceDiagnostic {
|
|
64
81
|
level: 'warning' | 'info';
|
|
@@ -70,6 +87,7 @@ export interface AppSurfaceDiagnostic {
|
|
|
70
87
|
export interface AppSurface {
|
|
71
88
|
middleware: Array<AppSurfaceMiddleware>;
|
|
72
89
|
routes: Array<AppSurfaceRoute>;
|
|
90
|
+
rpc_endpoints: Array<AppSurfaceRpcEndpoint>;
|
|
73
91
|
env: Array<AppSurfaceEnv>;
|
|
74
92
|
events: Array<AppSurfaceEvent>;
|
|
75
93
|
diagnostics: Array<AppSurfaceDiagnostic>;
|
|
@@ -84,6 +102,12 @@ export interface AppSurfaceSpec {
|
|
|
84
102
|
surface: AppSurface;
|
|
85
103
|
route_specs: Array<RouteSpec>;
|
|
86
104
|
middleware_specs: Array<MiddlewareSpec>;
|
|
105
|
+
rpc_endpoints: Array<RpcEndpointSpec>;
|
|
106
|
+
}
|
|
107
|
+
/** An RPC endpoint definition for surface generation. */
|
|
108
|
+
export interface RpcEndpointSpec {
|
|
109
|
+
path: string;
|
|
110
|
+
actions: Array<RpcAction>;
|
|
87
111
|
}
|
|
88
112
|
/** Options for `generate_app_surface`. */
|
|
89
113
|
export interface GenerateAppSurfaceOptions {
|
|
@@ -91,6 +115,7 @@ export interface GenerateAppSurfaceOptions {
|
|
|
91
115
|
middleware_specs: Array<MiddlewareSpec>;
|
|
92
116
|
env_schema?: z.ZodObject;
|
|
93
117
|
event_specs?: Array<SseEventSpec>;
|
|
118
|
+
rpc_endpoints?: Array<RpcEndpointSpec>;
|
|
94
119
|
}
|
|
95
120
|
/**
|
|
96
121
|
* Collect error schemas from all middleware that applies to a route path.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"surface.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/surface.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAC,CAAC,EAAC,MAAM,KAAK,CAAC;AAEtB,OAAO,KAAK,EAAC,YAAY,EAAC,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAC,cAAc,EAAC,MAAM,sBAAsB,CAAC;AACzD,OAAO,KAAK,EAAC,SAAS,EAAE,SAAS,EAAC,MAAM,iBAAiB,CAAC;AAC1D,OAAO,KAAK,EAAC,YAAY,EAAE,iBAAiB,EAAC,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"surface.d.ts","sourceRoot":"../src/lib/","sources":["../../src/lib/http/surface.ts"],"names":[],"mappings":"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"}
|