@nodii/grpc-interceptors 0.0.2 → 0.2.1

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 (73) hide show
  1. package/dist/compose.d.ts +7 -0
  2. package/dist/compose.d.ts.map +1 -0
  3. package/dist/compose.js +20 -0
  4. package/dist/compose.js.map +1 -0
  5. package/dist/configure.d.ts +66 -0
  6. package/dist/configure.d.ts.map +1 -0
  7. package/dist/configure.js +169 -0
  8. package/dist/configure.js.map +1 -0
  9. package/dist/factory.d.ts +7 -0
  10. package/dist/factory.d.ts.map +1 -0
  11. package/dist/factory.js +100 -0
  12. package/dist/factory.js.map +1 -0
  13. package/dist/index.d.ts +18 -1
  14. package/dist/index.d.ts.map +1 -1
  15. package/dist/index.js +29 -4
  16. package/dist/index.js.map +1 -1
  17. package/dist/interceptors/audit-context.d.ts +3 -0
  18. package/dist/interceptors/audit-context.d.ts.map +1 -0
  19. package/dist/interceptors/audit-context.js +59 -0
  20. package/dist/interceptors/audit-context.js.map +1 -0
  21. package/dist/interceptors/audit.d.ts +7 -0
  22. package/dist/interceptors/audit.d.ts.map +1 -0
  23. package/dist/interceptors/audit.js +111 -0
  24. package/dist/interceptors/audit.js.map +1 -0
  25. package/dist/interceptors/cancellation-guard.d.ts +3 -0
  26. package/dist/interceptors/cancellation-guard.d.ts.map +1 -0
  27. package/dist/interceptors/cancellation-guard.js +54 -0
  28. package/dist/interceptors/cancellation-guard.js.map +1 -0
  29. package/dist/interceptors/deadline-guard.d.ts +3 -0
  30. package/dist/interceptors/deadline-guard.d.ts.map +1 -0
  31. package/dist/interceptors/deadline-guard.js +90 -0
  32. package/dist/interceptors/deadline-guard.js.map +1 -0
  33. package/dist/interceptors/enrich-auth.d.ts +3 -0
  34. package/dist/interceptors/enrich-auth.d.ts.map +1 -0
  35. package/dist/interceptors/enrich-auth.js +85 -0
  36. package/dist/interceptors/enrich-auth.js.map +1 -0
  37. package/dist/interceptors/error-map.d.ts +4 -0
  38. package/dist/interceptors/error-map.d.ts.map +1 -0
  39. package/dist/interceptors/error-map.js +94 -0
  40. package/dist/interceptors/error-map.js.map +1 -0
  41. package/dist/interceptors/logging.d.ts +7 -0
  42. package/dist/interceptors/logging.d.ts.map +1 -0
  43. package/dist/interceptors/logging.js +66 -0
  44. package/dist/interceptors/logging.js.map +1 -0
  45. package/dist/interceptors/saga-headers.d.ts +23 -0
  46. package/dist/interceptors/saga-headers.d.ts.map +1 -0
  47. package/dist/interceptors/saga-headers.js +40 -0
  48. package/dist/interceptors/saga-headers.js.map +1 -0
  49. package/dist/interceptors/signal-binder.d.ts +3 -0
  50. package/dist/interceptors/signal-binder.d.ts.map +1 -0
  51. package/dist/interceptors/signal-binder.js +83 -0
  52. package/dist/interceptors/signal-binder.js.map +1 -0
  53. package/dist/interceptors/tenant-context.d.ts +3 -0
  54. package/dist/interceptors/tenant-context.d.ts.map +1 -0
  55. package/dist/interceptors/tenant-context.js +40 -0
  56. package/dist/interceptors/tenant-context.js.map +1 -0
  57. package/dist/interceptors-exports.d.ts +9 -0
  58. package/dist/interceptors-exports.d.ts.map +1 -0
  59. package/dist/interceptors-exports.js +12 -0
  60. package/dist/interceptors-exports.js.map +1 -0
  61. package/dist/reexports.d.ts +10 -0
  62. package/dist/reexports.d.ts.map +1 -0
  63. package/dist/reexports.js +27 -0
  64. package/dist/reexports.js.map +1 -0
  65. package/dist/telemetry-shim.d.ts +12 -0
  66. package/dist/telemetry-shim.d.ts.map +1 -0
  67. package/dist/telemetry-shim.js +94 -0
  68. package/dist/telemetry-shim.js.map +1 -0
  69. package/dist/types.d.ts +228 -0
  70. package/dist/types.d.ts.map +1 -0
  71. package/dist/types.js +36 -0
  72. package/dist/types.js.map +1 -0
  73. package/package.json +14 -7
