@nats-kit/rpc 0.3.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.
Files changed (96) hide show
  1. package/CHANGELOG.md +24 -0
  2. package/LICENSE +21 -0
  3. package/README.md +94 -0
  4. package/dist/commonjs/client.d.ts +9 -0
  5. package/dist/commonjs/client.d.ts.map +1 -0
  6. package/dist/commonjs/client.js +307 -0
  7. package/dist/commonjs/client.js.map +1 -0
  8. package/dist/commonjs/contract.d.ts +59 -0
  9. package/dist/commonjs/contract.d.ts.map +1 -0
  10. package/dist/commonjs/contract.js +56 -0
  11. package/dist/commonjs/contract.js.map +1 -0
  12. package/dist/commonjs/errors.d.ts +58 -0
  13. package/dist/commonjs/errors.d.ts.map +1 -0
  14. package/dist/commonjs/errors.js +74 -0
  15. package/dist/commonjs/errors.js.map +1 -0
  16. package/dist/commonjs/eslint/index.d.ts +22 -0
  17. package/dist/commonjs/eslint/index.d.ts.map +1 -0
  18. package/dist/commonjs/eslint/index.js +33 -0
  19. package/dist/commonjs/eslint/index.js.map +1 -0
  20. package/dist/commonjs/events.d.ts +55 -0
  21. package/dist/commonjs/events.d.ts.map +1 -0
  22. package/dist/commonjs/events.js +82 -0
  23. package/dist/commonjs/events.js.map +1 -0
  24. package/dist/commonjs/headers.d.ts +53 -0
  25. package/dist/commonjs/headers.d.ts.map +1 -0
  26. package/dist/commonjs/headers.js +116 -0
  27. package/dist/commonjs/headers.js.map +1 -0
  28. package/dist/commonjs/index.d.ts +15 -0
  29. package/dist/commonjs/index.d.ts.map +1 -0
  30. package/dist/commonjs/index.js +61 -0
  31. package/dist/commonjs/index.js.map +1 -0
  32. package/dist/commonjs/kv.d.ts +13 -0
  33. package/dist/commonjs/kv.d.ts.map +1 -0
  34. package/dist/commonjs/kv.js +23 -0
  35. package/dist/commonjs/kv.js.map +1 -0
  36. package/dist/commonjs/package.json +4 -0
  37. package/dist/commonjs/server.d.ts +45 -0
  38. package/dist/commonjs/server.d.ts.map +1 -0
  39. package/dist/commonjs/server.js +433 -0
  40. package/dist/commonjs/server.js.map +1 -0
  41. package/dist/commonjs/types.d.ts +100 -0
  42. package/dist/commonjs/types.d.ts.map +1 -0
  43. package/dist/commonjs/types.js +3 -0
  44. package/dist/commonjs/types.js.map +1 -0
  45. package/dist/esm/client.d.ts +9 -0
  46. package/dist/esm/client.d.ts.map +1 -0
  47. package/dist/esm/client.js +304 -0
  48. package/dist/esm/client.js.map +1 -0
  49. package/dist/esm/contract.d.ts +59 -0
  50. package/dist/esm/contract.d.ts.map +1 -0
  51. package/dist/esm/contract.js +48 -0
  52. package/dist/esm/contract.js.map +1 -0
  53. package/dist/esm/errors.d.ts +58 -0
  54. package/dist/esm/errors.d.ts.map +1 -0
  55. package/dist/esm/errors.js +67 -0
  56. package/dist/esm/errors.js.map +1 -0
  57. package/dist/esm/eslint/index.d.ts +22 -0
  58. package/dist/esm/eslint/index.d.ts.map +1 -0
  59. package/dist/esm/eslint/index.js +30 -0
  60. package/dist/esm/eslint/index.js.map +1 -0
  61. package/dist/esm/events.d.ts +55 -0
  62. package/dist/esm/events.d.ts.map +1 -0
  63. package/dist/esm/events.js +77 -0
  64. package/dist/esm/events.js.map +1 -0
  65. package/dist/esm/headers.d.ts +53 -0
  66. package/dist/esm/headers.d.ts.map +1 -0
  67. package/dist/esm/headers.js +108 -0
  68. package/dist/esm/headers.js.map +1 -0
  69. package/dist/esm/index.d.ts +15 -0
  70. package/dist/esm/index.d.ts.map +1 -0
  71. package/dist/esm/index.js +25 -0
  72. package/dist/esm/index.js.map +1 -0
  73. package/dist/esm/kv.d.ts +13 -0
  74. package/dist/esm/kv.d.ts.map +1 -0
  75. package/dist/esm/kv.js +20 -0
  76. package/dist/esm/kv.js.map +1 -0
  77. package/dist/esm/package.json +4 -0
  78. package/dist/esm/server.d.ts +45 -0
  79. package/dist/esm/server.d.ts.map +1 -0
  80. package/dist/esm/server.js +426 -0
  81. package/dist/esm/server.js.map +1 -0
  82. package/dist/esm/types.d.ts +100 -0
  83. package/dist/esm/types.d.ts.map +1 -0
  84. package/dist/esm/types.js +2 -0
  85. package/dist/esm/types.js.map +1 -0
  86. package/package.json +103 -0
  87. package/src/client.ts +377 -0
  88. package/src/contract.ts +105 -0
  89. package/src/errors.ts +100 -0
  90. package/src/eslint/index.ts +30 -0
  91. package/src/events.ts +139 -0
  92. package/src/headers.ts +147 -0
  93. package/src/index.ts +76 -0
  94. package/src/kv.ts +33 -0
  95. package/src/server.ts +500 -0
  96. package/src/types.ts +119 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * ESLint flat-config snippet (design §2.8): a lint-level nudge, not a
