@fougere/transport-http 0.2.0-alpha.2 → 0.3.0-alpha.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/client.d.ts +31 -4
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +47 -6
- package/dist/client.js.map +1 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/policy.d.ts +24 -0
- package/dist/policy.d.ts.map +1 -0
- package/dist/policy.js +26 -0
- package/dist/policy.js.map +1 -0
- package/dist/receive.d.ts +33 -0
- package/dist/receive.d.ts.map +1 -0
- package/dist/receive.js +78 -0
- package/dist/receive.js.map +1 -0
- package/dist/serve.d.ts +13 -1
- package/dist/serve.d.ts.map +1 -1
- package/dist/serve.js +26 -11
- package/dist/serve.js.map +1 -1
- package/dist/server.d.ts +20 -2
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +39 -3
- package/dist/server.js.map +1 -1
- package/package.json +8 -4
package/dist/client.d.ts
CHANGED
|
@@ -5,18 +5,45 @@
|
|
|
5
5
|
* typed error (SERVICE_UNAVAILABLE, GATEWAY_TIMEOUT, BAD_GATEWAY), an
|
|
6
6
|
* application failure comes back as the FougereError the façade threw.
|
|
7
7
|
*/
|
|
8
|
-
import { type Transport, type FrondCall, type InvocationContext } from '@fougere/core/contract';
|
|
9
|
-
import type { RpcRequest
|
|
8
|
+
import { type Transport, type FrondCall, type InvocationContext, type SignedCall } from '@fougere/core/contract';
|
|
9
|
+
import type { RpcRequest } from './jsonrpc.js';
|
|
10
10
|
export type { RpcRequest, RpcResponse } from './jsonrpc.js';
|
|
11
11
|
/** Frame a call as a JSON-RPC request. */
|
|
12
12
|
export declare function frameCall(call: FrondCall, invocation: InvocationContext, id: number): RpcRequest;
|
|
13
|
-
/**
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Unframe a JSON-RPC response — the result, or the revived FougereError thrown.
|
|
15
|
+
*
|
|
16
|
+
* The answer is JUDGED first: it crossed a process boundary, and `as RpcResponse` at the
|
|
17
|
+
* call site is a claim about it, not a check. A 200 carrying neither `result` nor `error`
|
|
18
|
+
* — a proxy's own JSON, a receiver that is not one — used to return `undefined` as if the
|
|
19
|
+
* op had succeeded, and a `null` body raised `Cannot use 'in' operator`, which is not the
|
|
20
|
+
* failure vocabulary this file promises.
|
|
21
|
+
*/
|
|
22
|
+
export declare function unframeResponse(response: unknown, call: FrondCall): unknown;
|
|
15
23
|
export interface HttpTransportOptions {
|
|
16
24
|
/** Abort a call after this long. A timed-out call may have executed — it is never retried. */
|
|
17
25
|
timeoutMs?: number;
|
|
18
26
|
/** Extra attempts on connection failures only — the request provably never left. */
|
|
19
27
|
retries?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Signs the state this transport sends, turning a claim into something the receiver
|
|
30
|
+
* can check. Supplied rather than built here: signing is `node:crypto`, and this
|
|
31
|
+
* module is published as the browser-safe `/client` subpath — a browser holds no key
|
|
32
|
+
* and never signs. `@fougere/app` wires it from `signEnvelope`.
|
|
33
|
+
*
|
|
34
|
+
* Absent, the state travels as a bare claim and only a receiver that asks for nothing
|
|
35
|
+
* will take it.
|
|
36
|
+
*/
|
|
37
|
+
sign?: (call: SignedCall) => Promise<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Who performs the request. Defaults to the global `fetch`.
|
|
40
|
+
*
|
|
41
|
+
* A Cloudflare service binding answers this shape (`env.CATALOG.fetch`), and on that
|
|
42
|
+
* platform it is not an optimization: a Worker calling a sibling's public URL is
|
|
43
|
+
* refused by the edge (error 1042), so a binding is the only route between two Workers
|
|
44
|
+
* of one account. Nothing else about the call changes — same envelope, same retries.
|
|
45
|
+
*/
|
|
46
|
+
fetch?: (input: string, init: RequestInit) => Promise<Response>;
|
|
20
47
|
}
|
|
21
48
|
export declare function createHttpTransport(baseUrl: string, options?: HttpTransportOptions): Transport;
|
|
22
49
|
//# sourceMappingURL=client.d.ts.map
|
package/dist/client.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAA2B,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAA2B,KAAK,SAAS,EAAE,KAAK,SAAS,EAAE,KAAK,iBAAiB,EAAE,KAAK,UAAU,EAAE,MAAM,wBAAwB,CAAC;AAC1I,OAAO,KAAK,EAAE,UAAU,EAA8B,MAAM,cAAc,CAAC;AAC3E,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE5D,0CAA0C;AAC1C,wBAAgB,SAAS,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,iBAAiB,EAAE,EAAE,EAAE,MAAM,GAAG,UAAU,CAEhG;AAED;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,SAAS,GAAG,OAAO,CA4B3E;AAED,MAAM,WAAW,oBAAoB;IACnC,8FAA8F;IAC9F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oFAAoF;IACpF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;;;OAQG;IACH,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,UAAU,KAAK,OAAO,CAAC,MAAM,CAAC,CAAC;IAC7C;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAC;CACjE;AAKD,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,oBAAyB,GAAG,SAAS,CA6ElG"}
|
package/dist/client.js
CHANGED
|
@@ -10,14 +10,39 @@ import { FougereError, ErrorCode } from '@fougere/core/contract';
|
|
|
10
10
|
export function frameCall(call, invocation, id) {
|
|
11
11
|
return { jsonrpc: '2.0', id, method: `${call.entity}.${call.op}`, params: invocation };
|
|
12
12
|
}
|
|
13
|
-
/**
|
|
13
|
+
/**
|
|
14
|
+
* Unframe a JSON-RPC response — the result, or the revived FougereError thrown.
|
|
15
|
+
*
|
|
16
|
+
* The answer is JUDGED first: it crossed a process boundary, and `as RpcResponse` at the
|
|
17
|
+
* call site is a claim about it, not a check. A 200 carrying neither `result` nor `error`
|
|
18
|
+
* — a proxy's own JSON, a receiver that is not one — used to return `undefined` as if the
|
|
19
|
+
* op had succeeded, and a `null` body raised `Cannot use 'in' operator`, which is not the
|
|
20
|
+
* failure vocabulary this file promises.
|
|
21
|
+
*/
|
|
14
22
|
export function unframeResponse(response, call) {
|
|
23
|
+
if (!response || typeof response !== 'object' || !('result' in response || 'error' in response)) {
|
|
24
|
+
throw new FougereError({
|
|
25
|
+
code: ErrorCode.BAD_GATEWAY,
|
|
26
|
+
message: 'Answered neither a result nor an error — not a Fougere receiver?',
|
|
27
|
+
entity: call.entity,
|
|
28
|
+
operation: call.op,
|
|
29
|
+
});
|
|
30
|
+
}
|
|
15
31
|
if ('error' in response) {
|
|
16
|
-
|
|
17
|
-
|
|
32
|
+
const error = response.error;
|
|
33
|
+
if (!error || typeof error !== 'object') {
|
|
34
|
+
throw new FougereError({
|
|
35
|
+
code: ErrorCode.BAD_GATEWAY,
|
|
36
|
+
message: 'Answered an error that is not a JSON-RPC error object',
|
|
37
|
+
entity: call.entity,
|
|
38
|
+
operation: call.op,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
if (error.data !== undefined)
|
|
42
|
+
throw FougereError.fromJSON(error.data);
|
|
18
43
|
throw new FougereError({
|
|
19
44
|
code: ErrorCode.INTERNAL_ERROR,
|
|
20
|
-
message: `${
|
|
45
|
+
message: `${error.message} (rpc ${error.code})`,
|
|
21
46
|
entity: call.entity,
|
|
22
47
|
operation: call.op,
|
|
23
48
|
});
|
|
@@ -28,15 +53,31 @@ export function unframeResponse(response, call) {
|
|
|
28
53
|
const CONNECTION_FAILURES = new Set(['ECONNREFUSED', 'ENOTFOUND', 'EAI_AGAIN']);
|
|
29
54
|
export function createHttpTransport(baseUrl, options = {}) {
|
|
30
55
|
const url = `${baseUrl.replace(/\/$/, '')}/_fougere/call`;
|
|
56
|
+
// Who performs the request, when it is not the global one. A Cloudflare service binding
|
|
57
|
+
// is exactly this shape — and on that platform it is the ONLY way two Workers of one
|
|
58
|
+
// account reach each other: measured, a Worker fetching a sibling's public URL is
|
|
59
|
+
// refused by the edge with error 1042 before the request leaves. The framing above and
|
|
60
|
+
// below is identical either way, which is the whole reason this is one option and not
|
|
61
|
+
// a second transport.
|
|
62
|
+
const send = options.fetch ?? fetch;
|
|
31
63
|
const timeoutMs = options.timeoutMs ?? 10_000;
|
|
32
64
|
const retries = options.retries ?? 1;
|
|
33
65
|
let nextId = 1;
|
|
34
66
|
return async (call, invocation) => {
|
|
35
|
-
|
|
67
|
+
// The envelope REPLACES the state on the wire — sending both would leave the
|
|
68
|
+
// receiver choosing between a proof and a claim about the same thing.
|
|
69
|
+
// `caller` is dropped on every hop: it names who signed THIS call, so carrying the
|
|
70
|
+
// one this process was handed would make `shop → catalog → billing` read `shop`.
|
|
71
|
+
// It travels outside the envelope anyway, so a stale one would be unsigned too.
|
|
72
|
+
const { caller: _established, ...forwarded } = invocation;
|
|
73
|
+
const sent = options.sign
|
|
74
|
+
? { ...forwarded, state: {}, identity: await options.sign({ ...call, ...invocation }) }
|
|
75
|
+
: forwarded;
|
|
76
|
+
const request = frameCall(call, sent, nextId++);
|
|
36
77
|
for (let attempt = 0;; attempt++) {
|
|
37
78
|
let res;
|
|
38
79
|
try {
|
|
39
|
-
res = await
|
|
80
|
+
res = await send(url, {
|
|
40
81
|
method: 'POST',
|
|
41
82
|
headers: { 'content-type': 'application/json' },
|
|
42
83
|
body: JSON.stringify(request),
|
package/dist/client.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,YAAY,EAAE,SAAS,
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { createHttpTransport, frameCall, unframeResponse, type HttpTransportOptions } from './client.js';
|
|
2
|
-
export { handleRpc } from './server.js';
|
|
2
|
+
export { handleRpc, type ReceiveOptions } from './server.js';
|
|
3
|
+
export { receive, type ReceiveHttpOptions } from './receive.js';
|
|
4
|
+
export { CALL_PATH, MAX_BODY_BYTES } from './policy.js';
|
|
3
5
|
export { serve, type ServeOptions, type RunningReceiver } from './serve.js';
|
|
4
6
|
export { APP_ERROR, PARSE_ERROR, INVALID_REQUEST } from './jsonrpc.js';
|
|
5
7
|
export type { RpcRequest, RpcResponse, RpcErrorShape } from './jsonrpc.js';
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACzG,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,eAAe,EAAE,KAAK,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACzG,OAAO,EAAE,SAAS,EAAE,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,KAAK,kBAAkB,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,KAAK,EAAE,KAAK,YAAY,EAAE,KAAK,eAAe,EAAE,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACvE,YAAY,EAAE,UAAU,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
export { createHttpTransport, frameCall, unframeResponse } from './client.js';
|
|
2
2
|
export { handleRpc } from './server.js';
|
|
3
|
+
export { receive } from './receive.js';
|
|
4
|
+
export { CALL_PATH, MAX_BODY_BYTES } from './policy.js';
|
|
3
5
|
export { serve } from './serve.js';
|
|
4
6
|
export { APP_ERROR, PARSE_ERROR, INVALID_REQUEST } from './jsonrpc.js';
|
|
5
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,eAAe,EAA6B,MAAM,aAAa,CAAC;AACzG,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,SAAS,EAAE,eAAe,EAA6B,MAAM,aAAa,CAAC;AACzG,OAAO,EAAE,SAAS,EAAuB,MAAM,aAAa,CAAC;AAC7D,OAAO,EAAE,OAAO,EAA2B,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAE,KAAK,EAA2C,MAAM,YAAY,CAAC;AAC5E,OAAO,EAAE,SAAS,EAAE,WAAW,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC"}
|
package/dist/policy.d.ts
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What every receiver of the envelope decides the same way, and what it does not.
|
|
3
|
+
*
|
|
4
|
+
* The cap and the answers are POLICY — `1024 * 1024` was spelled in four packages and
|
|
5
|
+
* omitted by the receiver written by hand. Reading the body is PLUMBING, and it belongs to
|
|
6
|
+
* the transport: a `node:http` stream and a `Request` body are read differently, and putting
|
|
7
|
+
* Node through the Web reader HALVED the door that took it (measured, 2026-08-22: the JSON-RPC
|
|
8
|
+
* door fell from 0.677 to 0.341 of its hand-written baseline, while the REST door, which never
|
|
9
|
+
* traverses `serve()`, sat at 0.653 in that same run).
|
|
10
|
+
*
|
|
11
|
+
* So this file holds the decisions. Each receiver keeps its own reader.
|
|
12
|
+
*/
|
|
13
|
+
import { type RpcResponse } from './jsonrpc.js';
|
|
14
|
+
/** What a receiver accepts before it stops reading. */
|
|
15
|
+
export declare const MAX_BODY_BYTES: number;
|
|
16
|
+
/** The path the envelope answers on. A host mounting it elsewhere passes its own. */
|
|
17
|
+
export declare const CALL_PATH = "/_fougere/call";
|
|
18
|
+
/** The answer to a payload that was not JSON. */
|
|
19
|
+
export declare const parseError: () => RpcResponse;
|
|
20
|
+
/** The answer to a body over the cap. */
|
|
21
|
+
export declare const tooLarge: () => {
|
|
22
|
+
error: string;
|
|
23
|
+
};
|
|
24
|
+
//# sourceMappingURL=policy.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.d.ts","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAe,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAE7D,uDAAuD;AACvD,eAAO,MAAM,cAAc,QAAc,CAAC;AAE1C,qFAAqF;AACrF,eAAO,MAAM,SAAS,mBAAmB,CAAC;AAE1C,iDAAiD;AACjD,eAAO,MAAM,UAAU,QAAO,WAI5B,CAAC;AAEH,yCAAyC;AACzC,eAAO,MAAM,QAAQ;IAAY,KAAK;CAAwB,CAAC"}
|
package/dist/policy.js
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What every receiver of the envelope decides the same way, and what it does not.
|
|
3
|
+
*
|
|
4
|
+
* The cap and the answers are POLICY — `1024 * 1024` was spelled in four packages and
|
|
5
|
+
* omitted by the receiver written by hand. Reading the body is PLUMBING, and it belongs to
|
|
6
|
+
* the transport: a `node:http` stream and a `Request` body are read differently, and putting
|
|
7
|
+
* Node through the Web reader HALVED the door that took it (measured, 2026-08-22: the JSON-RPC
|
|
8
|
+
* door fell from 0.677 to 0.341 of its hand-written baseline, while the REST door, which never
|
|
9
|
+
* traverses `serve()`, sat at 0.653 in that same run).
|
|
10
|
+
*
|
|
11
|
+
* So this file holds the decisions. Each receiver keeps its own reader.
|
|
12
|
+
*/
|
|
13
|
+
import { PARSE_ERROR } from './jsonrpc.js';
|
|
14
|
+
/** What a receiver accepts before it stops reading. */
|
|
15
|
+
export const MAX_BODY_BYTES = 1024 * 1024;
|
|
16
|
+
/** The path the envelope answers on. A host mounting it elsewhere passes its own. */
|
|
17
|
+
export const CALL_PATH = '/_fougere/call';
|
|
18
|
+
/** The answer to a payload that was not JSON. */
|
|
19
|
+
export const parseError = () => ({
|
|
20
|
+
jsonrpc: '2.0',
|
|
21
|
+
id: null,
|
|
22
|
+
error: { code: PARSE_ERROR, message: 'Parse error' },
|
|
23
|
+
});
|
|
24
|
+
/** The answer to a body over the cap. */
|
|
25
|
+
export const tooLarge = () => ({ error: 'Payload too large' });
|
|
26
|
+
//# sourceMappingURL=policy.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"policy.js","sourceRoot":"","sources":["../src/policy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AACH,OAAO,EAAE,WAAW,EAAoB,MAAM,cAAc,CAAC;AAE7D,uDAAuD;AACvD,MAAM,CAAC,MAAM,cAAc,GAAG,IAAI,GAAG,IAAI,CAAC;AAE1C,qFAAqF;AACrF,MAAM,CAAC,MAAM,SAAS,GAAG,gBAAgB,CAAC;AAE1C,iDAAiD;AACjD,MAAM,CAAC,MAAM,UAAU,GAAG,GAAgB,EAAE,CAAC,CAAC;IAC5C,OAAO,EAAE,KAAK;IACd,EAAE,EAAE,IAAI;IACR,KAAK,EAAE,EAAE,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAE;CACrD,CAAC,CAAC;AAEH,yCAAyC;AACzC,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,mBAAmB,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The envelope door for a host that speaks `Request`/`Response` — hono, a Worker, Next,
|
|
3
|
+
* SvelteKit. It reads a `Request` body; `serve` reads a `node:http` stream, and the two
|
|
4
|
+
* stay separate on purpose: putting Node through this reader HALVED the Node door
|
|
5
|
+
* (0.677 → 0.341 of its baseline, measured 2026-08-22).
|
|
6
|
+
*
|
|
7
|
+
* What they share is `policy.ts` — the cap and the answers. Nothing here is edge-specific
|
|
8
|
+
* beyond that: `handleRpc` is the wire and knows no HTTP at all.
|
|
9
|
+
*/
|
|
10
|
+
import { type ReceiveOptions } from './server.js';
|
|
11
|
+
import type { Transport } from '@fougere/core/contract';
|
|
12
|
+
export interface ReceiveHttpOptions extends ReceiveOptions {
|
|
13
|
+
/** Maximum JSON-RPC body size. Default: 1 MiB. */
|
|
14
|
+
maxBodyBytes?: number;
|
|
15
|
+
/** The path this door answers. Default: `/_fougere/call`. */
|
|
16
|
+
path?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Take unsigned calls, deliberately.
|
|
19
|
+
*
|
|
20
|
+
* `serve()` reads the decision off the ADDRESS — loopback by default, and widening it
|
|
21
|
+
* is written down. This door binds nothing: its host mounts it wherever it likes, and a
|
|
22
|
+
* `Request` arrives with no bound address to consult. So the decision has to be stated,
|
|
23
|
+
* and the default is the safe one: with no `verify` and no word here, this REFUSES to
|
|
24
|
+
* be built. A door that starts and then believes whatever `state` it is handed is the
|
|
25
|
+
* hole `identity.ts` exists to close, and it was open here.
|
|
26
|
+
*
|
|
27
|
+
* The one case that legitimately needs it beyond local development is the same as
|
|
28
|
+
* `serve`'s: something in front already established the peer.
|
|
29
|
+
*/
|
|
30
|
+
allowUnsigned?: boolean;
|
|
31
|
+
}
|
|
32
|
+
export declare function receive(runner: Transport, options?: ReceiveHttpOptions): (request: Request) => Promise<Response>;
|
|
33
|
+
//# sourceMappingURL=receive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receive.d.ts","sourceRoot":"","sources":["../src/receive.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAExD,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IACxD,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AA4CD,wBAAgB,OAAO,CACrB,MAAM,EAAE,SAAS,EACjB,OAAO,GAAE,kBAAuB,GAC/B,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CA+BzC"}
|
package/dist/receive.js
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The envelope door for a host that speaks `Request`/`Response` — hono, a Worker, Next,
|
|
3
|
+
* SvelteKit. It reads a `Request` body; `serve` reads a `node:http` stream, and the two
|
|
4
|
+
* stay separate on purpose: putting Node through this reader HALVED the Node door
|
|
5
|
+
* (0.677 → 0.341 of its baseline, measured 2026-08-22).
|
|
6
|
+
*
|
|
7
|
+
* What they share is `policy.ts` — the cap and the answers. Nothing here is edge-specific
|
|
8
|
+
* beyond that: `handleRpc` is the wire and knows no HTTP at all.
|
|
9
|
+
*/
|
|
10
|
+
import { handleRpc } from './server.js';
|
|
11
|
+
import { MAX_BODY_BYTES, CALL_PATH, parseError, tooLarge } from './policy.js';
|
|
12
|
+
const json = (body, status = 200) => new Response(JSON.stringify(body), { status, headers: { 'content-type': 'application/json' } });
|
|
13
|
+
/** Distinguishes "the body was too large" from any body a caller could actually send. */
|
|
14
|
+
const TOO_LARGE = Symbol('too large');
|
|
15
|
+
/**
|
|
16
|
+
* The declared length is a cheap refusal; the count is the real one. A `content-length` may
|
|
17
|
+
* be absent, and it may lie — the copy that trusted it alone had no cap at all in that case.
|
|
18
|
+
*/
|
|
19
|
+
async function bodyWithin(request, max) {
|
|
20
|
+
const declared = Number(request.headers.get('content-length'));
|
|
21
|
+
if (Number.isFinite(declared) && declared > max)
|
|
22
|
+
return TOO_LARGE;
|
|
23
|
+
const reader = request.body?.getReader();
|
|
24
|
+
if (!reader)
|
|
25
|
+
return '';
|
|
26
|
+
const chunks = [];
|
|
27
|
+
let size = 0;
|
|
28
|
+
for (;;) {
|
|
29
|
+
const { done, value } = await reader.read();
|
|
30
|
+
if (done)
|
|
31
|
+
break;
|
|
32
|
+
size += value.byteLength;
|
|
33
|
+
if (size > max) {
|
|
34
|
+
await reader.cancel();
|
|
35
|
+
return TOO_LARGE;
|
|
36
|
+
}
|
|
37
|
+
chunks.push(value);
|
|
38
|
+
}
|
|
39
|
+
return new TextDecoder().decode(concat(chunks, size));
|
|
40
|
+
}
|
|
41
|
+
function concat(chunks, size) {
|
|
42
|
+
const all = new Uint8Array(size);
|
|
43
|
+
let at = 0;
|
|
44
|
+
for (const chunk of chunks) {
|
|
45
|
+
all.set(chunk, at);
|
|
46
|
+
at += chunk.byteLength;
|
|
47
|
+
}
|
|
48
|
+
return all;
|
|
49
|
+
}
|
|
50
|
+
export function receive(runner, options = {}) {
|
|
51
|
+
// At CONSTRUCTION and not per call, for the reason `serve` refuses at bind: a receiver
|
|
52
|
+
// that starts and then rejects everything is found in production.
|
|
53
|
+
if (!options.verify && !options.allowUnsigned) {
|
|
54
|
+
throw new Error('A Fougere receiver takes the `state` it is handed, so this door needs to know who is calling.\n'
|
|
55
|
+
+ ' Wire `verify` (see `verifyEnvelope`, and `fougere keys` / `fougere grant`),\n'
|
|
56
|
+
+ ' or say `allowUnsigned: true` — which is right for local development and for a\n'
|
|
57
|
+
+ ' mesh whose sidecar already established the peer.');
|
|
58
|
+
}
|
|
59
|
+
const max = options.maxBodyBytes ?? MAX_BODY_BYTES;
|
|
60
|
+
const path = options.path ?? CALL_PATH;
|
|
61
|
+
return async (request) => {
|
|
62
|
+
if (request.method !== 'POST' || new URL(request.url).pathname !== path) {
|
|
63
|
+
return new Response(null, { status: 404 });
|
|
64
|
+
}
|
|
65
|
+
const raw = await bodyWithin(request, max);
|
|
66
|
+
if (raw === TOO_LARGE)
|
|
67
|
+
return json(tooLarge(), 413);
|
|
68
|
+
let parsed;
|
|
69
|
+
try {
|
|
70
|
+
parsed = JSON.parse(raw);
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return json(parseError());
|
|
74
|
+
}
|
|
75
|
+
return json(await handleRpc(runner, parsed, options));
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
//# sourceMappingURL=receive.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"receive.js","sourceRoot":"","sources":["../src/receive.ts"],"names":[],"mappings":"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"}
|
package/dist/serve.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Transport } from '@fougere/core';
|
|
2
|
-
|
|
2
|
+
import { type ReceiveOptions } from './server.js';
|
|
3
|
+
export interface ServeOptions extends ReceiveOptions {
|
|
3
4
|
/** Port to listen on. 0 (default) picks a free one. */
|
|
4
5
|
port?: number;
|
|
5
6
|
/**
|
|
@@ -13,6 +14,17 @@ export interface ServeOptions {
|
|
|
13
14
|
hosts?: string[];
|
|
14
15
|
/** Which address to bind. Must be one of `hosts`. Defaults to its first. */
|
|
15
16
|
host?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Serve unsigned calls beyond loopback, deliberately.
|
|
19
|
+
*
|
|
20
|
+
* The one case that legitimately needs it: something in front already established the
|
|
21
|
+
* peer — a service mesh whose sidecar terminated mTLS, an ingress doing client certs.
|
|
22
|
+
* Asking for a second signature there would redo what was just done a centimetre away.
|
|
23
|
+
*
|
|
24
|
+
* It is spelled separately from `requireIdentity` on purpose: that one arrives `false`
|
|
25
|
+
* by default from `identityFromEnv`, so it cannot also mean "I thought about this".
|
|
26
|
+
*/
|
|
27
|
+
allowUnsigned?: boolean;
|
|
16
28
|
/** Maximum JSON-RPC body size. Default: 1 MiB. */
|
|
17
29
|
maxBodyBytes?: number;
|
|
18
30
|
/** Time allowed to receive a request. Default: 15 seconds. */
|
package/dist/serve.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"serve.d.ts","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE/C,OAAO,EAAa,KAAK,cAAc,EAAE,MAAM,aAAa,CAAC;AAG7D,MAAM,WAAW,YAAa,SAAQ,cAAc;IAClD,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,4EAA4E;IAC5E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;OASG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,kDAAkD;IAClD,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8DAA8D;IAC9D,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,qDAAqD;AACrD,eAAO,MAAM,cAAc,UAAoC,CAAC;AAEhE,wBAAgB,KAAK,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,GAAE,YAAiB,GAAG,OAAO,CAAC,eAAe,CAAC,CA6E7F"}
|
package/dist/serve.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* half inside an existing server (@fougere/http, Nitro) is layer-2 work.
|
|
6
6
|
*/
|
|
7
7
|
import { createServer } from 'node:http';
|
|
8
|
-
import { PARSE_ERROR } from './jsonrpc.js';
|
|
9
8
|
import { handleRpc } from './server.js';
|
|
9
|
+
import { MAX_BODY_BYTES, CALL_PATH, parseError, tooLarge } from './policy.js';
|
|
10
10
|
/** What a frond binds when nobody says otherwise. */
|
|
11
11
|
export const LOOPBACK_HOSTS = ['127.0.0.1', 'localhost', '::1'];
|
|
12
12
|
export function serve(runner, options = {}) {
|
|
@@ -15,17 +15,32 @@ export function serve(runner, options = {}) {
|
|
|
15
15
|
return Promise.reject(new Error('A Fougere receiver needs at least one host to bind, `hosts` is empty'));
|
|
16
16
|
}
|
|
17
17
|
const host = options.host ?? allowed[0];
|
|
18
|
-
//
|
|
19
|
-
// the
|
|
20
|
-
//
|
|
21
|
-
// rather than inferred
|
|
22
|
-
// claim any user — so the answer stays identity at the Frond.
|
|
18
|
+
// Where a receiver binds, and what it admits, are two questions now. `verify` answers
|
|
19
|
+
// the second — without it this receiver still takes the `state` it is handed, and
|
|
20
|
+
// `hosts` is all that stands. The default keeps it on the machine; widening it is
|
|
21
|
+
// written down rather than inferred, and a widened receiver wants `requireIdentity`.
|
|
23
22
|
if (!allowed.includes(host)) {
|
|
24
23
|
return Promise.reject(new Error(`A Fougere receiver binds one of [${allowed.join(', ')}], got '${host}' — add it to \`hosts\` to allow it`));
|
|
25
24
|
}
|
|
26
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Loopback or signed — there is no third way to serve.
|
|
27
|
+
*
|
|
28
|
+
* The address already carries the decision: binding beyond loopback is a deliberate
|
|
29
|
+
* act (`hosts` says so), and a receiver reachable from outside that establishes nothing
|
|
30
|
+
* takes the `state` it is handed. Refusing at BOOT and not per call is the point — a
|
|
31
|
+
* receiver that starts and then rejects everything is discovered in production, one
|
|
32
|
+
* that will not start is discovered at deployment.
|
|
33
|
+
*/
|
|
34
|
+
if (!LOOPBACK_HOSTS.includes(host) && !options.verify && !options.allowUnsigned) {
|
|
35
|
+
return Promise.reject(new Error(`A Fougere receiver on '${host}' is reachable from outside this machine and would believe whatever `
|
|
36
|
+
+ 'state it is handed.\n'
|
|
37
|
+
+ ' - `fougere keys` once, then inject FOUGERE_ROOT here (and `fougere grant <frond>` for each caller), or\n'
|
|
38
|
+
+ ' - keep it on loopback, or\n'
|
|
39
|
+
+ ' - pass `allowUnsigned: true` if a mesh or an ingress already authenticated the caller.'));
|
|
40
|
+
}
|
|
41
|
+
const maxBodyBytes = options.maxBodyBytes ?? MAX_BODY_BYTES;
|
|
27
42
|
const server = createServer(async (req, res) => {
|
|
28
|
-
if (req.method !== 'POST' || req.url !==
|
|
43
|
+
if (req.method !== 'POST' || req.url !== CALL_PATH) {
|
|
29
44
|
res.writeHead(404).end();
|
|
30
45
|
return;
|
|
31
46
|
}
|
|
@@ -35,7 +50,7 @@ export function serve(runner, options = {}) {
|
|
|
35
50
|
const chunk = Buffer.from(value);
|
|
36
51
|
size += chunk.length;
|
|
37
52
|
if (size > maxBodyBytes) {
|
|
38
|
-
res.writeHead(413, { 'content-type': 'application/json' }).end(JSON.stringify(
|
|
53
|
+
res.writeHead(413, { 'content-type': 'application/json' }).end(JSON.stringify(tooLarge()));
|
|
39
54
|
return;
|
|
40
55
|
}
|
|
41
56
|
chunks.push(chunk);
|
|
@@ -43,10 +58,10 @@ export function serve(runner, options = {}) {
|
|
|
43
58
|
let response;
|
|
44
59
|
try {
|
|
45
60
|
const raw = JSON.parse(Buffer.concat(chunks).toString('utf8'));
|
|
46
|
-
response = await handleRpc(runner, raw);
|
|
61
|
+
response = await handleRpc(runner, raw, options);
|
|
47
62
|
}
|
|
48
63
|
catch {
|
|
49
|
-
response =
|
|
64
|
+
response = parseError();
|
|
50
65
|
}
|
|
51
66
|
res.writeHead(200, { 'content-type': 'application/json' }).end(JSON.stringify(response));
|
|
52
67
|
});
|
package/dist/serve.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../src/serve.ts"],"names":[],"mappings":"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"}
|
package/dist/server.d.ts
CHANGED
|
@@ -4,7 +4,25 @@
|
|
|
4
4
|
* Judges nothing: validation and middlewares live with the handler, inside
|
|
5
5
|
* the runner. The error a façade throws is framed whole, never flattened.
|
|
6
6
|
*/
|
|
7
|
-
import { type Transport } from '@fougere/core';
|
|
7
|
+
import { type SignedCall, type Transport } from '@fougere/core/contract';
|
|
8
8
|
import { type RpcResponse } from './jsonrpc.js';
|
|
9
|
-
|
|
9
|
+
/** What a receiver does with the caller's envelope. */
|
|
10
|
+
export interface ReceiveOptions {
|
|
11
|
+
/**
|
|
12
|
+
* Establishes who signed, or throws. Supplied rather than built here for the reason
|
|
13
|
+
* the sender's `sign` is: verifying is `node:crypto` and this package carries none.
|
|
14
|
+
* `@fougere/app` wires it from `verifyEnvelope` and the root public key.
|
|
15
|
+
*/
|
|
16
|
+
verify?: (identity: string, presented: SignedCall) => Promise<{
|
|
17
|
+
caller: string;
|
|
18
|
+
state: Record<string, unknown>;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Refuse a call carrying no verifiable identity — the whole of "secure by default"
|
|
22
|
+
* at the wire. Without it a receiver takes the state it is handed and its only
|
|
23
|
+
* protection is the address it bound.
|
|
24
|
+
*/
|
|
25
|
+
requireIdentity?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export declare function handleRpc(runner: Transport, raw: unknown, options?: ReceiveOptions): Promise<RpcResponse>;
|
|
10
28
|
//# sourceMappingURL=server.d.ts.map
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAkE,KAAK,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAkE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACzI,OAAO,EAA+C,KAAK,WAAW,EAAE,MAAM,cAAc,CAAC;AAE7F,uDAAuD;AACvD,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,MAAM,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,SAAS,EAAE,UAAU,KAAK,OAAO,CAAC;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAA;KAAE,CAAC,CAAC;IAClH;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,wBAAsB,SAAS,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,EAAE,OAAO,EAAE,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,WAAW,CAAC,CA0EnH"}
|
package/dist/server.js
CHANGED
|
@@ -4,9 +4,9 @@
|
|
|
4
4
|
* Judges nothing: validation and middlewares live with the handler, inside
|
|
5
5
|
* the runner. The error a façade throws is framed whole, never flattened.
|
|
6
6
|
*/
|
|
7
|
-
import { FougereError, ErrorCode, toPublicError } from '@fougere/core';
|
|
7
|
+
import { FougereError, ErrorCode, toPublicError } from '@fougere/core/contract';
|
|
8
8
|
import { APP_ERROR, INVALID_REQUEST } from './jsonrpc.js';
|
|
9
|
-
export async function handleRpc(runner, raw) {
|
|
9
|
+
export async function handleRpc(runner, raw, options = {}) {
|
|
10
10
|
const req = raw;
|
|
11
11
|
const id = typeof req?.id === 'number' || typeof req?.id === 'string' ? req.id : null;
|
|
12
12
|
if (!req || req.jsonrpc !== '2.0' || typeof req.method !== 'string' || id === null) {
|
|
@@ -24,11 +24,42 @@ export async function handleRpc(runner, raw) {
|
|
|
24
24
|
const op = req.method.slice(dot + 1);
|
|
25
25
|
// Fresh objects — middlewares deposit into state, nothing may be shared.
|
|
26
26
|
const sent = (req.params ?? {});
|
|
27
|
+
/**
|
|
28
|
+
* State is ESTABLISHED here, or it is only claimed.
|
|
29
|
+
*
|
|
30
|
+
* `sent.state` is what the caller typed; a verified envelope is what it can prove, and
|
|
31
|
+
* when a verifier is wired the envelope REPLACES the claim rather than enriching it —
|
|
32
|
+
* carrying both would leave every reader downstream choosing between them.
|
|
33
|
+
*/
|
|
34
|
+
let state = sent.state ?? {};
|
|
35
|
+
let caller;
|
|
36
|
+
if (options.verify && sent.identity) {
|
|
37
|
+
try {
|
|
38
|
+
// What ARRIVED, never what we would rather it had been — the comparison is the point.
|
|
39
|
+
({ caller, state } = await options.verify(sent.identity, {
|
|
40
|
+
entity,
|
|
41
|
+
op,
|
|
42
|
+
params: sent.params ?? {},
|
|
43
|
+
query: sent.query ?? {},
|
|
44
|
+
body: sent.body,
|
|
45
|
+
}));
|
|
46
|
+
}
|
|
47
|
+
catch (err) {
|
|
48
|
+
return refused(id, err?.message ?? 'unverifiable identity', entity, op);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
else if (options.requireIdentity) {
|
|
52
|
+
return refused(id, 'this receiver takes signed calls only', entity, op);
|
|
53
|
+
}
|
|
54
|
+
// Built field by field, never spread from `sent`: everything here is either judged
|
|
55
|
+
// above or carried deliberately, and `caller` is ours to write alone.
|
|
27
56
|
const invocation = {
|
|
28
57
|
params: sent.params ?? {},
|
|
29
58
|
query: sent.query ?? {},
|
|
30
59
|
body: sent.body,
|
|
31
|
-
state
|
|
60
|
+
state,
|
|
61
|
+
trace: sent.trace,
|
|
62
|
+
...(caller ? { caller } : {}),
|
|
32
63
|
};
|
|
33
64
|
try {
|
|
34
65
|
return { jsonrpc: '2.0', id, result: await runner({ entity, op }, invocation) };
|
|
@@ -47,4 +78,9 @@ export async function handleRpc(runner, raw) {
|
|
|
47
78
|
return { jsonrpc: '2.0', id, error: { code: APP_ERROR, message: data.message, data } };
|
|
48
79
|
}
|
|
49
80
|
}
|
|
81
|
+
/** An admission refusal, framed like any other failure so a caller reads one vocabulary. */
|
|
82
|
+
function refused(id, why, entity, op) {
|
|
83
|
+
const data = toPublicError(new FougereError({ code: ErrorCode.UNAUTHORIZED, message: `Refused: ${why}`, entity, operation: op }));
|
|
84
|
+
return { jsonrpc: '2.0', id, error: { code: APP_ERROR, message: data.message, data } };
|
|
85
|
+
}
|
|
50
86
|
//# sourceMappingURL=server.js.map
|
package/dist/server.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,aAAa,
|
|
1
|
+
{"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fougere/transport-http",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0-alpha.0",
|
|
4
4
|
"description": "The call contract on the wire, in JSON-RPC 2.0 (server + client).",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"fougere",
|
|
@@ -24,6 +24,10 @@
|
|
|
24
24
|
"types": "./dist/index.d.ts",
|
|
25
25
|
"import": "./dist/index.js"
|
|
26
26
|
},
|
|
27
|
+
"./receive": {
|
|
28
|
+
"types": "./dist/receive.d.ts",
|
|
29
|
+
"import": "./dist/receive.js"
|
|
30
|
+
},
|
|
27
31
|
"./client": {
|
|
28
32
|
"types": "./dist/client.d.ts",
|
|
29
33
|
"import": "./dist/client.js"
|
|
@@ -33,12 +37,12 @@
|
|
|
33
37
|
"dist"
|
|
34
38
|
],
|
|
35
39
|
"dependencies": {
|
|
36
|
-
"@fougere/core": "0.
|
|
40
|
+
"@fougere/core": "0.3.0-alpha.0"
|
|
37
41
|
},
|
|
38
42
|
"devDependencies": {
|
|
39
43
|
"jiti": "^2.6.1",
|
|
40
|
-
"@fougere/schema": "0.
|
|
41
|
-
"@fougere/container": "0.
|
|
44
|
+
"@fougere/schema": "0.3.0-alpha.0",
|
|
45
|
+
"@fougere/container": "0.3.0-alpha.0"
|
|
42
46
|
},
|
|
43
47
|
"publishConfig": {
|
|
44
48
|
"access": "public"
|