@@ -0,0 +1,7 @@
1
+ import type { UnaryInterceptor } from "./types";
2
+ /**
3
+ * Fold `interceptors` outer→inner into a single factory. The first entry
4
+ * becomes the outermost wrapper, the last is closest to the handler.
5
+ */
6
+ export declare function composeUnaryInterceptors(interceptors: readonly UnaryInterceptor[]): UnaryInterceptor;
7
+ //# sourceMappingURL=compose.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose.d.ts","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAgB,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAE9D;;;GAGG;AACH,wBAAgB,wBAAwB,CACtC,YAAY,EAAE,SAAS,gBAAgB,EAAE,GACxC,gBAAgB,CASlB"}
@@ -0,0 +1,20 @@
1
+ // composeUnaryInterceptors — local copy of the @nodii/grpc-auth helper,
2
+ // kept in this package so it can be the source-of-truth for the locked
3
+ // composition order. Bytewise identical to the grpc-auth helper per spec
4
+ // § 5.1 — outer→inner fold.
5
+ /**
6
+ * Fold `interceptors` outer→inner into a single factory. The first entry
7
+ * becomes the outermost wrapper, the last is closest to the handler.
8
+ */
9
+ export function composeUnaryInterceptors(interceptors) {
10
+ return (methodName, handler) => {
11
+ let wrapped = handler;
12
+ for (let i = interceptors.length - 1; i >= 0; i--) {
13
+ const factory = interceptors[i];
14
+ if (factory)
15
+ wrapped = factory(methodName, wrapped);
16
+ }
17
+ return wrapped;
18
+ };
19
+ }
20
+ //# sourceMappingURL=compose.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compose.js","sourceRoot":"","sources":["../src/compose.ts"],"names":[],"mappings":"AAAA,wEAAwE;AACxE,uEAAuE;AACvE,yEAAyE;AACzE,4BAA4B;AAI5B;;;GAGG;AACH,MAAM,UAAU,wBAAwB,CACtC,YAAyC;IAEzC,OAAO,CAAC,UAAkB,EAAE,OAAqB,EAAgB,EAAE;QACjE,IAAI,OAAO,GAAG,OAAO,CAAC;QACtB,KAAK,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;YAClD,MAAM,OAAO,GAAG,YAAY,CAAC,CAAC,CAAC,CAAC;YAChC,IAAI,OAAO;gBAAE,OAAO,GAAG,OAAO,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,OAAO,CAAC;IACjB,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,66 @@
1
+ import type { AuditConfig, CancellationConfig, DbConnection, DeadlineConfig, EnrichAuthConfig, ErrorMapEntry, InterceptorLogger, LoggingConfig, UnaryInterceptor } from "./types";
2
+ export interface ConfigureGrpcInterceptorsOptions {
3
+ /** Service short-name baked into the `<short>.audit_ctx` GUC. Required. */
4
+ serviceShortName: string;
5
+ /** Postgres connection abstraction — required for tenant/audit context. */
6
+ db?: DbConnection;
7
+ /**
8
+ * gRPC methods that REQUIRE `x-nodii-idempotency-key` per spec § 5.7
9
+ * (idempotencyGuard re-export). Empty set = guard is a no-op for every
10
+ * method (back-compat).
11
+ */
12
+ mutatorMethods?: ReadonlySet<string>;
13
+ /** gRPC methods that opt out of `SET app.tenant_id` (system context). */
14
+ systemContextMethods?: ReadonlySet<string>;
15
+ /** Methods that bypass the entire stack (e.g. health probes). */
16
+ skipForMethods?: ReadonlySet<string>;
17
+ /** Service-owned error catalog merged over `STANDARD_ERROR_CATALOG`. */
18
+ errorCatalog?: Record<string, ErrorMapEntry>;
19
+ logging?: LoggingConfig;
20
+ audit?: AuditConfig;
21
+ enrich?: EnrichAuthConfig;
22
+ deadline?: DeadlineConfig;
23
+ cancellation?: CancellationConfig;
24
+ /** Inject an alternate logger across all owned interceptors. */
25
+ logger?: InterceptorLogger;
26
+ /**
27
+ * Methods tagged `require_saga_context: true` per spec § 5.7 (sagaContext
28
+ * re-export from @nodii/saga). Missing = no methods enforced.
29
+ */
30
+ requireSagaContextMethods?: ReadonlySet<string>;
31
+ /** sagaContext enforcement mode — warn | reject. Default 'warn'. */
32
+ sagaContextEnforce?: "warn" | "reject";
33
+ }
34
+ export interface ConfiguredGrpcInterceptors {
35
+ /**
36
+ * Returns the composed UnaryInterceptor wired with the locked-order
37
+ * stack (spec § 5.4). Adopters wrap their service handlers with it:
38
+ *
39
+ * const composed = configured.standardStack();
40
+ * const wrapped = composed("/billing.X/CancelInvoice", handlerFn);
41
+ */
42
+ standardStack(): UnaryInterceptor;
43
+ /** Snapshot of the resolved config (useful for diagnostics + tests). */
44
+ readonly resolved: ResolvedGrpcInterceptorsConfig;
45
+ }
46
+ export interface ResolvedGrpcInterceptorsConfig {
47
+ readonly serviceShortName: string;
48
+ readonly db: DbConnection | null;
49
+ readonly mutatorMethods: ReadonlySet<string>;
50
+ readonly systemContextMethods: ReadonlySet<string>;
51
+ readonly skipForMethods: ReadonlySet<string>;
52
+ readonly errorCatalog: Record<string, ErrorMapEntry>;
53
+ readonly requireSagaContextMethods: ReadonlySet<string>;
54
+ readonly sagaContextEnforce: "warn" | "reject";
55
+ }
56
+ /**
57
+ * Bootstrap the gRPC interceptor stack. Idempotent (re-calls warn + are
58
+ * ignored). Returns a handle exposing `standardStack()` which adopters
59
+ * call once per RPC server set-up.
60
+ */
61
+ export declare function configureGrpcInterceptors(options: ConfigureGrpcInterceptorsOptions): ConfiguredGrpcInterceptors;
62
+ /** Diagnostics — returns null when configureGrpcInterceptors not yet called. */
63
+ export declare function getConfiguredOrNull(): ConfiguredGrpcInterceptors | null;
64
+ /** Test-only — drop the resolved registry so the next call re-bootstraps. */
65
+ export declare function _resetConfigureForTests(): void;
66
+ //# sourceMappingURL=configure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.d.ts","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"AA0CA,OAAO,KAAK,EACV,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,iBAAiB,EACjB,aAAa,EAGb,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAGjB,MAAM,WAAW,gCAAgC;IAC/C,2EAA2E;IAC3E,gBAAgB,EAAE,MAAM,CAAC;IACzB,2EAA2E;IAC3E,EAAE,CAAC,EAAE,YAAY,CAAC;IAClB;;;;OAIG;IACH,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,yEAAyE;IACzE,oBAAoB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC3C,iEAAiE;IACjE,cAAc,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACrC,wEAAwE;IACxE,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAC7C,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,MAAM,CAAC,EAAE,gBAAgB,CAAC;IAC1B,QAAQ,CAAC,EAAE,cAAc,CAAC;IAC1B,YAAY,CAAC,EAAE,kBAAkB,CAAC;IAClC,gEAAgE;IAChE,MAAM,CAAC,EAAE,iBAAiB,CAAC;IAC3B;;;OAGG;IACH,yBAAyB,CAAC,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAChD,oEAAoE;IACpE,kBAAkB,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;CACxC;AAED,MAAM,WAAW,0BAA0B;IACzC;;;;;;OAMG;IACH,aAAa,IAAI,gBAAgB,CAAC;IAClC,wEAAwE;IACxE,QAAQ,CAAC,QAAQ,EAAE,8BAA8B,CAAC;CACnD;AAED,MAAM,WAAW,8BAA8B;IAC7C,QAAQ,CAAC,gBAAgB,EAAE,MAAM,CAAC;IAClC,QAAQ,CAAC,EAAE,EAAE,YAAY,GAAG,IAAI,CAAC;IACjC,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,oBAAoB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACnD,QAAQ,CAAC,cAAc,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IAC7C,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IACrD,QAAQ,CAAC,yBAAyB,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACxD,QAAQ,CAAC,kBAAkB,EAAE,MAAM,GAAG,QAAQ,CAAC;CAChD;AAID;;;;GAIG;AACH,wBAAgB,yBAAyB,CACvC,OAAO,EAAE,gCAAgC,GACxC,0BAA0B,CAuF5B;AAED,gFAAgF;AAChF,wBAAgB,mBAAmB,IAAI,0BAA0B,GAAG,IAAI,CAEvE;AAED,6EAA6E;AAC7E,wBAAgB,uBAAuB,IAAI,IAAI,CAE9C"}
@@ -0,0 +1,169 @@
1
+ // configureGrpcInterceptors — spec § 5.2 + § 5.5.
2
+ //
3
+ // Boot helper that stores the resolved stack config in process-local
4
+ // state and produces the composed standard server stack on demand.
5
+ // Services call this once at process start (after `initSaga` +
6
+ // `initIdempotency` + auth bootstrap have run); subsequent calls to
7
+ // `createStandardServerStack()` reach into the registry for defaults.
8
+ //
9
+ // Surface:
10
+ // configureGrpcInterceptors({
11
+ // serviceShortName: "billing",
12
+ // db,
13
+ // redis, // optional — used by idempotencyGuard slot
14
+ // errorCatalog?,
15
+ // logging?,
16
+ // audit?,
17
+ // enrich?,
18
+ // deadline?,
19
+ // cancellation?,
20
+ // mutatorMethods?, // gRPC methods that REQUIRE the idempotency header
21
+ // systemContextMethods?, // gRPC methods that opt out of tenant scoping
22
+ // });
23
+ //
24
+ // Returns the composed `UnaryInterceptor` factory wired with the full
25
+ // locked stack (logging → audit → auth → enrich → saga → signal-binder →
26
+ // idempotency-guard → tenant → audit-ctx → mfa → deadline → cancellation
27
+ // → error-map → handler).
28
+ import { idempotencyGuard } from "@nodii/idempotency";
29
+ import { sagaContext } from "@nodii/saga";
30
+ import { signalBinder } from "./interceptors/signal-binder";
31
+ import { cancellationGuard, deadlineGuard, enrichAuthContext, errorMap, STANDARD_ERROR_CATALOG, tenantContext, withAuditUnary, withLoggingUnary, } from "./interceptors-exports";
32
+ import { auditContext } from "./interceptors/audit-context";
33
+ import { GrpcStatusError } from "./types";
34
+ let resolved = null;
35
+ /**
36
+ * Bootstrap the gRPC interceptor stack. Idempotent (re-calls warn + are
37
+ * ignored). Returns a handle exposing `standardStack()` which adopters
38
+ * call once per RPC server set-up.
39
+ */
40
+ export function configureGrpcInterceptors(options) {
41
+ if (!options) {
42
+ throw new GrpcStatusError("INTERNAL", "interceptor_config_required");
43
+ }
44
+ if (!options.serviceShortName) {
45
+ throw new GrpcStatusError("INTERNAL", "service_short_name_required");
46
+ }
47
+ if (resolved) {
48
+ // eslint-disable-next-line no-console
49
+ console.warn("[@nodii/grpc-interceptors] configureGrpcInterceptors() called more than once; ignoring subsequent call.");
50
+ return resolved;
51
+ }
52
+ const resolvedConfig = {
53
+ serviceShortName: options.serviceShortName,
54
+ db: options.db ?? null,
55
+ mutatorMethods: options.mutatorMethods ?? new Set(),
56
+ systemContextMethods: options.systemContextMethods ?? new Set(),
57
+ skipForMethods: options.skipForMethods ?? new Set(),
58
+ errorCatalog: {
59
+ ...STANDARD_ERROR_CATALOG,
60
+ ...(options.errorCatalog ?? {}),
61
+ },
62
+ requireSagaContextMethods: options.requireSagaContextMethods ?? new Set(),
63
+ sagaContextEnforce: options.sagaContextEnforce ?? "warn",
64
+ };
65
+ const interceptors = [
66
+ withLoggingUnary({
67
+ ...(options.logging ?? {}),
68
+ logger: options.logger ?? options.logging?.logger,
69
+ }),
70
+ withAuditUnary(options.audit ?? {}),
71
+ // withAuthUnary slot: services supply their own configured wrapper
72
+ // via the re-exported `withAuthUnary` (it requires JWKS / token
73
+ // manager wiring that varies per service). This factory composes
74
+ // around a passthrough; services that need auth wrap THEIR handler
75
+ // with the auth re-export before passing to standardStack().
76
+ passthroughSlot(),
77
+ enrichAuthContext(options.enrich ?? {}),
78
+ // Real saga sagaContext re-export. Requires saga library to be
79
+ // initialized; if not initialized, sagaContext throws — that's
80
+ // intentional (the service should init saga before this boot helper).
81
+ sagaContextSlot(resolvedConfig.requireSagaContextMethods, resolvedConfig.sagaContextEnforce),
82
+ // Real signalBinder.
83
+ signalBinder(),
84
+ // Real idempotencyGuard re-export.
85
+ idempotencyGuardSlot(resolvedConfig.mutatorMethods),
86
+ ...(options.db
87
+ ? [
88
+ tenantContext({
89
+ db: options.db,
90
+ systemContextMethods: resolvedConfig.systemContextMethods,
91
+ }),
92
+ auditContext({
93
+ db: options.db,
94
+ serviceShortName: options.serviceShortName,
95
+ }),
96
+ ]
97
+ : []),
98
+ passthroughSlot(), // mfaRequiredInterceptor slot — service-wired
99
+ deadlineGuard(options.deadline ?? {}),
100
+ cancellationGuard(options.cancellation ?? {}),
101
+ errorMap(resolvedConfig.errorCatalog),
102
+ ];
103
+ resolved = {
104
+ standardStack() {
105
+ return (methodName, handler) => {
106
+ if (resolvedConfig.skipForMethods.has(methodName))
107
+ return handler;
108
+ let wrapped = handler;
109
+ for (let i = interceptors.length - 1; i >= 0; i--) {
110
+ const factory = interceptors[i];
111
+ if (factory)
112
+ wrapped = factory(methodName, wrapped);
113
+ }
114
+ return wrapped;
115
+ };
116
+ },
117
+ resolved: resolvedConfig,
118
+ };
119
+ return resolved;
120
+ }
121
+ /** Diagnostics — returns null when configureGrpcInterceptors not yet called. */
122
+ export function getConfiguredOrNull() {
123
+ return resolved;
124
+ }
125
+ /** Test-only — drop the resolved registry so the next call re-bootstraps. */
126
+ export function _resetConfigureForTests() {
127
+ resolved = null;
128
+ }
129
+ // ── Internal slot helpers ────────────────────────────────────────────────────
130
+ function passthroughSlot() {
131
+ return (_method, handler) => async (call) => handler(call);
132
+ }
133
+ function sagaContextSlot(requireMethods, enforce) {
134
+ // sagaContext from @nodii/saga is a method-name-keyed enforcer; build it
135
+ // here so we can swap the requireSagaContextMethods set lazily.
136
+ const built = sagaContext({
137
+ requireSagaContextMethods: requireMethods,
138
+ enforce,
139
+ });
140
+ return (methodName, handler) => {
141
+ const inner = built(methodName, handler);
142
+ return async (call) => inner(call);
143
+ };
144
+ }
145
+ function idempotencyGuardSlot(mutatorMethods) {
146
+ // idempotencyGuard from @nodii/idempotency returns a handler-wrapper, not
147
+ // a method-keyed factory. We adapt it to the UnaryInterceptor contract by
148
+ // wrapping per call and supplying method extraction via the call.
149
+ const built = idempotencyGuard({
150
+ mutatorMethods: new Set(mutatorMethods),
151
+ getMethodName: (call) => {
152
+ const direct = call
153
+ .__methodName;
154
+ if (typeof direct === "string")
155
+ return direct;
156
+ return call.call?.handler?.path ?? "<unknown-method>";
157
+ },
158
+ });
159
+ return (methodName, handler) => {
160
+ return async (call) => {
161
+ // Stamp the method name onto the call so the guard's getMethodName
162
+ // can pick it up without a real @grpc/grpc-js call envelope.
163
+ call.__methodName = methodName;
164
+ const guarded = built(handler);
165
+ return guarded(call);
166
+ };
167
+ };
168
+ }
169
+ //# sourceMappingURL=configure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"configure.js","sourceRoot":"","sources":["../src/configure.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import type { StandardServerStackConfig, UnaryInterceptor } from "./types";
2
+ /**
3
+ * Build the standard composed stack with the locked outer→inner order
4
+ * per spec § 5.4. Accepts a single config; rejects custom-order args.
5
+ */
6
+ export declare function createStandardServerStack(config: StandardServerStackConfig): UnaryInterceptor;
7
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAwBA,OAAO,KAAK,EACV,yBAAyB,EAGzB,gBAAgB,EACjB,MAAM,SAAS,CAAC;AAUjB;;;GAGG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,EAAE,yBAAyB,GAChC,gBAAgB,CAmFlB"}
@@ -0,0 +1,100 @@
1
+ // createStandardServerStack — spec § 5.3 + § 5.4.
2
+ //
3
+ // Produces the locked 13-interceptor outer→inner composition. v0.1.1: the
4
+ // saga/idempotency slots are REAL re-exports from @nodii/saga and
5
+ // @nodii/idempotency (sibling libs on main). The withAuthUnary + mfa
6
+ // slots remain passthrough at this layer because they require
7
+ // service-specific JWKS / token-manager wiring; services wrap their
8
+ // handler with `withAuthUnary` from `@nodii/grpc-auth` (re-exported from
9
+ // this lib) before passing it to the composed factory.
10
+ import { idempotencyGuard } from "@nodii/idempotency";
11
+ import { sagaContext } from "@nodii/saga";
12
+ import { signalBinder } from "./interceptors/signal-binder";
13
+ import { cancellationGuard, deadlineGuard, enrichAuthContext, errorMap, STANDARD_ERROR_CATALOG, tenantContext, withAuditUnary, withLoggingUnary, auditContext, } from "./interceptors-exports";
14
+ import { GrpcStatusError } from "./types";
15
+ /** Pure passthrough — used for slots services wire themselves. */
16
+ function passthrough() {
17
+ return (_methodName, handler) => async (call) => handler(call);
18
+ }
19
+ /**
20
+ * Build the standard composed stack with the locked outer→inner order
21
+ * per spec § 5.4. Accepts a single config; rejects custom-order args.
22
+ */
23
+ export function createStandardServerStack(config) {
24
+ if (!config) {
25
+ throw new GrpcStatusError("INTERNAL", "interceptor_config_required");
26
+ }
27
+ if ("interceptors" in config ||
28
+ "order" in config) {
29
+ // Spec § 5.4 — custom-order args rejected at v0.1.0.
30
+ throw new GrpcStatusError("INTERNAL", "composition_order_locked");
31
+ }
32
+ const skipFor = config.skipForMethods ?? new Set();
33
+ const mutatorMethods = config.mutatorMethods ?? new Set();
34
+ const requireSagaCtxMethods = config.requireSagaContextMethods ?? new Set();
35
+ const sagaEnforce = config.sagaContextEnforce ?? "warn";
36
+ const builtSagaContext = sagaContext({
37
+ requireSagaContextMethods: requireSagaCtxMethods,
38
+ enforce: sagaEnforce,
39
+ });
40
+ const builtIdemGuard = idempotencyGuard({
41
+ mutatorMethods: new Set(mutatorMethods),
42
+ getMethodName: (call) => {
43
+ const direct = call
44
+ .__methodName;
45
+ if (typeof direct === "string")
46
+ return direct;
47
+ return call.call?.handler?.path ?? "<unknown-method>";
48
+ },
49
+ });
50
+ const stack = [
51
+ withLoggingUnary({ ...(config.logging ?? {}), logger: config.logger }),
52
+ withAuditUnary(config.audit ?? {}),
53
+ passthrough(), // withAuthUnary slot — service-wired
54
+ enrichAuthContext(config.enrich ?? {}),
55
+ (methodName, handler) => {
56
+ const inner = builtSagaContext(methodName, handler);
57
+ return async (call) => inner(call);
58
+ },
59
+ signalBinder(),
60
+ (methodName, handler) => {
61
+ return async (call) => {
62
+ call.__methodName =
63
+ methodName;
64
+ const guarded = builtIdemGuard(handler);
65
+ return guarded(call);
66
+ };
67
+ },
68
+ ...(config.db
69
+ ? [
70
+ tenantContext({
71
+ db: config.db,
72
+ systemContextMethods: config.tenant?.systemContextMethods,
73
+ }),
74
+ auditContext({
75
+ db: config.db,
76
+ serviceShortName: config.serviceShortName,
77
+ }),
78
+ ]
79
+ : []),
80
+ passthrough(), // mfaRequiredInterceptor slot — service-wired
81
+ deadlineGuard(config.deadline ?? {}),
82
+ cancellationGuard(config.cancellation ?? {}),
83
+ errorMap({
84
+ ...STANDARD_ERROR_CATALOG,
85
+ ...(config.errorCatalog ?? {}),
86
+ }),
87
+ ];
88
+ return (methodName, handler) => {
89
+ if (skipFor.has(methodName))
90
+ return handler;
91
+ let wrapped = handler;
92
+ for (let i = stack.length - 1; i >= 0; i--) {
93
+ const factory = stack[i];
94
+ if (factory)
95
+ wrapped = factory(methodName, wrapped);
96
+ }
97
+ return wrapped;
98
+ };
99
+ }
100
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,3 +1,20 @@
1
1
  export declare const LIB_NAME = "grpc-interceptors";
