@hawcx/oauth-client 5.2.0 → 6.2.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 (69) hide show
  1. package/CHANGELOG.md +355 -0
  2. package/README.md +247 -0
  3. package/dist/client-assertion.d.ts.map +1 -1
  4. package/dist/client-assertion.js +6 -2
  5. package/dist/client-assertion.js.map +1 -1
  6. package/dist/delegation/exceptions.d.ts +34 -0
  7. package/dist/delegation/exceptions.d.ts.map +1 -1
  8. package/dist/delegation/exceptions.js +39 -1
  9. package/dist/delegation/exceptions.js.map +1 -1
  10. package/dist/delegation/hawcx.d.ts +6 -2
  11. package/dist/delegation/hawcx.d.ts.map +1 -1
  12. package/dist/delegation/hawcx.js.map +1 -1
  13. package/dist/delegation/index.d.ts +2 -1
  14. package/dist/delegation/index.d.ts.map +1 -1
  15. package/dist/delegation/index.js +3 -1
  16. package/dist/delegation/index.js.map +1 -1
  17. package/dist/delegation/transport.d.ts +6 -2
  18. package/dist/delegation/transport.d.ts.map +1 -1
  19. package/dist/delegation/transport.js +9 -2
  20. package/dist/delegation/transport.js.map +1 -1
  21. package/dist/errors.d.ts +11 -1
  22. package/dist/errors.d.ts.map +1 -1
  23. package/dist/errors.js +1 -0
  24. package/dist/errors.js.map +1 -1
  25. package/dist/index.d.ts +6 -2
  26. package/dist/index.d.ts.map +1 -1
  27. package/dist/index.js +8 -2
  28. package/dist/index.js.map +1 -1
  29. package/dist/internal/url.d.ts +73 -0
  30. package/dist/internal/url.d.ts.map +1 -0
  31. package/dist/internal/url.js +210 -0
  32. package/dist/internal/url.js.map +1 -0
  33. package/dist/management/jwt_transport.d.ts +44 -3
  34. package/dist/management/jwt_transport.d.ts.map +1 -1
  35. package/dist/management/jwt_transport.js +60 -4
  36. package/dist/management/jwt_transport.js.map +1 -1
  37. package/dist/management/response_signature.d.ts +65 -0
  38. package/dist/management/response_signature.d.ts.map +1 -0
  39. package/dist/management/response_signature.js +170 -0
  40. package/dist/management/response_signature.js.map +1 -0
  41. package/dist/oauth.d.ts +89 -1
  42. package/dist/oauth.d.ts.map +1 -1
  43. package/dist/oauth.js +265 -34
  44. package/dist/oauth.js.map +1 -1
  45. package/dist/profile/client.d.ts +99 -0
  46. package/dist/profile/client.d.ts.map +1 -0
  47. package/dist/profile/client.js +209 -0
  48. package/dist/profile/client.js.map +1 -0
  49. package/dist/profile/errors.d.ts +62 -0
  50. package/dist/profile/errors.d.ts.map +1 -0
  51. package/dist/profile/errors.js +90 -0
  52. package/dist/profile/errors.js.map +1 -0
  53. package/dist/profile/http.d.ts +57 -0
  54. package/dist/profile/http.d.ts.map +1 -0
  55. package/dist/profile/http.js +295 -0
  56. package/dist/profile/http.js.map +1 -0
  57. package/dist/profile/tokens.d.ts +50 -0
  58. package/dist/profile/tokens.d.ts.map +1 -0
  59. package/dist/profile/tokens.js +137 -0
  60. package/dist/profile/tokens.js.map +1 -0
  61. package/dist/profile/types.d.ts +99 -0
  62. package/dist/profile/types.d.ts.map +1 -0
  63. package/dist/profile/types.js +7 -0
  64. package/dist/profile/types.js.map +1 -0
  65. package/dist/stepup/client.d.ts +11 -0
  66. package/dist/stepup/client.d.ts.map +1 -1
  67. package/dist/stepup/client.js +6 -1
  68. package/dist/stepup/client.js.map +1 -1
  69. package/package.json +1 -1