3
+ * guarantee — `no-restricted-properties` is purely syntactic. Spread into a
4
+ * consumer's flat config:
5
+ *
6
+ * ```js
7
+ * import { rpcBoundaryRules } from "@nats-kit/rpc/eslint";
8
+ * export default [{ files: ["src/**\/*.ts"], rules: { ...rpcBoundaryRules } }];
9
+ * ```
10
+ */
11
+ export const rpcBoundaryRules = {
12
+ "no-restricted-properties": [
13
+ "error",
14
+ {
15
+ property: "respondError",
16
+ message: "Return fail(...) or throw RpcError from an RPC handler; the rpc layer owns ADR-32 error headers.",
17
+ },
18
+ {
19
+ object: "nc",
20
+ property: "request",
21
+ message: "Use a typed createRpcClient() method instead of raw nc.request().",
22
+ },
23
+ {
24
+ object: "msg",
25
+ property: "respond",
26
+ message: "Raw msg.respond() bypasses the RPC envelope. Use an RPC handler.",
27
+ },
28
+ ],
29
+ };
30
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/eslint/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC9B,0BAA0B,EAAE;QAC1B,OAAO;QACP;YACE,QAAQ,EAAE,cAAc;YACxB,OAAO,EACL,kGAAkG;SACrG;QACD;YACE,MAAM,EAAE,IAAI;YACZ,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,mEAAmE;SAC7E;QACD;YACE,MAAM,EAAE,KAAK;YACb,QAAQ,EAAE,SAAS;YACnB,OAAO,EAAE,kEAAkE;SAC5E;KACF;CACF,CAAC"}
@@ -0,0 +1,55 @@
1
+ import { type MsgHdrs, type NatsConnectionLike, type NatsConnectionRunner, type PubAck } from "@nats-kit/core";
2
+ import { z } from "zod";
3
+ /** A CloudEvents-shaped event definition (§2.5, §4.8). */
4
+ export interface EventContract<T extends z.ZodType> {
5
+ /** `<app>.<entity>.<event>` — also the CloudEvents `type` and the subject. */
6
+ type: string;
7
+ /** CloudEvents `source`, e.g. "urn:anki:sandbox". */
8
+ source: string;
9
+ data: T;
10
+ }
11
+ export declare function defineEvent<T extends z.ZodType>(def: EventContract<T>): EventContract<T>;
12
+ /**
13
+ * `publishEvent` needs a JetStream client to get a `PubAck` (design §2.5);
14
+ * `NatsConnectionLike` alone is Core-NATS-only, so we widen it with just the
15
+ * one extra accessor both `NatsConnectionRunner` and the NestJS `NatsService`
16
+ * (which delegates to it) already expose.
17
+ */
18
+ export interface PublishEventOptions {
19
+ nats: NatsConnectionLike & Pick<NatsConnectionRunner, "getJetStream">;
20
+ /** CloudEvents `id` and `Nats-Msg-Id`. Defaults to a nuid. */
21
+ id?: string;
22
+ /** RFC3339. Defaults to `new Date().toISOString()`. */
23
+ time?: string;
24
+ /** CloudEvents optional `subject` attribute (a resource id, NOT the NATS subject). */
25
+ subject?: string;
26
+ traceparent?: string;
27
+ /** Override the publish subject. Defaults to `event.type`. */
28
+ natsSubject?: string;
29
+ }
30
+ interface CloudEventEnvelope<T> {
31
+ specversion: "1.0";
32
+ id: string;
33
+ source: string;
34
+ type: string;
35
+ time: string;
36
+ subject?: string;
37
+ datacontenttype: "application/json";
38
+ data: T;
39
+ }
40
+ export type CloudEvent<T> = CloudEventEnvelope<T>;
41
+ /**
42
+ * Publish a CloudEvents 1.0 structured-mode envelope (§4.8) via JetStream,
43
+ * with `Nats-Msg-Id` set to the CloudEvents `id` for stream-level dedup.
44
+ */
45
+ export declare function publishEvent<T extends z.ZodType>(event: EventContract<T>, data: z.input<T>, options: PublishEventOptions): Promise<PubAck>;
46
+ /**
47
+ * Parse a received JetStream/Core message as a CloudEvents envelope,
48
+ * validating the full envelope (not just `data`) per §4.8.
49
+ */
50
+ export declare function parseEvent<T extends z.ZodType>(event: EventContract<T>, msg: {
51
+ data: Uint8Array;
52
+ headers?: MsgHdrs;
53
+ }): CloudEvent<z.output<T>>;
54
+ export {};
55
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,OAAO,EACZ,KAAK,kBAAkB,EACvB,KAAK,oBAAoB,EACzB,KAAK,MAAM,EACZ,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB,0DAA0D;AAC1D,MAAM,WAAW,aAAa,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO;IAChD,8EAA8E;IAC9E,IAAI,EAAE,MAAM,CAAC;IACb,qDAAqD;IACrD,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,CAAC,CAAC;CACT;AAED,wBAAgB,WAAW,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE,aAAa,CAAC,CAAC,CAAC,GAAG,aAAa,CAAC,CAAC,CAAC,CAExF;AAED;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC,oBAAoB,EAAE,cAAc,CAAC,CAAC;IACtE,8DAA8D;IAC9D,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sFAAsF;IACtF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,8DAA8D;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,UAAU,kBAAkB,CAAC,CAAC;IAC5B,WAAW,EAAE,KAAK,CAAC;IACnB,EAAE,EAAE,MAAM,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,eAAe,EAAE,kBAAkB,CAAC;IACpC,IAAI,EAAE,CAAC,CAAC;CACT;AAED,MAAM,MAAM,UAAU,CAAC,CAAC,IAAI,kBAAkB,CAAC,CAAC,CAAC,CAAC;AAuClD;;;GAGG;AACH,wBAAsB,YAAY,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EACpD,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EACvB,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAChB,OAAO,EAAE,mBAAmB,GAC3B,OAAO,CAAC,MAAM,CAAC,CAwBjB;AAED;;;GAGG;AACH,wBAAgB,UAAU,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAC5C,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EACvB,GAAG,EAAE;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC3C,UAAU,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAKzB"}
@@ -0,0 +1,77 @@
1
+ import { nuid } from "@nats-io/nuid";
2
+ import { headers as buildMsgHdrs, } from "@nats-kit/core";
3
+ import { z } from "zod";
4
+ export function defineEvent(def) {
5
+ return def;
6
+ }
7
+ /** Validates the envelope shape (§4.8) around an arbitrary `data` payload. */
8
+ const CloudEventEnvelopeSchema = z.object({
9
+ specversion: z.literal("1.0"),
10
+ id: z.string().min(1),
11
+ source: z.string().min(1),
12
+ type: z.string().min(1),
13
+ time: z.string().min(1),
14
+ subject: z.string().optional(),
15
+ datacontenttype: z.literal("application/json"),
16
+ data: z.unknown(),
17
+ });
18
+ /**
19
+ * JSON has no representation for `NaN`/`Infinity` — `JSON.stringify` silently
20
+ * turns them into `null`, which would silently corrupt an event's data on
21
+ * the wire. Walk the value and reject before that can happen.
22
+ */
23
+ function assertJsonSafe(value, path = "$") {
24
+ if (typeof value === "number") {
25
+ if (!Number.isFinite(value)) {
26
+ throw new Error(`publishEvent: non-finite number (${String(value)}) at ${path} is not valid JSON`);
27
+ }
28
+ return;
29
+ }
30
+ if (Array.isArray(value)) {
31
+ value.forEach((v, i) => assertJsonSafe(v, `${path}[${i}]`));
32
+ return;
33
+ }
34
+ if (value !== null && typeof value === "object") {
35
+ for (const [k, v] of Object.entries(value)) {
36
+ assertJsonSafe(v, `${path}.${k}`);
37
+ }
38
+ }
39
+ }
40
+ /**
41
+ * Publish a CloudEvents 1.0 structured-mode envelope (§4.8) via JetStream,
42
+ * with `Nats-Msg-Id` set to the CloudEvents `id` for stream-level dedup.
43
+ */
44
+ export async function publishEvent(event, data, options) {
45
+ const parsed = event.data.parse(data);
46
+ assertJsonSafe(parsed);
47
+ const id = options.id ?? nuid.next();
48
+ const envelope = {
49
+ specversion: "1.0",
50
+ id,
51
+ source: event.source,
52
+ type: event.type,
53
+ time: options.time ?? new Date().toISOString(),
54
+ subject: options.subject,
55
+ datacontenttype: "application/json",
56
+ data: parsed,
57
+ };
58
+ const h = buildMsgHdrs();
59
+ if (options.traceparent !== undefined) {
60
+ h.set("traceparent", options.traceparent);
61
+ }
62
+ const body = new TextEncoder().encode(JSON.stringify(envelope));
63
+ await options.nats.waitForReady();
64
+ const js = options.nats.getJetStream();
65
+ return js.publish(options.natsSubject ?? event.type, body, { msgID: id, headers: h });
66
+ }
67
+ /**
68
+ * Parse a received JetStream/Core message as a CloudEvents envelope,
69
+ * validating the full envelope (not just `data`) per §4.8.
70
+ */
71
+ export function parseEvent(event, msg) {
72
+ const raw = JSON.parse(new TextDecoder().decode(msg.data));
73
+ const envelope = CloudEventEnvelopeSchema.parse(raw);
74
+ const data = event.data.parse(envelope.data);
75
+ return { ...envelope, data };
76
+ }
77
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/events.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,53 @@
1
+ import { type MsgHdrs } from "@nats-kit/core";
2
+ import { type RpcCaller } from "./types.js";
3
+ /** Header names (D5, §4.2). Never mint a bare `Nats-*` header — that prefix is server/ADR-32 territory. */
4
+ export declare const HEADER_REQUEST_ID = "Nk-Request-Id";
5
+ export declare const HEADER_CALLER_KIND = "Nk-Caller-Kind";
6
+ export declare const HEADER_CALLER_ID = "Nk-Caller-Id";
7
+ export declare const HEADER_CALLER_ROLE = "Nk-Caller-Role";
8
+ export declare const HEADER_DEADLINE = "Nk-Deadline";
9
+ export declare const HEADER_CONTENT_TYPE = "Content-Type";
10
+ export declare const HEADER_TRACEPARENT = "traceparent";
11
+ export declare const HEADER_TRACESTATE = "tracestate";
12
+ export declare const CONTENT_TYPE_JSON = "application/json";
13
+ export interface BuildRequestHeadersInit {
14
+ requestId: string;
15
+ caller: RpcCaller;
16
+ deadlineMs?: number;
17
+ traceparent?: string;
18
+ tracestate?: string;
19
+ /** Extra `Nk-*` headers. `Nats-*` and reserved names are rejected by the caller (client.ts). */
20
+ extra?: Record<string, string>;
21
+ }
22
+ /** Build the request `MsgHdrs` per §4.2. */
23
+ export declare function buildRequestHeaders(init: BuildRequestHeadersInit): MsgHdrs;
24
+ /**
25
+ * Parse `Nk-Caller-Role` per §4.2: comma-separated, no spaces, absent/empty
26
+ * means an empty set. Guards the classic `"".split(",")` trap, which yields
27
+ * `[""]` rather than `[]`.
28
+ */
29
+ export declare function parseRoles(headerValue: string | undefined | null): readonly string[];
30
+ export declare function isValidRole(role: string): boolean;
31
+ export declare function isValidRequestId(id: string): boolean;
32
+ export interface ParsedRequestHeaders {
33
+ requestId: string;
34
+ callerKind: "user" | "service";
35
+ callerId?: string;
36
+ roles: readonly string[];
37
+ deadlineMs?: number;
38
+ traceparent?: string;
39
+ }
40
+ export type ParseHeadersResult = {
41
+ ok: true;
42
+ value: ParsedRequestHeaders;
43
+ } | {
44
+ ok: false;
45
+ message: string;
46
+ };
47
+ /**
48
+ * Parse and validate the required/conditional request headers per §4.2.
49
+ * Used by `createRpcServer` as dispatch step 1 (missing/malformed -> 400;
50
+ * `user` with no `Nk-Caller-Id` -> handled by the caller as 401).
51
+ */
52
+ export declare function parseRequestHeaders(h: MsgHdrs | undefined): ParseHeadersResult;
53
+ //# sourceMappingURL=headers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../src/headers.ts"],"names":[],"mappings":"AAAA,OAAO,EAA2B,KAAK,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAGvE,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AAE5C,2GAA2G;AAC3G,eAAO,MAAM,iBAAiB,kBAAkB,CAAC;AACjD,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,gBAAgB,iBAAiB,CAAC;AAC/C,eAAO,MAAM,kBAAkB,mBAAmB,CAAC;AACnD,eAAO,MAAM,eAAe,gBAAgB,CAAC;AAC7C,eAAO,MAAM,mBAAmB,iBAAiB,CAAC;AAClD,eAAO,MAAM,kBAAkB,gBAAgB,CAAC;AAChD,eAAO,MAAM,iBAAiB,eAAe,CAAC;AAE9C,eAAO,MAAM,iBAAiB,qBAAqB,CAAC;AAKpD,MAAM,WAAW,uBAAuB;IACtC,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,EAAE,SAAS,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gGAAgG;IAChG,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAChC;AAED,4CAA4C;AAC5C,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CA0B1E;AAED;;;;GAIG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,SAAS,MAAM,EAAE,CAGpF;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEjD;AAED,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,MAAM,kBAAkB,GAC1B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,oBAAoB,CAAA;CAAE,GACzC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAEnC;;;;GAIG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,EAAE,OAAO,GAAG,SAAS,GAAG,kBAAkB,CAmD9E"}
@@ -0,0 +1,108 @@
1
+ import { headers as buildMsgHdrs } from "@nats-kit/core";
2
+ import { Match } from "@nats-io/nats-core";
3
+ /** Header names (D5, §4.2). Never mint a bare `Nats-*` header — that prefix is server/ADR-32 territory. */
4
+ export const HEADER_REQUEST_ID = "Nk-Request-Id";
5
+ export const HEADER_CALLER_KIND = "Nk-Caller-Kind";
6
+ export const HEADER_CALLER_ID = "Nk-Caller-Id";
7
+ export const HEADER_CALLER_ROLE = "Nk-Caller-Role";
8
+ export const HEADER_DEADLINE = "Nk-Deadline";
9
+ export const HEADER_CONTENT_TYPE = "Content-Type";
10
+ export const HEADER_TRACEPARENT = "traceparent";
11
+ export const HEADER_TRACESTATE = "tracestate";
12
+ export const CONTENT_TYPE_JSON = "application/json";
13
+ const ROLE_RE = /^[A-Za-z0-9_:-]{1,64}$/;
14
+ const REQUEST_ID_RE = /^[A-Za-z0-9_-]{1,64}$/;
15
+ /** Build the request `MsgHdrs` per §4.2. */
16
+ export function buildRequestHeaders(init) {
17
+ const h = buildMsgHdrs();
18
+ h.set(HEADER_CONTENT_TYPE, CONTENT_TYPE_JSON);
19
+ h.set(HEADER_REQUEST_ID, init.requestId);
20
+ h.set(HEADER_CALLER_KIND, init.caller.kind);
21
+ if (init.caller.id !== undefined) {
22
+ h.set(HEADER_CALLER_ID, init.caller.id);
23
+ }
24
+ if (init.caller.roles && init.caller.roles.length > 0) {
25
+ h.set(HEADER_CALLER_ROLE, init.caller.roles.join(","));
26
+ }
27
+ if (init.deadlineMs !== undefined) {
28
+ h.set(HEADER_DEADLINE, String(Math.trunc(init.deadlineMs)));
29
+ }
30
+ if (init.traceparent !== undefined) {
31
+ h.set(HEADER_TRACEPARENT, init.traceparent);
32
+ }
33
+ if (init.tracestate !== undefined) {
34
+ h.set(HEADER_TRACESTATE, init.tracestate);
35
+ }
36
+ if (init.extra) {
37
+ for (const [k, v] of Object.entries(init.extra)) {
38
+ h.set(k, v);
39
+ }
40
+ }
41
+ return h;
42
+ }
43
+ /**
44
+ * Parse `Nk-Caller-Role` per §4.2: comma-separated, no spaces, absent/empty
45
+ * means an empty set. Guards the classic `"".split(",")` trap, which yields
46
+ * `[""]` rather than `[]`.
47
+ */
48
+ export function parseRoles(headerValue) {
49
+ if (!headerValue)
50
+ return [];
51
+ return headerValue.split(",").filter((r) => r.length > 0);
52
+ }
53
+ export function isValidRole(role) {
54
+ return ROLE_RE.test(role);
55
+ }
56
+ export function isValidRequestId(id) {
57
+ return REQUEST_ID_RE.test(id);
58
+ }
59
+ /**
60
+ * Parse and validate the required/conditional request headers per §4.2.
61
+ * Used by `createRpcServer` as dispatch step 1 (missing/malformed -> 400;
62
+ * `user` with no `Nk-Caller-Id` -> handled by the caller as 401).
63
+ */
64
+ export function parseRequestHeaders(h) {
65
+ if (!h) {
66
+ return { ok: false, message: "missing required headers" };
67
+ }
68
+ const contentType = h.get(HEADER_CONTENT_TYPE, Match.IgnoreCase);
69
+ if (contentType && contentType !== CONTENT_TYPE_JSON) {
70
+ return { ok: false, message: `unsupported ${HEADER_CONTENT_TYPE}: "${contentType}"` };
71
+ }
72
+ const requestId = h.get(HEADER_REQUEST_ID, Match.IgnoreCase);
73
+ if (!requestId || !isValidRequestId(requestId)) {
74
+ return { ok: false, message: `missing or malformed ${HEADER_REQUEST_ID}` };
75
+ }
76
+ const callerKind = h.get(HEADER_CALLER_KIND, Match.IgnoreCase);
77
+ if (callerKind !== "user" && callerKind !== "service") {
78
+ return { ok: false, message: `missing or invalid ${HEADER_CALLER_KIND}` };
79
+ }
80
+ const rawCallerId = h.get(HEADER_CALLER_ID, Match.IgnoreCase) || undefined;
81
+ if (rawCallerId !== undefined && (rawCallerId.length < 1 || rawCallerId.length > 256)) {
82
+ return { ok: false, message: `${HEADER_CALLER_ID} must be 1-256 chars` };
83
+ }
84
+ const callerId = rawCallerId;
85
+ const rawRoles = h.get(HEADER_CALLER_ROLE, Match.IgnoreCase);
86
+ const roles = parseRoles(rawRoles);
87
+ if (rawRoles) {
88
+ for (const role of roles) {
89
+ if (!isValidRole(role)) {
90
+ return { ok: false, message: `malformed role in ${HEADER_CALLER_ROLE}: "${role}"` };
91
+ }
92
+ }
93
+ }
94
+ const rawDeadline = h.get(HEADER_DEADLINE, Match.IgnoreCase);
95
+ let deadlineMs;
96
+ if (rawDeadline) {
97
+ if (!/^\d+$/.test(rawDeadline)) {
98
+ return { ok: false, message: `malformed ${HEADER_DEADLINE}` };
99
+ }
100
+ deadlineMs = Number(rawDeadline);
101
+ }
102
+ const traceparent = h.get(HEADER_TRACEPARENT, Match.IgnoreCase) || undefined;
103
+ return {
104
+ ok: true,
105
+ value: { requestId, callerKind, callerId, roles, deadlineMs, traceparent },
106
+ };
107
+ }
108
+ //# sourceMappingURL=headers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headers.js","sourceRoot":"","sources":["../../src/headers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ export { defineService, method, methodSubject, serviceName, groupSubject, SUBJECT_SEGMENT_RE, } from "./contract.js";
2
+ export type { RpcMethodDef, ServiceContract } from "./contract.js";
3
+ export { createRpcClient } from "./client.js";
4
+ export type { RpcCaller, RpcCallOptions, RpcClient, RpcClientOptions, } from "./types.js";
5
+ export { createRpcServer, ok, fail, newRequestId } from "./server.js";
6
+ export type { RpcContext, RpcResult, RpcHandlers, RpcAuthorize, RpcServerOptions, RpcServerHandle, } from "./types.js";
7
+ export { RpcError, isRpcError, isDomainError, isTransportError, TRANSPORT_ERROR_CODES, SERVICE_ERROR_CODES, } from "./errors.js";
8
+ export type { RpcErrorKind, RpcErrorInit } from "./errors.js";
9
+ export { HEADER_REQUEST_ID, HEADER_CALLER_KIND, HEADER_CALLER_ID, HEADER_CALLER_ROLE, HEADER_DEADLINE, HEADER_CONTENT_TYPE, HEADER_TRACEPARENT, HEADER_TRACESTATE, CONTENT_TYPE_JSON, parseRoles, parseRequestHeaders, } from "./headers.js";
10
+ export { defineEvent, publishEvent, parseEvent } from "./events.js";
11
+ export type { EventContract, PublishEventOptions, CloudEvent } from "./events.js";
12
+ export { defineKvValue } from "./kv.js";
13
+ export type { KvValueContract } from "./kv.js";
14
+ export { ServiceError } from "@nats-io/services";
15
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAOA,OAAO,EACL,aAAa,EACb,MAAM,EACN,aAAa,EACb,WAAW,EACX,YAAY,EACZ,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,YAAY,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAGnE,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAC9C,YAAY,EACV,SAAS,EACT,cAAc,EACd,SAAS,EACT,gBAAgB,GACjB,MAAM,YAAY,CAAC;AAGpB,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACtE,YAAY,EACV,UAAU,EACV,SAAS,EACT,WAAW,EACX,YAAY,EACZ,gBAAgB,EAChB,eAAe,GAChB,MAAM,YAAY,CAAC;AAGpB,OAAO,EACL,QAAQ,EACR,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AACrB,YAAY,EAAE,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAI9D,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAGtB,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACpE,YAAY,EAAE,aAAa,EAAE,mBAAmB,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGlF,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACxC,YAAY,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAK/C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,25 @@
1
+ // Public surface of @nats-kit/rpc — typed request/reply RPC over NATS,
2
+ // built on @nats-io/services (ADR-32) with a reconnect supervisor.
3
+ //
4
+ // See docs/spec/nats-kit-wire-spec.md for the language-neutral wire spec this
5
+ // package implements (mirrors design doc §4).
6
+ // Contract
7
+ export { defineService, method, methodSubject, serviceName, groupSubject, SUBJECT_SEGMENT_RE, } from "./contract.js";
8
+ // Client
9
+ export { createRpcClient } from "./client.js";
10
+ // Server
11
+ export { createRpcServer, ok, fail, newRequestId } from "./server.js";
12
+ // Errors
13
+ export { RpcError, isRpcError, isDomainError, isTransportError, TRANSPORT_ERROR_CODES, SERVICE_ERROR_CODES, } from "./errors.js";
14
+ // Headers (exposed for consumers building their own low-level tooling, e.g.
15
+ // the interop test harness or a Go-side test client written in TS).
16
+ export { HEADER_REQUEST_ID, HEADER_CALLER_KIND, HEADER_CALLER_ID, HEADER_CALLER_ROLE, HEADER_DEADLINE, HEADER_CONTENT_TYPE, HEADER_TRACEPARENT, HEADER_TRACESTATE, CONTENT_TYPE_JSON, parseRoles, parseRequestHeaders, } from "./headers.js";
17
+ // Events
18
+ export { defineEvent, publishEvent, parseEvent } from "./events.js";
19
+ // KV
20
+ export { defineKvValue } from "./kv.js";
21
+ // Re-export the ADR-32 error class from `@nats-io/services` so consumers can
22
+ // `instanceof`-check it without a direct dependency (mirrors the core
23
+ // barrel's `@nats-io/*` re-export rule).
24
+ export { ServiceError } from "@nats-io/services";
25
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,uEAAuE;AACvE,mEAAmE;AACnE,EAAE;AACF,8EAA8E;AAC9E,8CAA8C;AAE9C,WAAW;AACX,OAAO,EACL,aAAa,EACb,MAAM,EACN,aAAa,EACb,WAAW,EACX,YAAY,EACZ,kBAAkB,GACnB,MAAM,eAAe,CAAC;AAGvB,SAAS;AACT,OAAO,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AAQ9C,SAAS;AACT,OAAO,EAAE,eAAe,EAAE,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAUtE,SAAS;AACT,OAAO,EACL,QAAQ,EACR,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,GACpB,MAAM,aAAa,CAAC;AAGrB,4EAA4E;AAC5E,oEAAoE;AACpE,OAAO,EACL,iBAAiB,EACjB,kBAAkB,EAClB,gBAAgB,EAChB,kBAAkB,EAClB,eAAe,EACf,mBAAmB,EACnB,kBAAkB,EAClB,iBAAiB,EACjB,iBAAiB,EACjB,UAAU,EACV,mBAAmB,GACpB,MAAM,cAAc,CAAC;AAEtB,SAAS;AACT,OAAO,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAGpE,KAAK;AACL,OAAO,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAGxC,6EAA6E;AAC7E,sEAAsE;AACtE,yCAAyC;AACzC,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { type z } from "zod";
2
+ /** A typed KV value contract (§2.5, §4.9). No envelope; a breaking shape change means a new bucket. */
3
+ export interface KvValueContract<T extends z.ZodType> {
4
+ bucket: string;
5
+ value: T;
6
+ /** Builds a validated, dot-joined key from parts; each part must be `[a-zA-Z0-9_-]+`. */
7
+ key(...parts: string[]): string;
8
+ }
9
+ export declare function defineKvValue<T extends z.ZodType>(def: {
10
+ bucket: string;
11
+ value: T;
12
+ }): KvValueContract<T>;
13
+ //# sourceMappingURL=kv.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv.d.ts","sourceRoot":"","sources":["../../src/kv.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,CAAC,EAAE,MAAM,KAAK,CAAC;AAI7B,uGAAuG;AACvG,MAAM,WAAW,eAAe,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO;IAClD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,CAAC,CAAC;IACT,yFAAyF;IACzF,GAAG,CAAC,GAAG,KAAK,EAAE,MAAM,EAAE,GAAG,MAAM,CAAC;CACjC;AAED,wBAAgB,aAAa,CAAC,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,EAAE;IACtD,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,CAAC,CAAC;CACV,GAAG,eAAe,CAAC,CAAC,CAAC,CAiBrB"}
package/dist/esm/kv.js ADDED
@@ -0,0 +1,20 @@
1
+ const KV_KEY_PART_RE = /^[a-zA-Z0-9_-]+$/;
2
+ export function defineKvValue(def) {
3
+ return {
4
+ bucket: def.bucket,
5
+ value: def.value,
6
+ key(...parts) {
7
+ for (const part of parts) {
8
+ if (!KV_KEY_PART_RE.test(part)) {
9
+ throw new Error(`defineKvValue(${def.bucket}): invalid key part "${part}"`);
10
+ }
11
+ }
12
+ const key = parts.join(".");
13
+ if (key.length === 0 || key.length > 255) {
14
+ throw new Error(`defineKvValue(${def.bucket}): key length out of bounds`);
15
+ }
16
+ return key;
17
+ },
18
+ };
19
+ }
20
+ //# sourceMappingURL=kv.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"kv.js","sourceRoot":"","sources":["../../src/kv.ts"],"names":[],"mappings":"AAEA,MAAM,cAAc,GAAG,kBAAkB,CAAC;AAU1C,MAAM,UAAU,aAAa,CAAsB,GAGlD;IACC,OAAO;QACL,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,GAAG,CAAC,GAAG,KAAe;YACpB,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;gBACzB,IAAI,CAAC,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;oBAC/B,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,MAAM,wBAAwB,IAAI,GAAG,CAAC,CAAC;gBAC9E,CAAC;YACH,CAAC;YACD,MAAM,GAAG,GAAG,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,GAAG,EAAE,CAAC;gBACzC,MAAM,IAAI,KAAK,CAAC,iBAAiB,GAAG,CAAC,MAAM,6BAA6B,CAAC,CAAC;YAC5E,CAAC;YACD,OAAO,GAAG,CAAC;QACb,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ {
2
+ "type": "module",
3
+ "sideEffects": false
4
+ }
@@ -0,0 +1,45 @@
1
+ import { type ServiceHandler } from "@nats-io/services";
2
+ import { type ServiceContract } from "./contract.js";
3
+ import { type RpcAuthorize, type RpcContext, type RpcHandlers, type RpcResult, type RpcServerHandle, type RpcServerOptions } from "./types.js";
4
+ /** Build a successful `RpcResult`. */
5
+ export declare function ok<T>(result: T): {
6
+ ok: true;
7
+ result: T;
8
+ };
9
+ /** Build a domain-error `RpcResult`. */
10
+ export declare function fail<E extends string>(code: E, message: string, details?: unknown): {
11
+ ok: false;
12
+ error: {
13
+ code: E;
14
+ message: string;
15
+ details?: unknown;
16
+ };
17
+ };
18
+ /**
19
+ * Build the `ServiceHandler` for one contract method — dispatch order fixed
20
+ * by design §2.4 / wire spec §4.5.
21
+ *
22
+ * The library's own synchronous try/catch around `handler(err, msg)` (see
23
+ * `ServiceImpl.setupHandler`) cannot observe an `async` handler's rejection,
24
+ * so it never counts our service errors toward `num_errors` — we build every
25
+ * response (success, domain error, service error) explicitly instead of
26
+ * throwing, which is what lets a 400/403 carry a JSON `details` body. This is
27
+ * a documented deviation from `nats micro stats` incrementing on our service
28
+ * errors; see the package README.
29
+ *
30
+ * Exported for unit tests (mock `ServiceMsg` + assert the dispatch order) and
31
+ * for advanced embedding over a transport other than `@nats-io/services`'
32
+ * `ServiceHandler`. Not part of the documented public API surface.
33
+ */
34
+ export declare function buildEndpointHandler<C extends ServiceContract>(contract: C, methodName: string, options: RpcServerOptions<C>, drainSignal: AbortSignal): ServiceHandler;
35
+ /**
36
+ * Start the reconnect supervisor loop for one contract (design §3).
37
+ *
38
+ * `Svcm`-backed `Service` instances permanently stop on connection loss with
39
+ * no restart path, so this loop rebuilds the service every time it stops
40
+ * (healthy stop or connection loss) until `signal` aborts.
41
+ */
42
+ export declare function createRpcServer<C extends ServiceContract>(contract: C, options: RpcServerOptions<C>): RpcServerHandle;
43
+ export declare function newRequestId(): string;
44
+ export type { RpcHandlers, RpcAuthorize, RpcContext, RpcResult, RpcServerHandle, RpcServerOptions };
45
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/server.ts"],"names":[],"mappings":"AAAA,OAAO,EAAsB,KAAK,cAAc,EAAmB,MAAM,mBAAmB,CAAC;AAQ7F,OAAO,EACL,KAAK,eAAe,EAIrB,MAAM,eAAe,CAAC;AAGvB,OAAO,EACL,KAAK,YAAY,EACjB,KAAK,UAAU,EACf,KAAK,WAAW,EAChB,KAAK,SAAS,EACd,KAAK,eAAe,EACpB,KAAK,gBAAgB,EACtB,MAAM,YAAY,CAAC;AAIpB,sCAAsC;AACtC,wBAAgB,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,GAAG;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,MAAM,EAAE,CAAC,CAAA;CAAE,CAExD;AAED,wCAAwC;AACxC,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,EACnC,IAAI,EAAE,CAAC,EACP,OAAO,EAAE,MAAM,EACf,OAAO,CAAC,EAAE,OAAO,GAChB;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE;QAAE,IAAI,EAAE,CAAC,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAA;CAAE,CAEvE;AAYD;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,oBAAoB,CAAC,CAAC,SAAS,eAAe,EAC5D,QAAQ,EAAE,CAAC,EACX,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,EAC5B,WAAW,EAAE,WAAW,GACvB,cAAc,CA0NhB;AAyED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,eAAe,EACvD,QAAQ,EAAE,CAAC,EACX,OAAO,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC3B,eAAe,CAsHjB;AAID,wBAAgB,YAAY,IAAI,MAAM,CAErC;AAED,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,eAAe,EAAE,gBAAgB,EAAE,CAAC"}