2
- export declare const VERSION = "0.0.1";
2
+ export declare const VERSION = "0.1.1";
3
+ export { withLoggingUnary } from "./interceptors/logging";
4
+ export { withAuditUnary } from "./interceptors/audit";
5
+ export { enrichAuthContext } from "./interceptors/enrich-auth";
6
+ export { tenantContext } from "./interceptors/tenant-context";
7
+ export { auditContext } from "./interceptors/audit-context";
8
+ export { deadlineGuard } from "./interceptors/deadline-guard";
9
+ export { cancellationGuard } from "./interceptors/cancellation-guard";
10
+ export { errorMap, STANDARD_ERROR_CATALOG, } from "./interceptors/error-map";
11
+ export { createStandardServerStack } from "./factory";
12
+ export { composeUnaryInterceptors } from "./compose";
13
+ export { configureGrpcInterceptors, getConfiguredOrNull, _resetConfigureForTests, } from "./configure";
14
+ export type { ConfigureGrpcInterceptorsOptions, ConfiguredGrpcInterceptors, ResolvedGrpcInterceptorsConfig, } from "./configure";
15
+ export { _resetTelemetryShimForTests, _setTelemetryShimForTests, } from "./telemetry-shim";
16
+ export * from "./reexports";
17
+ export type { SagaHeaderInjector } from "./interceptors/saga-headers";
18
+ export type { AuditConfig, AuditContextConfig, AuditEmitter, AuthOnCall, CancellationConfig, DbConnection, DeadlineConfig, EnrichAuthConfig, ErrorMapEntry, GrpcStatusCode, InterceptorLogger, LoggingConfig, StandardServerStackConfig, TelemetryShim, TenantContextConfig, UnaryCall, UnaryHandler, UnaryInterceptor, } from "./types";
19
+ export { GrpcStatusError, NotImplementedError, RpcCancelledError, } from "./types";
3
20
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAKA,eAAO,MAAM,QAAQ,sBAAsB,CAAC;AAC5C,eAAO,MAAM,OAAO,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAUA,eAAO,MAAM,QAAQ,sBAAsB,CAAC;AAC5C,eAAO,MAAM,OAAO,UAAU,CAAC;AAG/B,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EACL,QAAQ,EACR,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAGrD,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,gCAAgC,EAChC,0BAA0B,EAC1B,8BAA8B,GAC/B,MAAM,aAAa,CAAC;AAGrB,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAI1B,cAAc,aAAa,CAAC;AAC5B,YAAY,EAAE,kBAAkB,EAAE,MAAM,6BAA6B,CAAC;AAGtE,YAAY,EACV,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,UAAU,EACV,kBAAkB,EAClB,YAAY,EACZ,cAAc,EACd,gBAAgB,EAChB,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,aAAa,EACb,yBAAyB,EACzB,aAAa,EACb,mBAAmB,EACnB,SAAS,EACT,YAAY,EACZ,gBAAgB,GACjB,MAAM,SAAS,CAAC;AACjB,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,SAAS,CAAC"}
package/dist/index.js CHANGED
@@ -1,7 +1,32 @@
1
- // @nodii/grpc-interceptors — placeholder at v0.0.1.
2
- // Implementation lands at v0.1.0 per the locked feature_doc.
1
+ // @nodii/grpc-interceptors — v0.1.1 public barrel.
3
2
  //
