@origins-digital/nestjs-shared-key-http 0.0.0-stage → 1.0.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.
package/README.md CHANGED
@@ -1,3 +1,107 @@
1
- # Temporary Holding Version
1
+ # @origins-digital/nestjs-shared-key-http
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ `HttpService` for calls between Origins services: it adds the internal service
4
+ token (`x-internal-auth-token`) and `x-service-name`, so services no longer
5
+ build those headers by hand.
6
+
7
+ ## Rule (`applyInternalAuth`)
8
+
9
+ The internal headers are added only when the request has **neither** an
10
+ `authorization` **nor** an `x-internal-auth-token` header key (case-insensitive,
11
+ whatever the value, `undefined` and `''` included). Key presence means "the
12
+ caller decided": a forwarded session token that is missing is not replaced by
13
+ the internal token, so the service still answers 401.
14
+
15
+ - A caller-provided `x-internal-auth-token` or `x-service-name` is never overwritten.
16
+ - The JWT is fetched only when it will be sent.
17
+ - If the token cannot be resolved, the request rejects before it is sent.
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ yarn add @origins-digital/nestjs-shared-key-http
23
+ ```
24
+
25
+ Peer dependencies: `@nestjs/common`, `@nestjs/axios`, `axios`, `rxjs`,
26
+ `@origins-digital/nestjs-shared-key`.
27
+
28
+ ## Usage
29
+
30
+ `SharedKeyHttpService` needs `SharedKeyService`. The module never registers
31
+ `SharedKeyModule` itself, so the app keeps its key backend (SSM or Secrets
32
+ Manager) and its options. Either register it globally once:
33
+
34
+ ```ts
35
+ @Module({
36
+ imports: [
37
+ SharedKeyModule.forRoot({ isGlobal: true }),
38
+ SharedKeyHttpModule, // default options
39
+ ],
40
+ })
41
+ export class AppModule {}
42
+ ```
43
+
44
+ or pass the module that provides it:
45
+
46
+ ```ts
47
+ SharedKeyHttpModule.register({
48
+ serviceName: 'origins-backoffice-orchestrator', // x-service-name
49
+ imports: [SharedKeyModule],
50
+ axiosConfig: { timeout: 10_000 }, // defaults of the module's own axios instance
51
+ isGlobal: false,
52
+ });
53
+ ```
54
+
55
+ Then inject it (it extends `HttpService`):
56
+
57
+ ```ts
58
+ @Injectable()
59
+ export class VideoClient {
60
+ constructor(private readonly http: SharedKeyHttpService) {}
61
+
62
+ async getVideo(id: string) {
63
+ const { data } = await this.http.getAsPromise<Video>(`${host}/videos/${id}`, {
64
+ requestedService: 'origins-video-service',
65
+ });
66
+ return data;
67
+ }
68
+ }
69
+ ```
70
+
71
+ - `getAsPromise`, `postAsPromise`, `putAsPromise`, `patchAsPromise`,
72
+ `deleteAsPromise`, `headAsPromise` turn HTTP errors into the Nest exception
73
+ built by `raiseError` (`@origins-digital/error-utils`), labelled with
74
+ `requestedService`. Other errors pass through unchanged.
75
+ - The Observable methods of `HttpService` (`get`, `post`, ...) apply the same rule.
76
+ - The service uses its own axios instance: a plain `HttpModule` (calls to
77
+ external hosts) never gets the internal token.
78
+
79
+ `x-service-name` defaults to `${APP_ENV}-${npm_package_name}` (the package name
80
+ alone without `APP_ENV`, `unknown-service` without a package name). Note that
81
+ `npm_package_name` is only set when the app is started through npm/yarn; pass
82
+ `serviceName` to make it explicit.
83
+
84
+ ## Other clients (hey-api)
85
+
86
+ The rule is a plain axios request interceptor, reusable on any axios instance:
87
+
88
+ ```ts
89
+ client.instance.interceptors.request.use((config) =>
90
+ applyInternalAuth(config, () => sharedKeyHttp.internalHeaders()),
91
+ );
92
+ keepCallerAuthKeys(client);
93
+ ```
94
+
95
+ hey-api drops header keys whose value is `undefined` before axios runs, so the
96
+ rule would not see `authorization: undefined`. `keepCallerAuthKeys(client)`
97
+ wraps the client's request methods and sends `''` instead
98
+ (`withCallerAuthKeys(options)` is the pure version). Nest's `HttpService` keeps
99
+ undefined keys, so `SharedKeyHttpService` does not need it.
100
+
101
+ ## Build
102
+
103
+ ```bash
104
+ yarn build
105
+ yarn test
106
+ yarn lint
107
+ ```
@@ -0,0 +1,40 @@
1
+ export type CallerAuthCallOptions = {
2
+ headers?: unknown;
3
+ };
4
+ export declare const HTTP_CLIENT_METHODS: readonly ["request", "get", "post", "put", "patch", "delete", "head", "options", "connect", "trace"];
5
+ /**
6
+ * The part of a generated client (e.g. a hey-api axios client) that
7
+ * `keepCallerAuthKeys` wraps. Methods are declared as methods (bivariant
8
+ * parameters), so each generated client's narrower option types fit.
9
+ */
10
+ export interface CallerAuthClient {
11
+ request(options?: CallerAuthCallOptions): unknown;
12
+ get(options?: CallerAuthCallOptions): unknown;
13
+ post(options?: CallerAuthCallOptions): unknown;
14
+ put(options?: CallerAuthCallOptions): unknown;
15
+ patch(options?: CallerAuthCallOptions): unknown;
16
+ delete(options?: CallerAuthCallOptions): unknown;
17
+ head(options?: CallerAuthCallOptions): unknown;
18
+ options(options?: CallerAuthCallOptions): unknown;
19
+ connect(options?: CallerAuthCallOptions): unknown;
20
+ trace(options?: CallerAuthCallOptions): unknown;
21
+ }
22
+ /**
23
+ * Returns `options` with undefined `authorization` / `x-internal-auth-token`
24
+ * header values replaced by ''. Only plain-object headers are normalised;
25
+ * anything else (none, `Headers`, `AxiosHeaders`) is returned as is.
26
+ */
27
+ export declare const withCallerAuthKeys: (options?: CallerAuthCallOptions) => CallerAuthCallOptions | undefined;
28
+ /**
29
+ * Some clients (hey-api) drop header keys whose value is undefined before axios
30
+ * runs, so `applyInternalAuth` would not see `authorization: undefined` and
31
+ * would add the internal token. Wrapping the client's request methods with
32
+ * `withCallerAuthKeys` sends '' instead, which keeps the caller's choice
33
+ * visible: the rule leaves the request alone and the service answers 401, as
34
+ * it does for a missing header. Mutates and returns `client`.
35
+ *
36
+ * Not needed on Nest's `HttpService`: it hands the config to axios as is, and
37
+ * axios keeps undefined header keys.
38
+ */
39
+ export declare const keepCallerAuthKeys: <C extends CallerAuthClient>(client: C) => C;
40
+ //# sourceMappingURL=caller-auth-keys.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caller-auth-keys.d.ts","sourceRoot":"","sources":["../src/caller-auth-keys.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,qBAAqB,GAAG;IAAE,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE1D,eAAO,MAAM,mBAAmB,sGAWtB,CAAC;AAEX;;;;GAIG;AACH,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAClD,GAAG,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAC9C,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAC/C,GAAG,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAC9C,KAAK,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAChD,MAAM,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;IACjD,IAAI,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAC/C,OAAO,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAClD,OAAO,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;IAClD,KAAK,CAAC,OAAO,CAAC,EAAE,qBAAqB,GAAG,OAAO,CAAC;CACjD;AAWD;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,GAC7B,UAAU,qBAAqB,KAC9B,qBAAqB,GAAG,SAY1B,CAAC;AAEF;;;;;;;;;;GAUG;AACH,eAAO,MAAM,kBAAkB,GAAI,CAAC,SAAS,gBAAgB,EAC3D,QAAQ,CAAC,KACR,CAQF,CAAC"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.keepCallerAuthKeys = exports.withCallerAuthKeys = exports.HTTP_CLIENT_METHODS = void 0;
4
+ const internal_auth_rule_1 = require("./internal-auth.rule");
5
+ exports.HTTP_CLIENT_METHODS = [
6
+ 'request',
7
+ 'get',
8
+ 'post',
9
+ 'put',
10
+ 'patch',
11
+ 'delete',
12
+ 'head',
13
+ 'options',
14
+ 'connect',
15
+ 'trace',
16
+ ];
17
+ const isPlainObject = (value) => {
18
+ if (typeof value !== 'object' || value === null)
19
+ return false;
20
+ const proto = Object.getPrototypeOf(value);
21
+ return proto === Object.prototype || proto === null;
22
+ };
23
+ const isUndefinedCallerAuth = ([key, value]) => value === undefined && internal_auth_rule_1.CALLER_AUTH_HEADERS.has(key.toLowerCase());
24
+ /**
25
+ * Returns `options` with undefined `authorization` / `x-internal-auth-token`
26
+ * header values replaced by ''. Only plain-object headers are normalised;
27
+ * anything else (none, `Headers`, `AxiosHeaders`) is returned as is.
28
+ */
29
+ const withCallerAuthKeys = (options) => {
30
+ const headers = options === null || options === void 0 ? void 0 : options.headers;
31
+ if (!isPlainObject(headers))
32
+ return options;
33
+ const entries = Object.entries(headers);
34
+ if (!entries.some(isUndefinedCallerAuth))
35
+ return options;
36
+ const kept = entries.map(([key, value]) => [
37
+ key,
38
+ isUndefinedCallerAuth([key, value]) ? '' : value,
39
+ ]);
40
+ return Object.assign(Object.assign({}, options), { headers: Object.fromEntries(kept) });
41
+ };
42
+ exports.withCallerAuthKeys = withCallerAuthKeys;
43
+ /**
44
+ * Some clients (hey-api) drop header keys whose value is undefined before axios
45
+ * runs, so `applyInternalAuth` would not see `authorization: undefined` and
46
+ * would add the internal token. Wrapping the client's request methods with
47
+ * `withCallerAuthKeys` sends '' instead, which keeps the caller's choice
48
+ * visible: the rule leaves the request alone and the service answers 401, as
49
+ * it does for a missing header. Mutates and returns `client`.
50
+ *
51
+ * Not needed on Nest's `HttpService`: it hands the config to axios as is, and
52
+ * axios keeps undefined header keys.
53
+ */
54
+ const keepCallerAuthKeys = (client) => {
55
+ const target = client;
56
+ for (const method of exports.HTTP_CLIENT_METHODS) {
57
+ const send = target[method].bind(target);
58
+ target[method] = (options) => send((0, exports.withCallerAuthKeys)(options));
59
+ }
60
+ return client;
61
+ };
62
+ exports.keepCallerAuthKeys = keepCallerAuthKeys;
63
+ //# sourceMappingURL=caller-auth-keys.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"caller-auth-keys.js","sourceRoot":"","sources":["../src/caller-auth-keys.ts"],"names":[],"mappings":";;;AAAA,6DAA2D;AAI9C,QAAA,mBAAmB,GAAG;IACjC,SAAS;IACT,KAAK;IACL,MAAM;IACN,KAAK;IACL,OAAO;IACP,QAAQ;IACR,MAAM;IACN,SAAS;IACT,SAAS;IACT,OAAO;CACC,CAAC;AAoBX,MAAM,aAAa,GAAG,CAAC,KAAc,EAAoC,EAAE;IACzE,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;QAAE,OAAO,KAAK,CAAC;IAC9D,MAAM,KAAK,GAAY,MAAM,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC;IACpD,OAAO,KAAK,KAAK,MAAM,CAAC,SAAS,IAAI,KAAK,KAAK,IAAI,CAAC;AACtD,CAAC,CAAC;AAEF,MAAM,qBAAqB,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,CAAoB,EAAW,EAAE,CACzE,KAAK,KAAK,SAAS,IAAI,wCAAmB,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC;AAEpE;;;;GAIG;AACI,MAAM,kBAAkB,GAAG,CAChC,OAA+B,EACI,EAAE;IACrC,MAAM,OAAO,GAAG,OAAO,aAAP,OAAO,uBAAP,OAAO,CAAE,OAAO,CAAC;IACjC,IAAI,CAAC,aAAa,CAAC,OAAO,CAAC;QAAE,OAAO,OAAO,CAAC;IAE5C,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACxC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,qBAAqB,CAAC;QAAE,OAAO,OAAO,CAAC;IAEzD,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,EAAqB,EAAE,CAAC;QAC5D,GAAG;QACH,qBAAqB,CAAC,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK;KACjD,CAAC,CAAC;IACH,uCAAY,OAAO,KAAE,OAAO,EAAE,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,IAAG;AAC3D,CAAC,CAAC;AAdW,QAAA,kBAAkB,sBAc7B;AAEF;;;;;;;;;;GAUG;AACI,MAAM,kBAAkB,GAAG,CAChC,MAAS,EACN,EAAE;IACL,MAAM,MAAM,GAAqB,MAAM,CAAC;IACxC,KAAK,MAAM,MAAM,IAAI,2BAAmB,EAAE,CAAC;QACzC,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACzC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,OAA+B,EAAE,EAAE,CACnD,IAAI,CAAC,IAAA,0BAAkB,EAAC,OAAO,CAAC,CAAC,CAAC;IACtC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAVW,QAAA,kBAAkB,sBAU7B"}
@@ -0,0 +1,6 @@
1
+ export * from './internal-auth.rule';
2
+ export * from './caller-auth-keys';
3
+ export * from './shared-key-http.options';
4
+ export * from './shared-key-http.service';
5
+ export * from './shared-key-http.module';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,2BAA2B,CAAC;AAC1C,cAAc,0BAA0B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,22 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./internal-auth.rule"), exports);
18
+ __exportStar(require("./caller-auth-keys"), exports);
19
+ __exportStar(require("./shared-key-http.options"), exports);
20
+ __exportStar(require("./shared-key-http.service"), exports);
21
+ __exportStar(require("./shared-key-http.module"), exports);
22
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,uDAAqC;AACrC,qDAAmC;AACnC,4DAA0C;AAC1C,4DAA0C;AAC1C,2DAAyC"}
@@ -0,0 +1,27 @@
1
+ import { InternalAxiosRequestConfig } from 'axios';
2
+ export declare const INTERNAL_AUTH_TOKEN_HEADER = "x-internal-auth-token";
3
+ export declare const SERVICE_NAME_HEADER = "x-service-name";
4
+ /** Header keys that mean "the caller already chose the credential to send". */
5
+ export declare const CALLER_AUTH_HEADERS: ReadonlySet<string>;
6
+ /** Internal headers to add, e.g. `x-internal-auth-token` and `x-service-name`. */
7
+ export type InternalAuthHeaders = Readonly<Record<string, string>>;
8
+ /** Resolves the internal headers; only called when they will be sent. */
9
+ export type InternalHeadersProvider = () => Promise<InternalAuthHeaders>;
10
+ /**
11
+ * Axios request-interceptor rule for calls to internal services: adds the
12
+ * headers of `headersProvider` unless the request already carries an
13
+ * `authorization` or `x-internal-auth-token` header KEY, compared
14
+ * case-insensitively and whatever its value.
15
+ *
16
+ * Key presence, not value: a caller that forwards `authorization: sessionToken`
17
+ * with an undefined or empty token keeps sending no valid credential (the
18
+ * service answers 401) instead of silently getting the internal token.
19
+ * AxiosHeaders keeps keys whose value is undefined, so `Object.keys` sees them
20
+ * (`has()` would not). Headers the caller already set (e.g. `x-service-name`)
21
+ * are never overwritten. A rejection of `headersProvider` rejects the request
22
+ * before it is sent.
23
+ *
24
+ * Usage: `instance.interceptors.request.use((config) => applyInternalAuth(config, provider))`.
25
+ */
26
+ export declare const applyInternalAuth: (config: InternalAxiosRequestConfig, headersProvider: InternalHeadersProvider) => Promise<InternalAxiosRequestConfig>;
27
+ //# sourceMappingURL=internal-auth.rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-auth.rule.d.ts","sourceRoot":"","sources":["../src/internal-auth.rule.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgB,0BAA0B,EAAE,MAAM,OAAO,CAAC;AAEjE,eAAO,MAAM,0BAA0B,0BAA0B,CAAC;AAClE,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AAEpD,+EAA+E;AAC/E,eAAO,MAAM,mBAAmB,EAAE,WAAW,CAAC,MAAM,CAGlD,CAAC;AAEH,kFAAkF;AAClF,MAAM,MAAM,mBAAmB,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAEnE,yEAAyE;AACzE,MAAM,MAAM,uBAAuB,GAAG,MAAM,OAAO,CAAC,mBAAmB,CAAC,CAAC;AASzE;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,0BAA0B,EAClC,iBAAiB,uBAAuB,KACvC,OAAO,CAAC,0BAA0B,CAWpC,CAAC"}
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyInternalAuth = exports.CALLER_AUTH_HEADERS = exports.SERVICE_NAME_HEADER = exports.INTERNAL_AUTH_TOKEN_HEADER = void 0;
4
+ const axios_1 = require("axios");
5
+ exports.INTERNAL_AUTH_TOKEN_HEADER = 'x-internal-auth-token';
6
+ exports.SERVICE_NAME_HEADER = 'x-service-name';
7
+ /** Header keys that mean "the caller already chose the credential to send". */
8
+ exports.CALLER_AUTH_HEADERS = new Set([
9
+ 'authorization',
10
+ exports.INTERNAL_AUTH_TOKEN_HEADER,
11
+ ]);
12
+ /** Whether `headers` has one of `names` as a key, compared case-insensitively. */
13
+ const hasHeaderKey = (headers, names) => Object.keys(headers !== null && headers !== void 0 ? headers : {}).some((key) => names.has(key.toLowerCase()));
14
+ /**
15
+ * Axios request-interceptor rule for calls to internal services: adds the
16
+ * headers of `headersProvider` unless the request already carries an
17
+ * `authorization` or `x-internal-auth-token` header KEY, compared
18
+ * case-insensitively and whatever its value.
19
+ *
20
+ * Key presence, not value: a caller that forwards `authorization: sessionToken`
21
+ * with an undefined or empty token keeps sending no valid credential (the
22
+ * service answers 401) instead of silently getting the internal token.
23
+ * AxiosHeaders keeps keys whose value is undefined, so `Object.keys` sees them
24
+ * (`has()` would not). Headers the caller already set (e.g. `x-service-name`)
25
+ * are never overwritten. A rejection of `headersProvider` rejects the request
26
+ * before it is sent.
27
+ *
28
+ * Usage: `instance.interceptors.request.use((config) => applyInternalAuth(config, provider))`.
29
+ */
30
+ const applyInternalAuth = async (config, headersProvider) => {
31
+ if (hasHeaderKey(config.headers, exports.CALLER_AUTH_HEADERS))
32
+ return config;
33
+ const headers = axios_1.AxiosHeaders.from(config.headers);
34
+ for (const [name, value] of Object.entries(await headersProvider())) {
35
+ if (!hasHeaderKey(headers, new Set([name.toLowerCase()]))) {
36
+ headers.set(name, value);
37
+ }
38
+ }
39
+ config.headers = headers;
40
+ return config;
41
+ };
42
+ exports.applyInternalAuth = applyInternalAuth;
43
+ //# sourceMappingURL=internal-auth.rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal-auth.rule.js","sourceRoot":"","sources":["../src/internal-auth.rule.ts"],"names":[],"mappings":";;;AAAA,iCAAiE;AAEpD,QAAA,0BAA0B,GAAG,uBAAuB,CAAC;AACrD,QAAA,mBAAmB,GAAG,gBAAgB,CAAC;AAEpD,+EAA+E;AAClE,QAAA,mBAAmB,GAAwB,IAAI,GAAG,CAAC;IAC9D,eAAe;IACf,kCAA0B;CAC3B,CAAC,CAAC;AAQH,kFAAkF;AAClF,MAAM,YAAY,GAAG,CACnB,OAA2B,EAC3B,KAA0B,EACjB,EAAE,CACX,MAAM,CAAC,IAAI,CAAC,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;AAEzE;;;;;;;;;;;;;;;GAeG;AACI,MAAM,iBAAiB,GAAG,KAAK,EACpC,MAAkC,EAClC,eAAwC,EACH,EAAE;IACvC,IAAI,YAAY,CAAC,MAAM,CAAC,OAAO,EAAE,2BAAmB,CAAC;QAAE,OAAO,MAAM,CAAC;IAErE,MAAM,OAAO,GAAG,oBAAY,CAAC,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,eAAe,EAAE,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC;QAC3B,CAAC;IACH,CAAC;IACD,MAAM,CAAC,OAAO,GAAG,OAAO,CAAC;IACzB,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC;AAdW,QAAA,iBAAiB,qBAc5B"}
@@ -0,0 +1,16 @@
1
+ import { DynamicModule } from '@nestjs/common';
2
+ import { SharedKeyHttpModuleOptions } from './shared-key-http.options';
3
+ /**
4
+ * Provides `SharedKeyHttpService`. It needs `SharedKeyService`: either the app
5
+ * registers `SharedKeyModule.forRoot({ isGlobal: true })` once, or the module
6
+ * gets it through `register({ imports: [...] })`. It never registers
7
+ * `SharedKeyModule` itself, so the app keeps its choice of key backend
8
+ * (SSM / Secrets Manager) and options.
9
+ *
10
+ * - `imports: [SharedKeyHttpModule]`: default options, global `SharedKeyService`.
11
+ * - `imports: [SharedKeyHttpModule.register({ serviceName, imports, isGlobal })]`.
12
+ */
13
+ export declare class SharedKeyHttpModule {
14
+ static register(options?: SharedKeyHttpModuleOptions): DynamicModule;
15
+ }
16
+ //# sourceMappingURL=shared-key-http.module.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-key-http.module.d.ts","sourceRoot":"","sources":["../src/shared-key-http.module.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAoB,MAAM,gBAAgB,CAAC;AAEjE,OAAO,EAGL,0BAA0B,EAC3B,MAAM,2BAA2B,CAAC;AAanC;;;;;;;;;GASG;AACH,qBAIa,mBAAmB;IAC9B,MAAM,CAAC,QAAQ,CAAC,OAAO,GAAE,0BAA+B,GAAG,aAAa;CASzE"}
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ var SharedKeyHttpModule_1;
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ exports.SharedKeyHttpModule = void 0;
14
+ const common_1 = require("@nestjs/common");
15
+ const axios_1 = __importDefault(require("axios"));
16
+ const shared_key_http_options_1 = require("./shared-key-http.options");
17
+ const shared_key_http_service_1 = require("./shared-key-http.service");
18
+ const createProviders = (options) => [
19
+ { provide: shared_key_http_options_1.SHARED_KEY_HTTP_OPTIONS, useValue: options },
20
+ {
21
+ // Own instance: the auth interceptor never reaches the global axios.
22
+ provide: shared_key_http_options_1.SHARED_KEY_HTTP_AXIOS_INSTANCE,
23
+ useFactory: () => axios_1.default.create(options.axiosConfig),
24
+ },
25
+ shared_key_http_service_1.SharedKeyHttpService,
26
+ ];
27
+ /**
28
+ * Provides `SharedKeyHttpService`. It needs `SharedKeyService`: either the app
29
+ * registers `SharedKeyModule.forRoot({ isGlobal: true })` once, or the module
30
+ * gets it through `register({ imports: [...] })`. It never registers
31
+ * `SharedKeyModule` itself, so the app keeps its choice of key backend
32
+ * (SSM / Secrets Manager) and options.
33
+ *
34
+ * - `imports: [SharedKeyHttpModule]`: default options, global `SharedKeyService`.
35
+ * - `imports: [SharedKeyHttpModule.register({ serviceName, imports, isGlobal })]`.
36
+ */
37
+ let SharedKeyHttpModule = SharedKeyHttpModule_1 = class SharedKeyHttpModule {
38
+ static register(options = {}) {
39
+ var _a, _b;
40
+ return {
41
+ module: SharedKeyHttpModule_1,
42
+ global: (_a = options.isGlobal) !== null && _a !== void 0 ? _a : false,
43
+ imports: (_b = options.imports) !== null && _b !== void 0 ? _b : [],
44
+ providers: createProviders(options),
45
+ exports: [shared_key_http_service_1.SharedKeyHttpService],
46
+ };
47
+ }
48
+ };
49
+ exports.SharedKeyHttpModule = SharedKeyHttpModule;
50
+ exports.SharedKeyHttpModule = SharedKeyHttpModule = SharedKeyHttpModule_1 = __decorate([
51
+ (0, common_1.Module)({
52
+ providers: createProviders({}),
53
+ exports: [shared_key_http_service_1.SharedKeyHttpService],
54
+ })
55
+ ], SharedKeyHttpModule);
56
+ //# sourceMappingURL=shared-key-http.module.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-key-http.module.js","sourceRoot":"","sources":["../src/shared-key-http.module.ts"],"names":[],"mappings":";;;;;;;;;;;;;AAAA,2CAAiE;AACjE,kDAA0B;AAC1B,uEAImC;AACnC,uEAAiE;AAEjE,MAAM,eAAe,GAAG,CAAC,OAAmC,EAAc,EAAE,CAAC;IAC3E,EAAE,OAAO,EAAE,iDAAuB,EAAE,QAAQ,EAAE,OAAO,EAAE;IACvD;QACE,qEAAqE;QACrE,OAAO,EAAE,wDAA8B;QACvC,UAAU,EAAE,GAAG,EAAE,CAAC,eAAK,CAAC,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC;KACpD;IACD,8CAAoB;CACrB,CAAC;AAEF;;;;;;;;;GASG;AAKI,IAAM,mBAAmB,2BAAzB,MAAM,mBAAmB;IAC9B,MAAM,CAAC,QAAQ,CAAC,UAAsC,EAAE;;QACtD,OAAO;YACL,MAAM,EAAE,qBAAmB;YAC3B,MAAM,EAAE,MAAA,OAAO,CAAC,QAAQ,mCAAI,KAAK;YACjC,OAAO,EAAE,MAAA,OAAO,CAAC,OAAO,mCAAI,EAAE;YAC9B,SAAS,EAAE,eAAe,CAAC,OAAO,CAAC;YACnC,OAAO,EAAE,CAAC,8CAAoB,CAAC;SAChC,CAAC;IACJ,CAAC;CACF,CAAA;AAVY,kDAAmB;8BAAnB,mBAAmB;IAJ/B,IAAA,eAAM,EAAC;QACN,SAAS,EAAE,eAAe,CAAC,EAAE,CAAC;QAC9B,OAAO,EAAE,CAAC,8CAAoB,CAAC;KAChC,CAAC;GACW,mBAAmB,CAU/B"}
@@ -0,0 +1,22 @@
1
+ import { ModuleMetadata } from '@nestjs/common';
2
+ import { CreateAxiosDefaults } from 'axios';
3
+ export declare const SHARED_KEY_HTTP_OPTIONS: unique symbol;
4
+ export declare const SHARED_KEY_HTTP_AXIOS_INSTANCE: unique symbol;
5
+ export declare const DEFAULT_SERVICE_NAME = "unknown-service";
6
+ export type SharedKeyHttpModuleOptions = {
7
+ /** `x-service-name` sent with the internal token. Default: `defaultServiceName()`. */
8
+ serviceName?: string;
9
+ /** Defaults of the module's own axios instance (e.g. `timeout`). */
10
+ axiosConfig?: CreateAxiosDefaults;
11
+ /**
12
+ * Modules that provide `SharedKeyService`, e.g. `[SharedKeyModule]`. Leave it
13
+ * empty when the app registers `SharedKeyModule.forRoot({ isGlobal: true })`
14
+ * (or `SharedSecretModule`) once at the root.
15
+ */
16
+ imports?: ModuleMetadata['imports'];
17
+ /** Registers the module globally. Default: false. */
18
+ isGlobal?: boolean;
19
+ };
20
+ /** `${APP_ENV}-${npm_package_name}`, the package name alone without APP_ENV, else `unknown-service`. */
21
+ export declare const defaultServiceName: (env?: NodeJS.ProcessEnv) => string;
22
+ //# sourceMappingURL=shared-key-http.options.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-key-http.options.d.ts","sourceRoot":"","sources":["../src/shared-key-http.options.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,EAAE,mBAAmB,EAAE,MAAM,OAAO,CAAC;AAE5C,eAAO,MAAM,uBAAuB,eAAoC,CAAC;AACzE,eAAO,MAAM,8BAA8B,eAE1C,CAAC;AACF,eAAO,MAAM,oBAAoB,oBAAoB,CAAC;AAEtD,MAAM,MAAM,0BAA0B,GAAG;IACvC,sFAAsF;IACtF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oEAAoE;IACpE,WAAW,CAAC,EAAE,mBAAmB,CAAC;IAClC;;;;OAIG;IACH,OAAO,CAAC,EAAE,cAAc,CAAC,SAAS,CAAC,CAAC;IACpC,qDAAqD;IACrD,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAEF,wGAAwG;AACxG,eAAO,MAAM,kBAAkB,GAC7B,MAAK,MAAM,CAAC,UAAwB,KACnC,MAIF,CAAC"}
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.defaultServiceName = exports.DEFAULT_SERVICE_NAME = exports.SHARED_KEY_HTTP_AXIOS_INSTANCE = exports.SHARED_KEY_HTTP_OPTIONS = void 0;
4
+ exports.SHARED_KEY_HTTP_OPTIONS = Symbol('SHARED_KEY_HTTP_OPTIONS');
5
+ exports.SHARED_KEY_HTTP_AXIOS_INSTANCE = Symbol('SHARED_KEY_HTTP_AXIOS_INSTANCE');
6
+ exports.DEFAULT_SERVICE_NAME = 'unknown-service';
7
+ /** `${APP_ENV}-${npm_package_name}`, the package name alone without APP_ENV, else `unknown-service`. */
8
+ const defaultServiceName = (env = process.env) => {
9
+ const packageName = env.npm_package_name;
10
+ if (!packageName)
11
+ return exports.DEFAULT_SERVICE_NAME;
12
+ return env.APP_ENV ? `${env.APP_ENV}-${packageName}` : packageName;
13
+ };
14
+ exports.defaultServiceName = defaultServiceName;
15
+ //# sourceMappingURL=shared-key-http.options.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-key-http.options.js","sourceRoot":"","sources":["../src/shared-key-http.options.ts"],"names":[],"mappings":";;;AAGa,QAAA,uBAAuB,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;AAC5D,QAAA,8BAA8B,GAAG,MAAM,CAClD,gCAAgC,CACjC,CAAC;AACW,QAAA,oBAAoB,GAAG,iBAAiB,CAAC;AAiBtD,wGAAwG;AACjG,MAAM,kBAAkB,GAAG,CAChC,MAAyB,OAAO,CAAC,GAAG,EAC5B,EAAE;IACV,MAAM,WAAW,GAAG,GAAG,CAAC,gBAAgB,CAAC;IACzC,IAAI,CAAC,WAAW;QAAE,OAAO,4BAAoB,CAAC;IAC9C,OAAO,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,GAAG,CAAC,OAAO,IAAI,WAAW,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC;AACrE,CAAC,CAAC;AANW,QAAA,kBAAkB,sBAM7B"}
@@ -0,0 +1,41 @@
1
+ import { HttpService } from '@nestjs/axios';
2
+ import { SharedKeyService } from '@origins-digital/nestjs-shared-key';
3
+ import { AxiosInstance, AxiosRequestConfig, AxiosResponse } from 'axios';
4
+ import { InternalAuthHeaders } from './internal-auth.rule';
5
+ import { SharedKeyHttpModuleOptions } from './shared-key-http.options';
6
+ export declare const DEFAULT_REQUESTED_SERVICE = "shared-key-http-service";
7
+ /** Axios config plus the service label used in the errors of `*AsPromise`. */
8
+ export type SharedKeyHttpRequestConfig<D = unknown> = AxiosRequestConfig<D> & {
9
+ requestedService?: string;
10
+ };
11
+ /**
12
+ * `HttpService` for calls to internal Origins services: `applyInternalAuth`
13
+ * adds `x-internal-auth-token` and `x-service-name` unless the caller set an
14
+ * `authorization` or `x-internal-auth-token` header key.
15
+ *
16
+ * It runs on the module's own axios instance, never the global axios, so a
17
+ * plain `HttpModule` (calls to external hosts) is left untouched.
18
+ */
19
+ export declare class SharedKeyHttpService extends HttpService {
20
+ private readonly sharedKeyService;
21
+ private readonly serviceName;
22
+ constructor(axiosInstance: AxiosInstance, sharedKeyService: SharedKeyService, options: SharedKeyHttpModuleOptions);
23
+ /**
24
+ * Internal auth headers, also usable as the headers provider of other clients
25
+ * (`() => sharedKeyHttp.internalHeaders()`). Rejects when no token resolves.
26
+ */
27
+ internalHeaders(): Promise<InternalAuthHeaders>;
28
+ getAsPromise<T = unknown, D = unknown>(url: string, config?: SharedKeyHttpRequestConfig<D>): Promise<AxiosResponse<T, D>>;
29
+ deleteAsPromise<T = unknown, D = unknown>(url: string, config?: SharedKeyHttpRequestConfig<D>): Promise<AxiosResponse<T, D>>;
30
+ headAsPromise<T = unknown, D = unknown>(url: string, config?: SharedKeyHttpRequestConfig<D>): Promise<AxiosResponse<T, D>>;
31
+ postAsPromise<T = unknown, D = unknown>(url: string, data?: D, config?: SharedKeyHttpRequestConfig<D>): Promise<AxiosResponse<T, D>>;
32
+ putAsPromise<T = unknown, D = unknown>(url: string, data?: D, config?: SharedKeyHttpRequestConfig<D>): Promise<AxiosResponse<T, D>>;
33
+ patchAsPromise<T = unknown, D = unknown>(url: string, data?: D, config?: SharedKeyHttpRequestConfig<D>): Promise<AxiosResponse<T, D>>;
34
+ private resolveConfig;
35
+ /**
36
+ * HTTP errors become the Nest exception `raiseError` builds, labelled with
37
+ * `requestedService`; other errors (e.g. from the auth rule) pass through.
38
+ */
39
+ private toPromise;
40
+ }
41
+ //# sourceMappingURL=shared-key-http.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-key-http.service.d.ts","sourceRoot":"","sources":["../src/shared-key-http.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAQ5C,OAAO,EAEL,gBAAgB,EACjB,MAAM,oCAAoC,CAAC;AAC5C,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,aAAa,EAEd,MAAM,OAAO,CAAC;AAEf,OAAO,EAGL,mBAAmB,EAEpB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAIL,0BAA0B,EAC3B,MAAM,2BAA2B,CAAC;AAEnC,eAAO,MAAM,yBAAyB,4BAA4B,CAAC;AAEnE,8EAA8E;AAC9E,MAAM,MAAM,0BAA0B,CAAC,CAAC,GAAG,OAAO,IAAI,kBAAkB,CAAC,CAAC,CAAC,GAAG;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B,CAAC;AAEF;;;;;;;GAOG;AACH,qBACa,oBAAqB,SAAQ,WAAW;IAKjD,OAAO,CAAC,QAAQ,CAAC,gBAAgB;IAJnC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;gBAGK,aAAa,EAAE,aAAa,EACnD,gBAAgB,EAAE,gBAAgB,EAClB,OAAO,EAAE,0BAA0B;IAStE;;;OAGG;IACG,eAAe,IAAI,OAAO,CAAC,mBAAmB,CAAC;IAerD,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACnC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,0BAA0B,CAAC,CAAC,CAAC,GACrC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAK/B,eAAe,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACtC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,0BAA0B,CAAC,CAAC,CAAC,GACrC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAK/B,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACpC,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,0BAA0B,CAAC,CAAC,CAAC,GACrC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAK/B,aAAa,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACpC,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,CAAC,EACR,MAAM,CAAC,EAAE,0BAA0B,CAAC,CAAC,CAAC,GACrC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAQ/B,YAAY,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACnC,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,CAAC,EACR,MAAM,CAAC,EAAE,0BAA0B,CAAC,CAAC,CAAC,GACrC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAQ/B,cAAc,CAAC,CAAC,GAAG,OAAO,EAAE,CAAC,GAAG,OAAO,EACrC,GAAG,EAAE,MAAM,EACX,IAAI,CAAC,EAAE,CAAC,EACR,MAAM,CAAC,EAAE,0BAA0B,CAAC,CAAC,CAAC,GACrC,OAAO,CAAC,aAAa,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAQ/B,OAAO,CAAC,aAAa;IAerB;;;OAGG;IACH,OAAO,CAAC,SAAS;CAalB"}
@@ -0,0 +1,120 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var __rest = (this && this.__rest) || function (s, e) {
15
+ var t = {};
16
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
17
+ t[p] = s[p];
18
+ if (s != null && typeof Object.getOwnPropertySymbols === "function")
19
+ for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
20
+ if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
21
+ t[p[i]] = s[p[i]];
22
+ }
23
+ return t;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.SharedKeyHttpService = exports.DEFAULT_REQUESTED_SERVICE = void 0;
27
+ const axios_1 = require("@nestjs/axios");
28
+ const common_1 = require("@nestjs/common");
29
+ const cacheable_1 = require("@origins-digital/cacheable");
30
+ const error_utils_1 = require("@origins-digital/error-utils");
31
+ const nestjs_shared_key_1 = require("@origins-digital/nestjs-shared-key");
32
+ const axios_2 = require("axios");
33
+ const rxjs_1 = require("rxjs");
34
+ const internal_auth_rule_1 = require("./internal-auth.rule");
35
+ const shared_key_http_options_1 = require("./shared-key-http.options");
36
+ exports.DEFAULT_REQUESTED_SERVICE = 'shared-key-http-service';
37
+ /**
38
+ * `HttpService` for calls to internal Origins services: `applyInternalAuth`
39
+ * adds `x-internal-auth-token` and `x-service-name` unless the caller set an
40
+ * `authorization` or `x-internal-auth-token` header key.
41
+ *
42
+ * It runs on the module's own axios instance, never the global axios, so a
43
+ * plain `HttpModule` (calls to external hosts) is left untouched.
44
+ */
45
+ let SharedKeyHttpService = class SharedKeyHttpService extends axios_1.HttpService {
46
+ constructor(axiosInstance, sharedKeyService, options) {
47
+ var _a;
48
+ super(axiosInstance);
49
+ this.sharedKeyService = sharedKeyService;
50
+ this.serviceName = (_a = options.serviceName) !== null && _a !== void 0 ? _a : (0, shared_key_http_options_1.defaultServiceName)();
51
+ axiosInstance.interceptors.request.use((config) => (0, internal_auth_rule_1.applyInternalAuth)(config, () => this.internalHeaders()));
52
+ }
53
+ /**
54
+ * Internal auth headers, also usable as the headers provider of other clients
55
+ * (`() => sharedKeyHttp.internalHeaders()`). Rejects when no token resolves.
56
+ */
57
+ async internalHeaders() {
58
+ const jwtAccessToken = cacheable_1.GenericOutput.data(await this.sharedKeyService.getInternalAuthJWT());
59
+ if (!(jwtAccessToken === null || jwtAccessToken === void 0 ? void 0 : jwtAccessToken.key)) {
60
+ throw new common_1.InternalServerErrorException('Could not resolve the internal shared key token');
61
+ }
62
+ return {
63
+ [internal_auth_rule_1.INTERNAL_AUTH_TOKEN_HEADER]: jwtAccessToken.key,
64
+ [internal_auth_rule_1.SERVICE_NAME_HEADER]: this.serviceName,
65
+ };
66
+ }
67
+ getAsPromise(url, config) {
68
+ const { requestedService, axiosConfig } = this.resolveConfig(config);
69
+ return this.toPromise(this.get(url, axiosConfig), requestedService);
70
+ }
71
+ deleteAsPromise(url, config) {
72
+ const { requestedService, axiosConfig } = this.resolveConfig(config);
73
+ return this.toPromise(this.delete(url, axiosConfig), requestedService);
74
+ }
75
+ headAsPromise(url, config) {
76
+ const { requestedService, axiosConfig } = this.resolveConfig(config);
77
+ return this.toPromise(this.head(url, axiosConfig), requestedService);
78
+ }
79
+ postAsPromise(url, data, config) {
80
+ const { requestedService, axiosConfig } = this.resolveConfig(config);
81
+ return this.toPromise(this.post(url, data, axiosConfig), requestedService);
82
+ }
83
+ putAsPromise(url, data, config) {
84
+ const { requestedService, axiosConfig } = this.resolveConfig(config);
85
+ return this.toPromise(this.put(url, data, axiosConfig), requestedService);
86
+ }
87
+ patchAsPromise(url, data, config) {
88
+ const { requestedService, axiosConfig } = this.resolveConfig(config);
89
+ return this.toPromise(this.patch(url, data, axiosConfig), requestedService);
90
+ }
91
+ resolveConfig(config) {
92
+ if (!config) {
93
+ return {
94
+ requestedService: exports.DEFAULT_REQUESTED_SERVICE,
95
+ axiosConfig: undefined,
96
+ };
97
+ }
98
+ const { requestedService = exports.DEFAULT_REQUESTED_SERVICE } = config, axiosConfig = __rest(config, ["requestedService"]);
99
+ return { requestedService, axiosConfig };
100
+ }
101
+ /**
102
+ * HTTP errors become the Nest exception `raiseError` builds, labelled with
103
+ * `requestedService`; other errors (e.g. from the auth rule) pass through.
104
+ */
105
+ toPromise(request$, requestedService) {
106
+ return (0, rxjs_1.firstValueFrom)(request$.pipe((0, rxjs_1.catchError)((error) => {
107
+ if ((0, axios_2.isAxiosError)(error))
108
+ (0, error_utils_1.raiseError)(error, { requestedService });
109
+ throw error;
110
+ })));
111
+ }
112
+ };
113
+ exports.SharedKeyHttpService = SharedKeyHttpService;
114
+ exports.SharedKeyHttpService = SharedKeyHttpService = __decorate([
115
+ (0, common_1.Injectable)(),
116
+ __param(0, (0, common_1.Inject)(shared_key_http_options_1.SHARED_KEY_HTTP_AXIOS_INSTANCE)),
117
+ __param(2, (0, common_1.Inject)(shared_key_http_options_1.SHARED_KEY_HTTP_OPTIONS)),
118
+ __metadata("design:paramtypes", [Function, nestjs_shared_key_1.SharedKeyService, Object])
119
+ ], SharedKeyHttpService);
120
+ //# sourceMappingURL=shared-key-http.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"shared-key-http.service.js","sourceRoot":"","sources":["../src/shared-key-http.service.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,102 @@
1
1
  {
2
2
  "name": "@origins-digital/nestjs-shared-key-http",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.1",
4
+ "description": "NestJS HttpService that adds the internal shared-key auth headers to calls between Origins services",
5
+ "main": "./dist/index.js",
6
+ "module": "./dist/index.d.ts",
7
+ "types": "./dist/index.d.ts",
8
+ "author": "Origins Digital (https://www.origins-digital.com/)",
9
+ "license": "MIT",
10
+ "exports": {
11
+ ".": "./dist/index.js"
12
+ },
13
+ "files": [
14
+ "dist"
15
+ ],
16
+ "scripts": {
17
+ "format": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"",
18
+ "lint": "eslint \"src/**/*.ts\"",
19
+ "lint:fix": "eslint \"src/**/*.ts\" --fix",
20
+ "test": "jest --passWithNoTests",
21
+ "test:watch": "jest --watch",
22
+ "test:cov": "jest --coverage",
23
+ "test:debug": "node --inspect-brk -r tsconfig-paths/register -r ts-node/register node_modules/.bin/jest --runInBand",
24
+ "build": "rimraf dist && tsc -p tsconfig.build.json",
25
+ "release:patch": "release-it patch --ci",
26
+ "release:minor": "release-it minor --ci",
27
+ "release:major": "release-it major --ci",
28
+ "commit": "git-cz",
29
+ "prepublish": "yarn build"
30
+ },
31
+ "dependencies": {
32
+ "@origins-digital/cacheable": "3.4.0",
33
+ "@origins-digital/error-utils": "2.1.4"
34
+ },
35
+ "peerDependencies": {
36
+ "@nestjs/axios": ">=4.0.1",
37
+ "@nestjs/common": ">=11.0.0",
38
+ "@origins-digital/nestjs-shared-key": ">=3.2.1",
39
+ "axios": ">=1.4.0",
40
+ "rxjs": ">=7.1.0"
41
+ },
42
+ "devDependencies": {
43
+ "@commitlint/cli": "^17.6.6",
44
+ "@commitlint/config-conventional": "^17.6.6",
45
+ "@nestjs/testing": "^11.1.11",
46
+ "@types/node": "^20.3.1",
47
+ "commitizen": "^4.3.0",
48
+ "conventional-recommended-bump": "^11.2.0",
49
+ "cz-conventional-changelog": "^3.3.0",
50
+ "eslint": "^9.0.0",
51
+ "eslint-config-prettier": "^9.0.0",
52
+ "eslint-plugin-prettier": "^5.0.0",
53
+ "jest": "^29.5.0",
54
+ "prettier": "^3.0.0",
55
+ "rimraf": "^5.0.5",
56
+ "ts-jest": "^29.1.0",
57
+ "ts-node": "^10.9.1",
58
+ "tsconfig-paths": "^4.2.0",
59
+ "typescript": "^5.3.2"
60
+ },
61
+ "jest": {
62
+ "moduleFileExtensions": [
63
+ "js",
64
+ "json",
65
+ "ts"
66
+ ],
67
+ "rootDir": "src",
68
+ "testRegex": ".*\\.spec\\.ts$",
69
+ "transform": {
70
+ "^.+\\.ts$": "ts-jest"
71
+ },
72
+ "collectCoverageFrom": [
73
+ "**/*.(t|j)s"
74
+ ],
75
+ "coverageDirectory": "../coverage",
76
+ "testEnvironment": "node"
77
+ },
78
+ "publishConfig": {
79
+ "registry": "https://registry.npmjs.org",
80
+ "access": "public"
81
+ },
82
+ "release-it": {
83
+ "git": {
84
+ "requireCleanWorkingDir": false,
85
+ "commitMessage": "chore(release): bump nestjs-shared-key-http ${version}",
86
+ "tagName": "${npm.name}-v${version}",
87
+ "tagAnnotation": "nestjs-shared-key-http-${version}",
88
+ "push": false,
89
+ "commit": true,
90
+ "addUntrackedFiles": false
91
+ },
92
+ "npm": {
93
+ "publish": true
94
+ },
95
+ "hooks": {
96
+ "before:init": [
97
+ "yarn test",
98
+ "yarn build"
99
+ ]
100
+ }
101
+ }
102
+ }