@@ -0,0 +1,209 @@
1
+ "use strict";
2
+ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, state, value, kind, f) {
3
+ if (kind === "m") throw new TypeError("Private method is not writable");
4
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
5
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
6
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
7
+ };
8
+ var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
9
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
10
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
11
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
12
+ };
13
+ var _ProfileClient_http, _ProfileClient_forUser, _UserProfileClient_http;
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.UserProfileClient = exports.ProfileClient = void 0;
16
+ /**
17
+ * Hawcx profile service client.
18
+ *
19
+ * - {@link ProfileClient} acts as the backend itself (`client_credentials`,
20
+ * `private_key_jwt`) and manages any user in the tenant.
21
+ * - {@link UserProfileClient} (from {@link ProfileClient.forUser}) acts for one
22
+ * signed-in user via an RFC 8693 exchange of their ID token (`profile:self`).
23
+ *
24
+ * Backend only: the OP refuses both grants to public clients.
25
+ */
26
+ const errors_1 = require("../errors");
27
+ const url_1 = require("../internal/url");
28
+ const http_1 = require("./http");
29
+ const tokens_1 = require("./tokens");
30
+ const toPage = (r) => ({
31
+ items: r.items,
32
+ nextCursor: r.next_cursor ?? null,
33
+ });
34
+ const isPage = (d) => (0, http_1.isObject)(d) && Array.isArray(d.items);
35
+ const isConsents = (d) => (0, http_1.isObject)(d) && (0, http_1.isObject)(d.current) && Array.isArray(d.history);
36
+ const userPath = (userId) => ['v1', 'users', (0, http_1.segment)(userId, 'userId')];
37
+ const pageQuery = (p = {}) => ({ limit: p.limit, cursor: p.cursor });
38
+ /**
39
+ * Yield every item across pages. Stops (without error) if the server hands
40
+ * back a cursor it already returned, so a server bug can't loop forever.
41
+ */
42
+ async function* paginate(fetchPage) {
43
+ const seen = new Set();
44
+ let cursor;
45
+ for (;;) {
46
+ const page = await fetchPage(cursor);
47
+ yield* page.items;
48
+ // null, missing or "" ends it.
49
+ if (!page.nextCursor || seen.has(page.nextCursor))
50
+ return;
51
+ seen.add(page.nextCursor);
52
+ cursor = page.nextCursor;
53
+ }
54
+ }
55
+ /** Consent + audit calls, shared by the machine (`users/{id}`) and delegated (`me`) clients. */
56
+ async function consents(http, prefix, page) {
57
+ const r = await http.request('GET', [...prefix, 'consents'], { query: pageQuery(page), valid: isConsents });
58
+ return { current: r.current, history: r.history, nextCursor: r.next_cursor ?? null };
59
+ }
60
+ const setConsent = (http, prefix, purpose, input) => http.request('PUT', [...prefix, 'consents', (0, http_1.segment)(purpose, 'purpose')], {
61
+ body: input,
62
+ });
63
+ const audit = async (http, prefix, page) => toPage(await http.request('GET', [...prefix, 'audit'], {
64
+ query: pageQuery(page),
65
+ valid: isPage,
66
+ }));
67
+ /** Machine client: manage any user's profile, consents and audit trail in the tenant. */
68
+ class ProfileClient {
69
+ /**
70
+ * @param oauth - a discovery-mode client with a signer:
71
+ * `(await HawcxOAuth.fromIssuer(...)).withClientAssertion(signer)`.
72
+ */
73
+ constructor(oauth, options = {}) {
74
+ _ProfileClient_http.set(this, void 0);
75
+ _ProfileClient_forUser.set(this, void 0);
76
+ const ctx = oauth.profileContext();
77
+ if (ctx === null) {
78
+ throw new errors_1.HawcxError('ProfileClient requires a discovery-mode HawcxOAuth with a client assertion signer: ' +
79
+ '(await HawcxOAuth.fromIssuer({...})).withClientAssertion(signer)');
80
+ }
81
+ const base = (0, url_1.parseSecureBaseUrl)('baseUrl', options.baseUrl ?? `${ctx.issuer.replace(/\/+$/, '')}/profile`, message => new errors_1.HawcxError(message));
82
+ const timeout = options.timeout ?? 10000;
83
+ const http = (tokens, surface401 = false) => new http_1.ProfileHttp({
84
+ baseUrl: base.origin + base.pathPrefix,
85
+ configId: ctx.configId,
86
+ tokens,
87
+ fetch: options.fetch,
88
+ timeout,
89
+ maxRetries: options.maxRetries,
90
+ sleep: options.sleep,
91
+ surface401,
92
+ });
93
+ const tokenOpts = { fetch: options.fetch, timeout, now: options.now };
94
+ __classPrivateFieldSet(this, _ProfileClient_http, http((0, tokens_1.machineTokenSource)(oauth, { ...tokenOpts, scopes: options.scopes })), "f");
95
+ __classPrivateFieldSet(this, _ProfileClient_forUser, idToken => http((0, tokens_1.exchangeTokenSource)(oauth, idToken, { ...tokenOpts, audience: options.audience }), true), "f");
96
+ }
97
+ /**
98
+ * A client acting for the user whose ID token this is (its `aud` must be
99
+ * this same client). Exchanges lazily on first call and caches the token for
100
+ * its own lifetime. The OP caps that lifetime at the ID token's `exp` (60 s
101
+ * by default), so use it with the ID token you just received at sign-in; for
102
+ * later work on a user's profile use the machine methods with their
103
+ * `user_id` (the `sub` claim).
104
+ */
105
+ forUser(idToken) {
106
+ if (typeof idToken !== 'string' || idToken === '')
107
+ throw new errors_1.HawcxError('idToken is required');
108
+ return UserProfileClient.create(__classPrivateFieldGet(this, _ProfileClient_forUser, "f").call(this, idToken));
109
+ }
110
+ /** `GET /v1/users/{userId}` [users:read] */
111
+ async getUser(userId) {
112
+ return __classPrivateFieldGet(this, _ProfileClient_http, "f").request('GET', userPath(userId));
113
+ }
114
+ /** `GET /v1/users` [users:read] */
115
+ async listUsers(options = {}) {
116
+ const { limit, email, status, cursor } = options;
117
+ return toPage(await __classPrivateFieldGet(this, _ProfileClient_http, "f").request('GET', ['v1', 'users'], {
118
+ query: { limit, email, status, cursor },
119
+ valid: isPage,
120
+ }));
121
+ }
122
+ /** Every user matching the filters, following `next_cursor`. */
123
+ iterUsers(options = {}) {
124
+ return paginate(cursor => this.listUsers({ ...options, cursor }));
125
+ }
126
+ /**
127
+ * `POST /v1/users` [users:write]; 404 if the identity doesn't exist, 409 if
128
+ * the profile does. `user_id` must pass the same path-segment rules as
129
+ * `userId` elsewhere. Retried only on a transient token-endpoint failure.
130
+ */
131
+ async createUser(input) {
132
+ // Never create a record the other methods can't address.
133
+ (0, http_1.segment)(input?.user_id, 'user_id');
134
+ return __classPrivateFieldGet(this, _ProfileClient_http, "f").request('POST', ['v1', 'users'], { body: input });
135
+ }
136
+ /** `PATCH /v1/users/{userId}` [users:write]: `null` clears a field, an omitted key is unchanged. Retried only on a transient token-endpoint failure. */
137
+ async updateUser(userId, patch) {
138
+ return __classPrivateFieldGet(this, _ProfileClient_http, "f").request('PATCH', userPath(userId), { body: patch });
139
+ }
140
+ /** `PUT /v1/users/{userId}` [users:write] */
141
+ async replaceUser(userId, input) {
142
+ return __classPrivateFieldGet(this, _ProfileClient_http, "f").request('PUT', userPath(userId), { body: input });
143
+ }
144
+ /** `DELETE /v1/users/{userId}` [users:delete] */
145
+ async deleteUser(userId) {
146
+ await __classPrivateFieldGet(this, _ProfileClient_http, "f").request('DELETE', userPath(userId));
147
+ }
148
+ /** `GET /v1/users/{userId}/consents` [consent:read] */
149
+ async getConsents(userId, page) {
150
+ return consents(__classPrivateFieldGet(this, _ProfileClient_http, "f"), userPath(userId), page);
151
+ }
152
+ /** `PUT /v1/users/{userId}/consents/{purpose}` [consent:write]; 422 for an unknown purpose. */
153
+ async setConsent(userId, purpose, input) {
154
+ return setConsent(__classPrivateFieldGet(this, _ProfileClient_http, "f"), userPath(userId), purpose, input);
155
+ }
156
+ /** `GET /v1/users/{userId}/audit` [audit:read] */
157
+ async getAudit(userId, page) {
158
+ return audit(__classPrivateFieldGet(this, _ProfileClient_http, "f"), userPath(userId), page);
159
+ }
160
+ /** The user's whole audit trail, following `next_cursor`. */
161
+ iterAudit(userId, options = {}) {
162
+ return paginate(cursor => this.getAudit(userId, { limit: options.limit, cursor }));
163
+ }
164
+ }
165
+ exports.ProfileClient = ProfileClient;
166
+ _ProfileClient_http = new WeakMap(), _ProfileClient_forUser = new WeakMap();
167
+ /** Delegated client (`profile:self`): the signed-in user's own profile, consents and audit. */
168
+ class UserProfileClient {
169
+ /** Not constructible directly: use {@link ProfileClient.forUser}. */
170
+ constructor(http) {
171
+ _UserProfileClient_http.set(this, void 0);
172
+ // Runtime guard for plain-JS callers; TypeScript already refuses `new`.
173
+ if (!(http instanceof http_1.ProfileHttp)) {
174
+ throw new errors_1.HawcxError('UserProfileClient is created with ProfileClient.forUser(idToken)');
175
+ }
176
+ __classPrivateFieldSet(this, _UserProfileClient_http, http, "f");
177
+ }
178
+ /** @internal */
179
+ static create(http) {
180
+ return new UserProfileClient(http);
181
+ }
182
+ /** `GET /v1/me` */
183
+ async getMe() {
184
+ return __classPrivateFieldGet(this, _UserProfileClient_http, "f").request('GET', ['v1', 'me']);
185
+ }
186
+ /** `PATCH /v1/me`: `null` clears a field, an omitted key is unchanged. Retried only on a transient token-endpoint failure. */
187
+ async updateMe(patch) {
188
+ return __classPrivateFieldGet(this, _UserProfileClient_http, "f").request('PATCH', ['v1', 'me'], { body: patch });
189
+ }
190
+ /** `GET /v1/me/consents` */
191
+ async getMyConsents(page) {
192
+ return consents(__classPrivateFieldGet(this, _UserProfileClient_http, "f"), ['v1', 'me'], page);
193
+ }
194
+ /** `PUT /v1/me/consents/{purpose}` */
195
+ async setMyConsent(purpose, input) {
196
+ return setConsent(__classPrivateFieldGet(this, _UserProfileClient_http, "f"), ['v1', 'me'], purpose, input);
197
+ }
198
+ /** `GET /v1/me/audit` */
199
+ async getMyAudit(page) {
200
+ return audit(__classPrivateFieldGet(this, _UserProfileClient_http, "f"), ['v1', 'me'], page);
201
+ }
202
+ /** The user's whole audit trail, following `next_cursor`. */
203
+ iterMyAudit(options = {}) {
204
+ return paginate(cursor => this.getMyAudit({ limit: options.limit, cursor }));
205
+ }
206
+ }
207
+ exports.UserProfileClient = UserProfileClient;
208
+ _UserProfileClient_http = new WeakMap();
209
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/profile/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ /**
2
+ * Profile service errors (RFC 9457 `application/problem+json`).
3
+ */
4
+ import { HawcxError } from '../errors';
5
+ export interface ProfileApiErrorInit {
6
+ /**
7
+ * HTTP status; `0` for a network failure or timeout (no response). A 2xx
8
+ * whose body could not be read keeps its status (the call ran).
9
+ */
10
+ status: number;
11
+ title?: string | null;
12
+ detail?: string | null;
13
+ type?: string | null;
14
+ instance?: string | null;
15
+ requestId?: string | null;
16
+ retryAfter?: number | null;
17
+ missing?: string[] | null;
18
+ fields?: string[] | null;
19
+ body?: Record<string, unknown> | null;
20
+ /** Response body text; capped with {@link capRawBody}. */
21
+ rawBody?: string | null;
22
+ }
23
+ /**
24
+ * `text` capped at 4096 UTF-16 code units, never ending on half a surrogate
25
+ * pair; `null` for an empty body.
26
+ */
27
+ export declare function capRawBody(text: string): string | null;
28
+ /**
29
+ * A non-2xx answer, unusable 2xx, or no answer from the Hawcx profile service. Message is
30
+ * `"<status> <title>: <detail>"`; never carries a token.
31
+ */
32
+ export declare class ProfileApiError extends HawcxError {
33
+ readonly status: number;
34
+ readonly title: string | null;
35
+ readonly detail: string | null;
36
+ readonly type: string | null;
37
+ readonly instance: string | null;
38
+ /** `X-Request-Id` response header (else a body `request_id`, Kong), for support tickets. */
39
+ readonly requestId: string | null;
40
+ /** `Retry-After` in seconds, when the server sent one. */
41
+ readonly retryAfter: number | null;
42
+ /** Scopes the token lacked (403 insufficient scope). */
43
+ readonly missing: string[] | null;
44
+ /** Rejected request fields (422). */
45
+ readonly fields: string[] | null;
46
+ /** The parsed problem body, or `null` if the body was not a JSON object. */
47
+ readonly body: Record<string, unknown> | null;
48
+ /**
49
+ * The response body text as received (e.g. a gateway's HTML error page),
50
+ * capped at 4096 UTF-16 code units; `null` if empty or no response. On a
51
+ * 2xx it is kept only for a markup page: a body that does not parse as JSON
52
+ * and starts with `<` after whitespace or a BOM (any other 2xx body may carry profile
53
+ * PII). Never part of `message`.
54
+ */
55
+ readonly rawBody: string | null;
56
+ constructor(init: ProfileApiErrorInit, message?: string);
57
+ }
58
+ /** Trimmed `X-Request-Id`; if blank, a string `request_id` in a JSON-object body (Kong); else null. */
59
+ export declare function requestIdFrom(headers: Headers, body: Record<string, unknown> | null): string | null;
60
+ /** Map an error response to a {@link ProfileApiError}; never throws. */
61
+ export declare function parseProblem(status: number, headers: Headers, bodyText: string): ProfileApiError;
62
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/profile/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAEvC,MAAM,WAAW,mBAAmB;IAClC;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,OAAO,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACzB,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IACtC,0DAA0D;IAC1D,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzB;AAID;;;GAGG;AACH,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAKtD;AAED;;;GAGG;AACH,qBAAa,eAAgB,SAAQ,UAAU;IAC7C,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC/B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,4FAA4F;IAC5F,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IAClC,qCAAqC;IACrC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC;IACjC,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAC9C;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;gBAEpB,IAAI,EAAE,mBAAmB,EAAE,OAAO,CAAC,EAAE,MAAM;CAiBxD;AAUD,uGAAuG;AACvG,wBAAgB,aAAa,CAC3B,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,GACnC,MAAM,GAAG,IAAI,CAEf;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,CA6BhG"}
@@ -0,0 +1,90 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ProfileApiError = void 0;
4
+ exports.capRawBody = capRawBody;
5
+ exports.requestIdFrom = requestIdFrom;
6
+ exports.parseProblem = parseProblem;
7
+ /**
8
+ * Profile service errors (RFC 9457 `application/problem+json`).
9
+ */
10
+ const errors_1 = require("../errors");
11
+ const RAW_BODY_CAP = 4096;
12
+ /**
13
+ * `text` capped at 4096 UTF-16 code units, never ending on half a surrogate
14
+ * pair; `null` for an empty body.
15
+ */
16
+ function capRawBody(text) {
17
+ if (text === '')
18
+ return null;
19
+ if (text.length <= RAW_BODY_CAP)
20
+ return text;
21
+ const last = text.charCodeAt(RAW_BODY_CAP - 1);
22
+ return text.slice(0, last >= 0xd800 && last <= 0xdbff ? RAW_BODY_CAP - 1 : RAW_BODY_CAP);
23
+ }
24
+ /**
25
+ * A non-2xx answer, unusable 2xx, or no answer from the Hawcx profile service. Message is
26
+ * `"<status> <title>: <detail>"`; never carries a token.
27
+ */
28
+ class ProfileApiError extends errors_1.HawcxError {
29
+ constructor(init, message) {
30
+ const title = init.title ?? null;
31
+ const detail = init.detail ?? null;
32
+ super(message ?? `${init.status}${title ? ` ${title}` : ''}${detail ? `: ${detail}` : ''}`);
33
+ this.name = 'ProfileApiError';
34
+ this.status = init.status;
35
+ this.title = title;
36
+ this.detail = detail;
37
+ this.type = init.type ?? null;
38
+ this.instance = init.instance ?? null;
39
+ this.requestId = init.requestId ?? null;
40
+ this.retryAfter = init.retryAfter ?? null;
41
+ this.missing = init.missing ?? null;
42
+ this.fields = init.fields ?? null;
43
+ this.body = init.body ?? null;
44
+ this.rawBody = init.rawBody ?? null;
45
+ }
46
+ }
47
+ exports.ProfileApiError = ProfileApiError;
48
+ /** A string, trimmed; blank counts as absent. */
49
+ const text = (v) => {
50
+ const t = typeof v === 'string' ? v.trim() : '';
51
+ return t === '' ? null : t;
52
+ };
53
+ const strArray = (v) => Array.isArray(v) && v.every(x => typeof x === 'string') ? v : null;
54
+ /** Trimmed `X-Request-Id`; if blank, a string `request_id` in a JSON-object body (Kong); else null. */
55
+ function requestIdFrom(headers, body) {
56
+ return text(headers.get('X-Request-Id')) ?? text(body?.request_id);
57
+ }
58
+ /** Map an error response to a {@link ProfileApiError}; never throws. */
59
+ function parseProblem(status, headers, bodyText) {
60
+ let body = null;
61
+ try {
62
+ const parsed = JSON.parse(bodyText);
63
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)) {
64
+ body = parsed;
65
+ }
66
+ }
67
+ catch {
68
+ // not JSON (e.g. a gateway HTML page): keep what the status tells us
69
+ }
70
+ // Delta-seconds only; an HTTP-date Retry-After falls back to backoff.
71
+ const ra = headers.get('Retry-After');
72
+ const retryAfter = ra !== null && /^\d+$/.test(ra.trim()) ? Number(ra.trim()) : null;
73
+ const title = text(body?.title);
74
+ // Kong answers {"message": ..., "request_id": ...}, not problem+json.
75
+ const detail = text(body?.detail) ?? (title === null ? text(body?.message) : null);
76
+ return new ProfileApiError({
77
+ status,
78
+ title,
79
+ detail,
80
+ type: text(body?.type),
81
+ instance: text(body?.instance),
82
+ requestId: requestIdFrom(headers, body),
83
+ retryAfter,
84
+ missing: strArray(body?.missing),
85
+ fields: strArray(body?.fields),
86
+ body,
87
+ rawBody: capRawBody(bodyText),
88
+ });
89
+ }
90
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/profile/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,57 @@
1
+ import type { TokenSource } from './tokens';
2
+ export interface ProfileHttpOptions {
3
+ /** Base URL, e.g. `https://api.hawcx.com/profile` (https, http only on loopback). */
4
+ baseUrl: string;
5
+ configId: string;
6
+ tokens: Pick<TokenSource, 'getToken' | 'invalidate'>;
7
+ /**
8
+ * `fetch` implementation. Failures from an injected fetch whose error shape
9
+ * isn't recognised (no connect-phase `code`/`errno`) count as "may have run".
10
+ */
11
+ fetch?: typeof fetch;
12
+ /** Per-request timeout in ms (default 10000). */
13
+ timeout?: number;
14
+ /**
15
+ * Retry budget per call (default 2): GET/PUT/DELETE on transient profile
16
+ * failures, and every method (POST/PATCH included) on a transient
17
+ * token-endpoint failure, since no profile request was sent.
18
+ */
19
+ maxRetries?: number;
20
+ /** Injectable for tests. */
21
+ sleep?: (ms: number) => Promise<void>;
22
+ /**
23
+ * After a 401, if minting the replay's token fails with a non-transient
24
+ * token error, throw that 401 instead (delegated client: the ID token has
25
+ * expired, so `invalid_grant` would hide the real answer).
26
+ */
27
+ surface401?: boolean;
28
+ }
29
+ export interface RequestOptions {
30
+ query?: Record<string, string | number | undefined>;
31
+ body?: unknown;
32
+ /** Shape check for a 2xx JSON body (default: a JSON object); `false` throws `Unexpected response body`. */
33
+ valid?: (data: unknown) => boolean;
34
+ }
35
+ export declare const isObject: (v: unknown) => v is Record<string, unknown>;
36
+ /**
37
+ * Validate a caller-supplied path parameter and percent-encode it as exactly
38
+ * one segment (`?`, `#`, `%` encoded). Empty, `.`, `..`, and anything with
39
+ * `/`, `\` or a control character are refused client-side: an encoded `%2F`
40
+ * could still be decoded into a separator by a proxy.
41
+ */
42
+ export declare function segment(value: string, name: string): string;
43
+ export declare class ProfileHttp {
44
+ #private;
45
+ constructor(options: ProfileHttpOptions);
46
+ /**
47
+ * `segments` must already be encoded literals or {@link segment} output.
48
+ * Returns the parsed 2xx JSON body, which must pass `opts.valid` (default:
49
+ * a JSON object) or a `ProfileApiError` is thrown; a 204 to any method but
50
+ * DELETE is `Unexpected response body`. `null` only for a DELETE answered
51
+ * 2xx (whatever the body), or a DELETE answered 404 after an earlier attempt
52
+ * of the same call may have run (no response, a 2xx whose body failed
53
+ * mid-read, or 504).
54
+ */
55
+ request<T = unknown>(method: string, segments: string[], opts?: RequestOptions): Promise<T>;
56
+ }
57
+ //# sourceMappingURL=http.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"http.d.ts","sourceRoot":"","sources":["../../src/profile/http.ts"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C,MAAM,WAAW,kBAAkB;IACjC,qFAAqF;IACrF,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,GAAG,YAAY,CAAC,CAAC;IACrD;;;OAGG;IACH,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;IACrB,iDAAiD;IACjD,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,4BAA4B;IAC5B,KAAK,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACtC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;IACpD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,2GAA2G;IAC3G,KAAK,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,OAAO,CAAC;CACpC;AAUD,eAAO,MAAM,QAAQ,GAAI,GAAG,OAAO,KAAG,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CACP,CAAC;AAE3D;;;;;GAKG;AACH,wBAAgB,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAc3D;AAED,qBAAa,WAAW;;gBAIV,OAAO,EAAE,kBAAkB;IAYvC;;;;;;;;OAQG;IACG,OAAO,CAAC,CAAC,GAAG,OAAO,EACvB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAAE,EAClB,IAAI,GAAE,cAAmB,GACxB,OAAO,CAAC,CAAC,CAAC;CA0Kd"}