4
- // Spec: https://planning.dev.nucleus-cloud.in/api/v1/feature-docs?serviceId=nodii-libs&docKey=grpc-interceptors
3
+ // Spec: planning hub feature_doc serviceId=nodii-libs docKey=grpc-interceptors.
4
+ //
5
+ // Single-import surface: 8 owned cross-cutting interceptors + real
6
+ // re-exports of every gRPC interceptor + `composeUnaryInterceptors`
7
+ // helper from the peer libraries (`@nodii/grpc-auth`, `@nodii/saga`,
8
+ // `@nodii/idempotency`) + `configureGrpcInterceptors` boot helper +
9
+ // `createStandardServerStack` factory locked-order composer.
5
10
  export const LIB_NAME = "grpc-interceptors";
6
- export const VERSION = "0.0.1";
11
+ export const VERSION = "0.1.1";
12
+ // Owned interceptors.
13
+ export { withLoggingUnary } from "./interceptors/logging";
14
+ export { withAuditUnary } from "./interceptors/audit";
15
+ export { enrichAuthContext } from "./interceptors/enrich-auth";
16
+ export { tenantContext } from "./interceptors/tenant-context";
17
+ export { auditContext } from "./interceptors/audit-context";
18
+ export { deadlineGuard } from "./interceptors/deadline-guard";
19
+ export { cancellationGuard } from "./interceptors/cancellation-guard";
20
+ export { errorMap, STANDARD_ERROR_CATALOG, } from "./interceptors/error-map";
21
+ // Composed-stack factory + composer.
22
+ export { createStandardServerStack } from "./factory";
23
+ export { composeUnaryInterceptors } from "./compose";
24
+ // Boot helper (spec § 5.2 + § 5.5).
25
+ export { configureGrpcInterceptors, getConfiguredOrNull, _resetConfigureForTests, } from "./configure";
26
+ // Test doubles + helpers.
27
+ export { _resetTelemetryShimForTests, _setTelemetryShimForTests, } from "./telemetry-shim";
28
+ // Re-export façade (real grpc-auth + real saga + real idempotency + owned
29
+ // signalBinder + withSagaHeaders).
30
+ export * from "./reexports";
31
+ export { GrpcStatusError, NotImplementedError, RpcCancelledError, } from "./types";
7
32
  //# 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,oDAAoD;AACpD,6DAA6D;AAC7D,EAAE;AACF,gHAAgH;AAEhH,MAAM,CAAC,MAAM,QAAQ,GAAG,mBAAmB,CAAC;AAC5C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,mDAAmD;AACnD,EAAE;AACF,gFAAgF;AAChF,EAAE;AACF,mEAAmE;AACnE,oEAAoE;AACpE,qEAAqE;AACrE,oEAAoE;AACpE,6DAA6D;AAE7D,MAAM,CAAC,MAAM,QAAQ,GAAG,mBAAmB,CAAC;AAC5C,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,sBAAsB;AACtB,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC/D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,YAAY,EAAE,MAAM,8BAA8B,CAAC;AAC5D,OAAO,EAAE,aAAa,EAAE,MAAM,+BAA+B,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mCAAmC,CAAC;AACtE,OAAO,EACL,QAAQ,EACR,sBAAsB,GACvB,MAAM,0BAA0B,CAAC;AAElC,qCAAqC;AACrC,OAAO,EAAE,yBAAyB,EAAE,MAAM,WAAW,CAAC;AACtD,OAAO,EAAE,wBAAwB,EAAE,MAAM,WAAW,CAAC;AAErD,oCAAoC;AACpC,OAAO,EACL,yBAAyB,EACzB,mBAAmB,EACnB,uBAAuB,GACxB,MAAM,aAAa,CAAC;AAOrB,0BAA0B;AAC1B,OAAO,EACL,2BAA2B,EAC3B,yBAAyB,GAC1B,MAAM,kBAAkB,CAAC;AAE1B,0EAA0E;AAC1E,mCAAmC;AACnC,cAAc,aAAa,CAAC;AAwB5B,OAAO,EACL,eAAe,EACf,mBAAmB,EACnB,iBAAiB,GAClB,MAAM,SAAS,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { AuditContextConfig, UnaryInterceptor } from "../types";
2
+ export declare function auditContext(config: AuditContextConfig): UnaryInterceptor;
3
+ //# sourceMappingURL=audit-context.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-context.d.ts","sourceRoot":"","sources":["../../src/interceptors/audit-context.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EACV,kBAAkB,EAGlB,gBAAgB,EACjB,MAAM,UAAU,CAAC;AAGlB,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,gBAAgB,CA6BzE"}
@@ -0,0 +1,59 @@
1
+ // auditContext — spec § 5.9.
2
+ //
3
+ // `SELECT set_config('<service>.audit_ctx', $1, true)` on the same ALS-bound
4
+ // connection used by `tenantContext`. Read by service-side audit triggers
5
+ // via `current_setting('<service>.audit_ctx', true)::jsonb`. Best-effort:
6
+ // `set_config` failures log + the call proceeds (audit-as-best-effort).
7
+ import { resolveTelemetry } from "../telemetry-shim";
8
+ import { GrpcStatusError } from "../types";
9
+ export function auditContext(config) {
10
+ if (!config.db) {
11
+ throw new GrpcStatusError("INTERNAL", "audit_context_db_unconfigured");
12
+ }
13
+ if (!config.serviceShortName) {
14
+ throw new GrpcStatusError("INTERNAL", "audit_context_service_short_name_required");
15
+ }
16
+ const gucName = `${config.serviceShortName}.audit_ctx`;
17
+ return (_methodName, handler) => {
18
+ return async (call) => {
19
+ const payload = buildPayload(call);
20
+ try {
21
+ await config.db.exec("SELECT set_config($1, $2, true)", [
22
+ gucName,
23
+ JSON.stringify(payload),
24
+ ]);
25
+ }
26
+ catch (err) {
27
+ resolveTelemetry().logger.error("audit_context.set_config_failed", {
28
+ error: err instanceof Error ? err.message : String(err),
29
+ guc: gucName,
30
+ });
31
+ }
32
+ return handler(call);
33
+ };
34
+ };
35
+ }
36
+ function buildPayload(call) {
37
+ const service = call.auth?.serviceActor;
38
+ const user = call.auth?.userActor;
39
+ const reqCtx = call.auth?.requestContext;
40
+ return {
41
+ service_actor: service
42
+ ? {
43
+ service_id: service.service_id ?? service.serviceId,
44
+ service_name: service.service_name ?? service.serviceName,
45
+ }
46
+ : null,
47
+ user_actor: user
48
+ ? {
49
+ user_id: user.user_id,
50
+ tenant_id: user.tenant_id,
51
+ user_role: user.user_role,
52
+ }
53
+ : null,
54
+ correlation_id: reqCtx?.correlationId ?? null,
55
+ tenant_id: reqCtx?.tenant_id ?? null,
56
+ intent_id: reqCtx?.intent_id ?? null,
57
+ };
58
+ }
59
+ //# sourceMappingURL=audit-context.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit-context.js","sourceRoot":"","sources":["../../src/interceptors/audit-context.ts"],"names":[],"mappings":"AAAA,6BAA6B;AAC7B,EAAE;AACF,6EAA6E;AAC7E,0EAA0E;AAC1E,0EAA0E;AAC1E,wEAAwE;AAExE,OAAO,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAOrD,OAAO,EAAE,eAAe,EAAE,MAAM,UAAU,CAAC;AAE3C,MAAM,UAAU,YAAY,CAAC,MAA0B;IACrD,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;QACf,MAAM,IAAI,eAAe,CAAC,UAAU,EAAE,+BAA+B,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,CAAC,MAAM,CAAC,gBAAgB,EAAE,CAAC;QAC7B,MAAM,IAAI,eAAe,CACvB,UAAU,EACV,2CAA2C,CAC5C,CAAC;IACJ,CAAC;IACD,MAAM,OAAO,GAAG,GAAG,MAAM,CAAC,gBAAgB,YAAY,CAAC;IAEvD,OAAO,CAAC,WAAmB,EAAE,OAAqB,EAAgB,EAAE;QAClE,OAAO,KAAK,EAAE,IAAe,EAAoB,EAAE;YACjD,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,CAAC;YACnC,IAAI,CAAC;gBACH,MAAM,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,iCAAiC,EAAE;oBACtD,OAAO;oBACP,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;iBACxB,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,gBAAgB,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,iCAAiC,EAAE;oBACjE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;oBACvD,GAAG,EAAE,OAAO;iBACb,CAAC,CAAC;YACL,CAAC;YACD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC;QACvB,CAAC,CAAC;IACJ,CAAC,CAAC;AACJ,CAAC;AAED,SAAS,YAAY,CAAC,IAAe;IACnC,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,YAAY,CAAC;IACxC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,EAAE,SAAS,CAAC;IAClC,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC;IACzC,OAAO;QACL,aAAa,EAAE,OAAO;YACpB,CAAC,CAAC;gBACE,UAAU,EAAE,OAAO,CAAC,UAAU,IAAI,OAAO,CAAC,SAAS;gBACnD,YAAY,EAAE,OAAO,CAAC,YAAY,IAAI,OAAO,CAAC,WAAW;aAC1D;YACH,CAAC,CAAC,IAAI;QACR,UAAU,EAAE,IAAI;YACd,CAAC,CAAC;gBACE,OAAO,EAAE,IAAI,CAAC,OAAO;gBACrB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,SAAS,EAAE,IAAI,CAAC,SAAS;aAC1B;YACH,CAAC,CAAC,IAAI;QACR,cAAc,EAAE,MAAM,EAAE,aAAa,IAAI,IAAI;QAC7C,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,IAAI;QACpC,SAAS,EAAE,MAAM,EAAE,SAAS,IAAI,IAAI;KACrC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { AuditConfig, UnaryInterceptor } from "../types";
2
+ /**
3
+ * Build the audit interceptor. Sits between logging and auth in the
4
+ * locked composition.
5
+ */
6
+ export declare function withAuditUnary(config?: AuditConfig): UnaryInterceptor;
7
+ //# sourceMappingURL=audit.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audit.d.ts","sourceRoot":"","sources":["../../src/interceptors/audit.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,WAAW,EAIX,gBAAgB,EACjB,MAAM,UAAU,CAAC;AA+BlB;;;GAGG;AACH,wBAAgB,cAAc,CAAC,MAAM,GAAE,WAAgB,GAAG,gBAAgB,CAoDzE"}