@conduit-client/jwt-manager 3.0.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -3,6 +3,7 @@
3
3
  * All rights reserved.
4
4
  * For full license text, see the LICENSE.txt file
5
5
  */
6
+ import { loggerService } from "@conduit-client/utils";
6
7
  function e(e2) {
7
8
  this.message = e2;
8
9
  }
@@ -51,50 +52,6 @@ function o(e2, r2) {
51
52
  }
52
53
  }
53
54
  n.prototype = new Error(), n.prototype.name = "InvalidTokenError";
54
- /*!
55
- * Copyright (c) 2022, Salesforce, Inc.,
56
- * All rights reserved.
57
- * For full license text, see the LICENSE.txt file
58
- */
59
- const LogLevelMap = {
60
- TRACE: 4,
61
- DEBUG: 3,
62
- INFO: 2,
63
- WARN: 1,
64
- ERROR: 0
65
- };
66
- class ConsoleLogger {
67
- constructor(level = "WARN", printer = console.log, formatter = (level2, message) => `${level2}: ${message}`) {
68
- this.level = level;
69
- this.printer = printer;
70
- this.formatter = formatter;
71
- this.messages = [];
72
- }
73
- trace(message) {
74
- this.log("TRACE", message);
75
- }
76
- debug(message) {
77
- this.log("DEBUG", message);
78
- }
79
- info(message) {
80
- this.log("INFO", message);
81
- }
82
- warn(message) {
83
- this.log("WARN", message);
84
- }
85
- error(message) {
86
- this.log("ERROR", message);
87
- }
88
- log(level, message) {
89
- if (LogLevelMap[level] > LogLevelMap[this.level]) {
90
- return;
91
- }
92
- this.printer(this.formatter(level, message));
93
- }
94
- }
95
- function loggerService(level, printer, formatter) {
96
- return new ConsoleLogger(level, printer, formatter);
97
- }
98
55
  class JwtToken {
99
56
  /**
100
57
  * Create a new JwtToken.
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../node_modules/jwt-decode/build/jwt-decode.esm.js","../../utils/dist/index.js","../src/jwt-token.ts","../src/jwt-repository.ts","../src/jwt-manager.ts"],"sourcesContent":["function e(e){this.message=e}e.prototype=new Error,e.prototype.name=\"InvalidCharacterError\";var r=\"undefined\"!=typeof window&&window.atob&&window.atob.bind(window)||function(r){var t=String(r).replace(/=+$/,\"\");if(t.length%4==1)throw new e(\"'atob' failed: The string to be decoded is not correctly encoded.\");for(var n,o,a=0,i=0,c=\"\";o=t.charAt(i++);~o&&(n=a%4?64*n+o:o,a++%4)?c+=String.fromCharCode(255&n>>(-2*a&6)):0)o=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\".indexOf(o);return c};function t(e){var t=e.replace(/-/g,\"+\").replace(/_/g,\"/\");switch(t.length%4){case 0:break;case 2:t+=\"==\";break;case 3:t+=\"=\";break;default:throw\"Illegal base64url string!\"}try{return function(e){return decodeURIComponent(r(e).replace(/(.)/g,(function(e,r){var t=r.charCodeAt(0).toString(16).toUpperCase();return t.length<2&&(t=\"0\"+t),\"%\"+t})))}(t)}catch(e){return r(t)}}function n(e){this.message=e}function o(e,r){if(\"string\"!=typeof e)throw new n(\"Invalid token specified\");var o=!0===(r=r||{}).header?0:1;try{return JSON.parse(t(e.split(\".\")[o]))}catch(e){throw new n(\"Invalid token specified: \"+e.message)}}n.prototype=new Error,n.prototype.name=\"InvalidTokenError\";export default o;export{n as InvalidTokenError};\n//# sourceMappingURL=jwt-decode.esm.js.map\n","/*!\n * Copyright (c) 2022, Salesforce, Inc.,\n * All rights reserved.\n * For full license text, see the LICENSE.txt file\n */\nfunction bfs(start, predicate, getChildren) {\n const queue = [...start];\n const visited = /* @__PURE__ */ new Set([...start]);\n const matches2 = /* @__PURE__ */ new Set();\n while (queue.length) {\n const curr = queue.shift();\n if (predicate(curr)) {\n matches2.add(curr);\n }\n const children = getChildren(curr);\n for (const child of children) {\n if (!visited.has(child)) {\n visited.add(child);\n queue.push(child);\n }\n }\n }\n return matches2;\n}\nfunction lineFormatter(position, message, filePath) {\n return `${message} (${filePath}:${position.line}:${position.column})`;\n}\nclass DefaultFileParserLogger {\n constructor(services, filePath) {\n this.services = services;\n this.filePath = filePath;\n }\n trace(position, message) {\n this.services.logger.trace(this.format(position, message));\n }\n debug(position, message) {\n this.services.logger.debug(this.format(position, message));\n }\n info(position, message) {\n this.services.logger.info(this.format(position, message));\n }\n warn(position, message) {\n this.services.logger.warn(this.format(position, message));\n }\n error(position, message) {\n this.services.logger.error(this.format(position, message));\n }\n format(position, message) {\n return lineFormatter(position, message, this.filePath);\n }\n}\nfunction matches(test, s) {\n if (test === void 0) {\n return false;\n } else if (typeof test === \"string\") {\n return s === test;\n } else if (test instanceof RegExp) {\n return test.test(s);\n } else if (typeof test === \"function\") {\n return test(s);\n }\n return test.some((m) => matches(m, s));\n}\nfunction includes(incexc, s) {\n if (matches(incexc.exclude, s)) {\n return false;\n }\n if (matches(incexc.include, s)) {\n return true;\n }\n if (incexc.include) {\n return false;\n }\n return true;\n}\nconst { create, freeze, keys, entries } = Object;\nconst { hasOwnProperty } = Object.prototype;\nconst { isArray } = Array;\nconst { push, indexOf, slice } = Array.prototype;\nconst { stringify, parse } = JSON;\nconst WeakSetConstructor = WeakSet;\nconst LogLevelMap = {\n TRACE: 4,\n DEBUG: 3,\n INFO: 2,\n WARN: 1,\n ERROR: 0\n};\nclass ConsoleLogger {\n constructor(level = \"WARN\", printer = console.log, formatter = (level2, message) => `${level2}: ${message}`) {\n this.level = level;\n this.printer = printer;\n this.formatter = formatter;\n this.messages = [];\n }\n trace(message) {\n this.log(\"TRACE\", message);\n }\n debug(message) {\n this.log(\"DEBUG\", message);\n }\n info(message) {\n this.log(\"INFO\", message);\n }\n warn(message) {\n this.log(\"WARN\", message);\n }\n error(message) {\n this.log(\"ERROR\", message);\n }\n log(level, message) {\n if (LogLevelMap[level] > LogLevelMap[this.level]) {\n return;\n }\n this.printer(this.formatter(level, message));\n }\n}\nfunction loggerService(level, printer, formatter) {\n return new ConsoleLogger(level, printer, formatter);\n}\nclass Ok {\n constructor(value) {\n this.value = value;\n }\n isOk() {\n return true;\n }\n isErr() {\n return !this.isOk();\n }\n}\nclass Err {\n constructor(error) {\n this.error = error;\n }\n isOk() {\n return false;\n }\n isErr() {\n return !this.isOk();\n }\n}\nconst ok = (value) => new Ok(value);\nconst err = (err2) => new Err(err2);\nclass DataNotFoundError extends Error {\n constructor(message) {\n super(message);\n this.name = \"DataNotFoundError\";\n }\n}\nclass DataIncompleteError extends Error {\n constructor(message, partialData) {\n super(message);\n this.partialData = partialData;\n this.name = \"DataIncompleteError\";\n }\n}\nfunction isDataNotFoundError(error) {\n return error instanceof DataNotFoundError || error.name === \"DataNotFoundError\";\n}\nfunction isDataIncompleteError(error) {\n return error instanceof DataIncompleteError || error.name === \"DataIncompleteError\";\n}\nfunction isCacheHitOrError(value) {\n if (value.isErr() && (isDataIncompleteError(value.error) || isDataNotFoundError(value.error))) {\n return false;\n }\n return true;\n}\nfunction isCacheMiss(value) {\n return !isCacheHitOrError(value);\n}\nfunction isResult(value) {\n return value != null && typeof value === \"object\" && \"isOk\" in value && \"isErr\" in value && typeof value.isOk === \"function\" && typeof value.isErr === \"function\" && (value.isOk() === true && value.isErr() === false && \"value\" in value || value.isOk() === false && value.isErr() === true && \"error\" in value);\n}\nfunction setOverlaps(setA, setB) {\n for (const element of setA) {\n if (setB.has(element)) {\n return true;\n }\n }\n return false;\n}\nfunction setDifference(setA, setB) {\n const differenceSet = /* @__PURE__ */ new Set();\n for (const element of setA) {\n if (!setB.has(element)) {\n differenceSet.add(element);\n }\n }\n return differenceSet;\n}\nfunction addAllToSet(targetSet, sourceSet) {\n for (const element of sourceSet) {\n targetSet.add(element);\n }\n}\nconst toTypeScriptSafeIdentifier = (s) => s.length >= 1 ? s[0].replace(/[^$_\\p{ID_Start}]/u, \"_\") + s.slice(1).replace(/[^$\\u200c\\u200d\\p{ID_Continue}]/gu, \"_\") : \"\";\nfunction isSubscribable(obj) {\n return typeof obj === \"object\" && obj !== null && \"subscribe\" in obj && typeof obj.subscribe === \"function\" && \"refresh\" in obj && typeof obj.refresh === \"function\";\n}\nfunction isSubscribableResult(x) {\n if (!isResult(x)) {\n return false;\n }\n return isSubscribable(x.isOk() ? x.value : x.error);\n}\nfunction buildSubscribableResult(result, subscribe, refresh) {\n if (result.isOk()) {\n return ok({ data: result.value, subscribe, refresh });\n } else {\n return err({ failure: result.error, subscribe, refresh });\n }\n}\nfunction resolvedPromiseLike(result) {\n if (isPromiseLike(result)) {\n return result.then((nextResult) => nextResult);\n }\n return {\n then: (onFulfilled, _onRejected) => {\n try {\n return resolvedPromiseLike(onFulfilled(result));\n } catch (e) {\n if (onFulfilled === void 0) {\n return resolvedPromiseLike(result);\n }\n return rejectedPromiseLike(e);\n }\n }\n };\n}\nfunction rejectedPromiseLike(reason) {\n if (isPromiseLike(reason)) {\n return reason.then((nextResult) => nextResult);\n }\n return {\n then: (_onFulfilled, onRejected) => {\n if (typeof onRejected === \"function\") {\n try {\n return resolvedPromiseLike(onRejected(reason));\n } catch (e) {\n return rejectedPromiseLike(e);\n }\n }\n return rejectedPromiseLike(reason);\n }\n };\n}\nfunction isPromiseLike(x) {\n return typeof (x == null ? void 0 : x.then) === \"function\";\n}\nfunction racesync(values) {\n for (const value of values) {\n let settled = void 0;\n if (isPromiseLike(value)) {\n value.then(\n (_) => {\n settled = value;\n },\n (_) => {\n settled = value;\n }\n );\n } else {\n settled = resolvedPromiseLike(value);\n }\n if (settled !== void 0) {\n return settled;\n }\n }\n return Promise.race(values);\n}\nfunction withResolvers() {\n let resolve, reject;\n const promise = new Promise((res, rej) => {\n resolve = res;\n reject = rej;\n });\n return { promise, resolve, reject };\n}\nfunction deepEquals(x, y) {\n if (x === void 0) {\n return y === void 0;\n } else if (x === null) {\n return y === null;\n } else if (y === null) {\n return x === null;\n } else if (isArray(x)) {\n if (!isArray(y) || x.length !== y.length) {\n return false;\n }\n for (let i = 0; i < x.length; ++i) {\n if (!deepEquals(x[i], y[i])) {\n return false;\n }\n }\n return true;\n } else if (typeof x === \"object\") {\n if (typeof y !== \"object\") {\n return false;\n }\n const xkeys = Object.keys(x);\n const ykeys = Object.keys(y);\n if (xkeys.length !== ykeys.length) {\n return false;\n }\n for (let i = 0; i < xkeys.length; ++i) {\n const key = xkeys[i];\n if (!deepEquals(x[key], y[key])) {\n return false;\n }\n }\n return true;\n }\n return x === y;\n}\nfunction stableJSONStringify(node) {\n if (node && node.toJSON && typeof node.toJSON === \"function\") {\n node = node.toJSON();\n }\n if (node === void 0) {\n return;\n }\n if (typeof node === \"number\") {\n return isFinite(node) ? \"\" + node : \"null\";\n }\n if (typeof node !== \"object\") {\n return stringify(node);\n }\n let i;\n let out;\n if (isArray(node)) {\n out = \"[\";\n for (i = 0; i < node.length; i++) {\n if (i) {\n out += \",\";\n }\n out += stableJSONStringify(node[i]) || \"null\";\n }\n return out + \"]\";\n }\n if (node === null) {\n return \"null\";\n }\n const objKeys = keys(node).sort();\n out = \"\";\n for (i = 0; i < objKeys.length; i++) {\n const key = objKeys[i];\n const value = stableJSONStringify(node[key]);\n if (!value) {\n continue;\n }\n if (out) {\n out += \",\";\n }\n out += stringify(key) + \":\" + value;\n }\n return \"{\" + out + \"}\";\n}\nfunction toError(x) {\n if (x instanceof Error) {\n return x;\n }\n return new Error(typeof x === \"string\" ? x : JSON.stringify(x));\n}\nfunction deepCopy(x) {\n const stringified = stringify(x);\n return stringified ? parse(stringified) : void 0;\n}\nfunction readableStreamToAsyncIterable(stream) {\n if (stream.locked) {\n return err(new Error(\"ReadableStream is already locked\"));\n }\n if (Symbol.asyncIterator in stream) {\n return ok(stream);\n }\n const reader = stream.getReader();\n return ok({\n [Symbol.asyncIterator]: () => ({\n next: async () => {\n try {\n const result = await reader.read();\n if (result.done) {\n try {\n reader.releaseLock();\n } catch {\n }\n return { done: true, value: void 0 };\n }\n return {\n done: false,\n value: result.value\n };\n } catch (e) {\n try {\n reader.releaseLock();\n } catch {\n }\n throw e;\n }\n },\n return: async (value) => {\n try {\n await reader.cancel();\n } catch {\n }\n try {\n reader.releaseLock();\n } catch {\n }\n return { done: true, value };\n },\n throw: async (exception) => {\n try {\n await reader.cancel();\n } catch {\n }\n try {\n reader.releaseLock();\n } catch {\n }\n throw exception;\n }\n })\n });\n}\nfunction satisfies(provided, requested) {\n const providedN = provided.split(\".\").map((s) => parseInt(s));\n const requestedN = requested.split(\".\").map((s) => parseInt(s));\n return providedN[0] === requestedN[0] && providedN[1] >= requestedN[1];\n}\nfunction stringIsVersion(s) {\n const versionParts = s.split(\".\");\n return (versionParts.length === 2 || versionParts.length === 3) && versionParts.every((part) => part.match(/^\\d+$/));\n}\nvar HttpStatusCode = /* @__PURE__ */ ((HttpStatusCode2) => {\n HttpStatusCode2[HttpStatusCode2[\"Ok\"] = 200] = \"Ok\";\n HttpStatusCode2[HttpStatusCode2[\"Created\"] = 201] = \"Created\";\n HttpStatusCode2[HttpStatusCode2[\"NoContent\"] = 204] = \"NoContent\";\n HttpStatusCode2[HttpStatusCode2[\"NotModified\"] = 304] = \"NotModified\";\n HttpStatusCode2[HttpStatusCode2[\"BadRequest\"] = 400] = \"BadRequest\";\n HttpStatusCode2[HttpStatusCode2[\"Unauthorized\"] = 401] = \"Unauthorized\";\n HttpStatusCode2[HttpStatusCode2[\"Forbidden\"] = 403] = \"Forbidden\";\n HttpStatusCode2[HttpStatusCode2[\"NotFound\"] = 404] = \"NotFound\";\n HttpStatusCode2[HttpStatusCode2[\"ServerError\"] = 500] = \"ServerError\";\n HttpStatusCode2[HttpStatusCode2[\"GatewayTimeout\"] = 504] = \"GatewayTimeout\";\n return HttpStatusCode2;\n})(HttpStatusCode || {});\nfunction getFetchResponseFromAuraError(err2) {\n if (err2.data !== void 0 && err2.data.statusCode !== void 0) {\n let data = {};\n data = err2.data;\n if (err2.id !== void 0) {\n data.id = err2.id;\n }\n return new FetchResponse(data.statusCode, data);\n }\n return new FetchResponse(500, {\n error: err2.message\n });\n}\nasync function coerceResponseToFetchResponse(response) {\n const { status } = response;\n const responseHeaders = {};\n response.headers.forEach((value, key) => {\n responseHeaders[key] = value;\n });\n let responseBody = null;\n if (status !== 204) {\n const contentType = responseHeaders[\"content-type\"];\n responseBody = contentType && contentType.startsWith(\"application/json\") ? await response.json() : await response.text();\n }\n return new FetchResponse(status, responseBody, responseHeaders);\n}\nfunction getStatusText(status) {\n switch (status) {\n case 200:\n return \"OK\";\n case 201:\n return \"Created\";\n case 304:\n return \"Not Modified\";\n case 400:\n return \"Bad Request\";\n case 404:\n return \"Not Found\";\n case 500:\n return \"Server Error\";\n default:\n return `Unexpected HTTP Status Code: ${status}`;\n }\n}\nclass FetchResponse extends Error {\n constructor(status, body, headers) {\n super();\n this.status = status;\n this.body = body;\n this.headers = headers || {};\n this.ok = status >= 200 && this.status <= 299;\n this.statusText = getStatusText(status);\n }\n}\nconst deeplyFrozen = new WeakSetConstructor();\nfunction deepFreeze(value) {\n if (typeof value !== \"object\" || value === null || deeplyFrozen.has(value)) {\n return;\n }\n deeplyFrozen.add(value);\n if (isArray(value)) {\n for (let i = 0, len = value.length; i < len; i += 1) {\n deepFreeze(value[i]);\n }\n } else {\n const keys$1 = keys(value);\n for (let i = 0, len = keys$1.length; i < len; i += 1) {\n deepFreeze(value[keys$1[i]]);\n }\n }\n freeze(value);\n}\nfunction isScalar(value) {\n return typeof value === \"string\" || typeof value === \"number\" || typeof value === \"boolean\" || value === null || value === void 0;\n}\nfunction isScalarObject(value) {\n return Object.values(value).every((value2) => isScalar(value2));\n}\nfunction isScalarArray(value) {\n return value.every((item) => isScalar(item));\n}\nfunction encodeQueryParam(paramName, value, explode) {\n switch (typeof value) {\n case \"string\":\n return [`${paramName}=${encodeURIComponent(value)}`];\n case \"number\":\n case \"boolean\":\n return [`${paramName}=${value}`];\n case \"object\":\n if (value === null) {\n return [];\n }\n if (isArray(value)) {\n if (!isScalarArray(value)) {\n throw new Error(`Unsupported non-scalar array type for ${paramName}`);\n }\n if (explode) {\n return value.map(\n (item) => `${paramName}=${item ? encodeURIComponent(item) : item}`\n );\n }\n return [\n `${paramName}=${value.map((item) => item ? encodeURIComponent(item) : item).join(\",\")}`\n ];\n }\n if (!isScalarObject(value)) {\n throw new Error(`Unsupported non-scalar object type for ${paramName}`);\n }\n if (explode) {\n return entries(value).map(\n ([key, value2]) => `${key}=${value2 ? encodeURIComponent(value2) : value2}`\n );\n }\n return [\n `${paramName}=${entries(value).flat().map((item) => item ? encodeURIComponent(item) : item).join(\",\")}`\n ];\n default:\n return [];\n }\n}\nclass InternalError extends Error {\n constructor(data) {\n super();\n this.data = data;\n this.type = \"internal\";\n }\n}\nclass UserVisibleError extends Error {\n constructor(data) {\n super();\n this.data = data;\n this.type = \"user-visible\";\n }\n}\nfunction isUserVisibleError(error) {\n return error instanceof Error && \"type\" in error && error.type === \"user-visible\";\n}\nfunction logError(error) {\n if (isUserVisibleError(error)) {\n return;\n }\n console.error(\"OneStore Command threw an error that we did not expect\", error);\n}\nfunction applyDecorators(baseCommand, decorators, options) {\n if (!decorators || decorators.length === 0) {\n return baseCommand;\n }\n return decorators.reduce((command, decorator) => decorator(command, options), baseCommand);\n}\nexport {\n isArray as ArrayIsArray,\n indexOf as ArrayPrototypeIndexOf,\n push as ArrayPrototypePush,\n slice as ArrayPrototypeSlice,\n ConsoleLogger,\n DataIncompleteError,\n DataNotFoundError,\n DefaultFileParserLogger,\n Err,\n FetchResponse,\n HttpStatusCode,\n InternalError,\n parse as JSONParse,\n stringify as JSONStringify,\n LogLevelMap,\n create as ObjectCreate,\n entries as ObjectEntries,\n freeze as ObjectFreeze,\n keys as ObjectKeys,\n hasOwnProperty as ObjectPrototypeHasOwnProperty,\n Ok,\n UserVisibleError,\n WeakSetConstructor,\n addAllToSet,\n applyDecorators,\n bfs,\n buildSubscribableResult,\n coerceResponseToFetchResponse,\n deepCopy,\n deepEquals,\n deepFreeze,\n encodeQueryParam,\n err,\n getFetchResponseFromAuraError,\n includes,\n isCacheHitOrError,\n isCacheMiss,\n isDataIncompleteError,\n isDataNotFoundError,\n isPromiseLike,\n isResult,\n isSubscribable,\n isSubscribableResult,\n isUserVisibleError,\n lineFormatter,\n logError,\n loggerService,\n ok,\n racesync,\n readableStreamToAsyncIterable,\n rejectedPromiseLike,\n resolvedPromiseLike,\n satisfies,\n setDifference,\n setOverlaps,\n stableJSONStringify,\n stringIsVersion,\n toError,\n toTypeScriptSafeIdentifier,\n withResolvers\n};\n//# sourceMappingURL=index.js.map\n","import type { JwtPayload } from 'jwt-decode';\n\n/**\n * Represents a decoded JWT payload with a non-nullable 'exp' field and any additional payload T.\n */\nexport type JwtTokenInfo<T = unknown> = JwtPayload & { exp: NonNullable<JwtPayload['exp']> } & T;\n\n/**\n * Represents a JWT token with its decoded info and optional extra info.\n *\n * @typeparam T - Type of the additional payload in the JWT.\n * @typeparam ExtraInfo - Type of the additional information.\n */\nexport class JwtToken<T = unknown, ExtraInfo = undefined> {\n /**\n * Create a new JwtToken.\n *\n * @param _token - The JWT string.\n * @param _decodedInfo - The decoded information from the JWT.\n * @param _extraInfo - Any additional information associated with the JWT.\n */\n constructor(\n private _token: string,\n private _decodedInfo: JwtTokenInfo<T>,\n private _extraInfo?: ExtraInfo\n ) {}\n\n /**\n * Get the JWT string.\n *\n * @returns The JWT string.\n */\n public get token() {\n return this._token;\n }\n\n /**\n * Get the additional information associated with the JWT.\n *\n * @returns The additional information.\n */\n public get extraInfo() {\n return this._extraInfo;\n }\n\n /**\n * Get the decoded information from the JWT.\n *\n * @returns The decoded information.\n */\n public get decodedInfo() {\n return this._decodedInfo;\n }\n\n /**\n * Get the remaining time in seconds until the JWT expires.\n *\n * @returns The remaining time in seconds.\n */\n public get tokenRemainingSeconds(): number {\n return this.decodedInfo.exp - Date.now() / 1000;\n }\n\n /**\n * Check if the JWT is expired.\n *\n * @returns True if the JWT is expired, false otherwise.\n */\n public get isExpired(): boolean {\n return this.tokenRemainingSeconds <= 0;\n }\n}\n","import jwt_decode from 'jwt-decode';\nimport { loggerService } from '@conduit-client/utils';\nimport { JwtToken } from './jwt-token';\nimport type { LoggerService } from '@conduit-client/utils';\nimport type { JwtTokenInfo } from './jwt-token';\n\n/**\n * Default logger if none is provided. Is overwritten in non-production environments.\n */\nlet defaultLogger: LoggerService = {\n trace: () => {},\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\nif (process.env.NODE_ENV !== 'production') {\n defaultLogger = loggerService();\n}\n\n/**\n * Decodes JWT token information and provides a default expiry if none is present.\n *\n * @param token - JWT token as a string.\n * @param defaultTokenTTLInSeconds - Default expiry time in seconds if \"exp\" claim is not present in token.\n * @param logger - Logger for logging warnings and errors.\n *\n * @returns An object of decoded JWT token information.\n */\nfunction computeDecodedInfo<T>(\n token: string,\n defaultTokenTTLInSeconds: number,\n logger: LoggerService\n): JwtTokenInfo<T> {\n const decodedInfo = jwt_decode<JwtTokenInfo<T>>(token);\n\n if (decodedInfo.exp === undefined) {\n logger.warn(`\"exp\" claim is not present in the provided token.`);\n decodedInfo.exp = Date.now() / 1000 + defaultTokenTTLInSeconds;\n }\n\n return decodedInfo;\n}\n\n/**\n * A repository for JWT tokens.\n */\nexport class JwtRepository<T = unknown, ExtraInfo = undefined> {\n private _token?: JwtToken<T, ExtraInfo>;\n private timeoutHandler?: ReturnType<typeof setTimeout>;\n private observers: Array<(token: JwtToken<T, ExtraInfo>) => void> = [];\n\n /**\n * @param limitInSeconds - Time in seconds before the token's expiry to notify observers.\n * @param defaultTokenTTLInSeconds - Default token expiry time in seconds if \"exp\" claim is not present in token.\n * @param logger - Logger for logging warnings and errors.\n */\n constructor(\n private limitInSeconds: number = 5,\n private defaultTokenTTLInSeconds = 120,\n private logger: LoggerService = defaultLogger\n ) {}\n\n /**\n * Get the current token.\n */\n public get token() {\n return this._token;\n }\n\n /**\n * Set the current token.\n *\n * @param token - JWT token as a string.\n * @param extraInfo - Optional extra information.\n */\n public setToken(token: string, extraInfo?: ExtraInfo): JwtToken<T, ExtraInfo> {\n const decodedInfo = computeDecodedInfo<T>(\n token,\n this.defaultTokenTTLInSeconds,\n this.logger\n );\n this._token = new JwtToken<T, ExtraInfo>(token, decodedInfo, extraInfo);\n\n this.observeTokenExpiration();\n\n return this._token;\n }\n\n /**\n * Remove the current token.\n */\n public removeToken(): void {\n this._token = undefined;\n this.clearTimeoutHandler();\n }\n\n /**\n * Subscribe to the token nearing its expiration.\n *\n * @param cb - Callback function to execute when token is nearing expiration.\n */\n public subscribeToTokenNearExpiration(cb: (token: JwtToken<T, ExtraInfo>) => void): () => void {\n this.observers.push(cb);\n this.observeTokenExpiration();\n\n return () => {\n this.observers = this.observers.filter((observer) => observer !== cb);\n };\n }\n\n /**\n * Clear the timeout handler.\n */\n private clearTimeoutHandler(): void {\n if (this.timeoutHandler !== undefined) {\n clearTimeout(this.timeoutHandler);\n }\n }\n\n /**\n * Observe and handle token expiration.\n */\n private observeTokenExpiration(): void {\n this.clearTimeoutHandler();\n if (this.observers.length === 0 || this.token === undefined) {\n return;\n }\n\n this.timeoutHandler = setTimeout(\n () => this.notifyTokenIsExpiring(),\n this.computeTimeoutTimeInMs()\n );\n }\n\n /**\n * Compute the timeout time in milliseconds.\n */\n private computeTimeoutTimeInMs() {\n const remainingSeconds = this.token!.tokenRemainingSeconds;\n\n let timeoutTimeInSeconds = remainingSeconds - this.limitInSeconds;\n\n return timeoutTimeInSeconds < 0 ? 0 : timeoutTimeInSeconds * 1000;\n }\n\n /**\n * Notify all observers that the token is expiring.\n */\n private notifyTokenIsExpiring() {\n this.observers.forEach((cb) => {\n try {\n cb.call(undefined, this.token!);\n } catch (e) {\n this.logger.error((e as Error).message);\n }\n });\n }\n}\n","import type { JwtRepository } from './jwt-repository';\nimport type { JwtToken } from './jwt-token';\n\n/**\n * JwtResolver type. It is used to define the structure for JWT resolver instances.\n * JwtResolver contains a method getJwt that should return a Promise with a JWT and optionally extra information.\n *\n * @template ExtraInfo The type of the optional extra information returned by the getJwt method. Defaults to undefined.\n * @property {() => Promise<{ jwt: string; extraInfo: ExtraInfo }>} getJwt Method for getting a JWT.\n */\nexport type JwtResolver<ExtraInfo = undefined> = {\n getJwt(): Promise<{ jwt: string; extraInfo: ExtraInfo }>;\n};\n\n/**\n * JwtManagerOptions bag\n *\n * keepTokenUpdated: indicates whether the token should be updated each time it nears expiration\n * @property {boolean}\n */\nexport type JwtManagerOptions = {\n keepTokenUpdated?: boolean;\n};\n\n/**\n * JwtManager class.\n * It provides methods for managing JWT (Json Web Token), such as retrieving and refreshing.\n *\n * @template T The data type the JwtToken carries. Default to unknown.\n * @template ExtraInfo The type of the optional extra information returned by the getJwt method. Defaults to undefined.\n * @property {JwtRepository<T, ExtraInfo>} jwtRepository JwtRepository instance used for token management.\n * @property {JwtResolver<ExtraInfo>} resolver JwtResolver instance used for token retrieval.\n */\nexport class JwtManager<T = unknown, ExtraInfo = undefined> {\n private inflightPromise?: Promise<JwtToken<T, ExtraInfo>>;\n\n /**\n * Constructor for JwtManager class.\n *\n * @param {JwtRepository<T, ExtraInfo>} jwtRepository JwtRepository instance used for token management.\n * @param {JwtResolver<ExtraInfo>} resolver JwtResolver instance used for token retrieval.\n * @param {JwtManagerOptions} options JwtManagerOptions bag to customize behavior.\n */\n constructor(\n private jwtRepository: JwtRepository<T, ExtraInfo>,\n private resolver: JwtResolver<ExtraInfo>,\n options?: JwtManagerOptions\n ) {\n if (options?.keepTokenUpdated) {\n jwtRepository.subscribeToTokenNearExpiration(() => this.refreshToken());\n }\n }\n\n /**\n * Method to get a JWT token.\n * If there's a token request in progress, it will return the Promise of this request.\n * If the current token is undefined or expired, it will initiate a token refresh.\n * Otherwise, it will return the current token.\n *\n * @returns {JwtToken<T, ExtraInfo> | Promise<JwtToken<T, ExtraInfo>>} The current token or the Promise of a token request.\n */\n getJwt(): JwtToken<T, ExtraInfo> | Promise<JwtToken<T, ExtraInfo>> {\n if (this.inflightPromise) {\n return this.inflightPromise;\n }\n\n const token = this.jwtRepository.token;\n\n if (token === undefined || token.isExpired) {\n return this.refreshToken();\n }\n\n return token;\n }\n\n /**\n * Method to refresh a JWT token.\n * If a refresh request is already in progress, it will return the Promise of this request.\n * Otherwise, it will start a new refresh request and return its Promise.\n *\n * @returns {Promise<JwtToken<T, ExtraInfo>>} Promise of the refreshed token.\n */\n refreshToken(): Promise<JwtToken<T, ExtraInfo>> {\n if (this.inflightPromise === undefined) {\n this.inflightPromise = new Promise((resolve, reject) => {\n this.resolver\n .getJwt()\n .then(({ jwt, extraInfo }) => {\n this.inflightPromise = undefined;\n const token = this.jwtRepository.setToken(jwt, extraInfo);\n resolve(token);\n })\n .catch((reason) => {\n this.inflightPromise = undefined;\n reject(reason);\n });\n });\n }\n\n return this.inflightPromise;\n }\n\n /**\n * Method to check if a token refresh is in progress.\n *\n * @returns {boolean} true if a token refresh is in progress, false otherwise.\n */\n get isRefreshingToken() {\n return this.inflightPromise !== undefined;\n }\n}\n"],"names":["e","r","t","n","o","jwt_decode"],"mappings":"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","x_google_ignoreList":[0]}
1
+ {"version":3,"file":"index.js","sources":["../../../../node_modules/jwt-decode/build/jwt-decode.esm.js","../src/jwt-token.ts","../src/jwt-repository.ts","../src/jwt-manager.ts"],"sourcesContent":["function e(e){this.message=e}e.prototype=new Error,e.prototype.name=\"InvalidCharacterError\";var r=\"undefined\"!=typeof window&&window.atob&&window.atob.bind(window)||function(r){var t=String(r).replace(/=+$/,\"\");if(t.length%4==1)throw new e(\"'atob' failed: The string to be decoded is not correctly encoded.\");for(var n,o,a=0,i=0,c=\"\";o=t.charAt(i++);~o&&(n=a%4?64*n+o:o,a++%4)?c+=String.fromCharCode(255&n>>(-2*a&6)):0)o=\"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=\".indexOf(o);return c};function t(e){var t=e.replace(/-/g,\"+\").replace(/_/g,\"/\");switch(t.length%4){case 0:break;case 2:t+=\"==\";break;case 3:t+=\"=\";break;default:throw\"Illegal base64url string!\"}try{return function(e){return decodeURIComponent(r(e).replace(/(.)/g,(function(e,r){var t=r.charCodeAt(0).toString(16).toUpperCase();return t.length<2&&(t=\"0\"+t),\"%\"+t})))}(t)}catch(e){return r(t)}}function n(e){this.message=e}function o(e,r){if(\"string\"!=typeof e)throw new n(\"Invalid token specified\");var o=!0===(r=r||{}).header?0:1;try{return JSON.parse(t(e.split(\".\")[o]))}catch(e){throw new n(\"Invalid token specified: \"+e.message)}}n.prototype=new Error,n.prototype.name=\"InvalidTokenError\";export default o;export{n as InvalidTokenError};\n//# sourceMappingURL=jwt-decode.esm.js.map\n","import type { JwtPayload } from 'jwt-decode';\n\n/**\n * Represents a decoded JWT payload with a non-nullable 'exp' field and any additional payload T.\n */\nexport type JwtTokenInfo<T = unknown> = JwtPayload & { exp: NonNullable<JwtPayload['exp']> } & T;\n\n/**\n * Represents a JWT token with its decoded info and optional extra info.\n *\n * @typeparam T - Type of the additional payload in the JWT.\n * @typeparam ExtraInfo - Type of the additional information.\n */\nexport class JwtToken<T = unknown, ExtraInfo = undefined> {\n /**\n * Create a new JwtToken.\n *\n * @param _token - The JWT string.\n * @param _decodedInfo - The decoded information from the JWT.\n * @param _extraInfo - Any additional information associated with the JWT.\n */\n constructor(\n private _token: string,\n private _decodedInfo: JwtTokenInfo<T>,\n private _extraInfo?: ExtraInfo\n ) {}\n\n /**\n * Get the JWT string.\n *\n * @returns The JWT string.\n */\n public get token() {\n return this._token;\n }\n\n /**\n * Get the additional information associated with the JWT.\n *\n * @returns The additional information.\n */\n public get extraInfo() {\n return this._extraInfo;\n }\n\n /**\n * Get the decoded information from the JWT.\n *\n * @returns The decoded information.\n */\n public get decodedInfo() {\n return this._decodedInfo;\n }\n\n /**\n * Get the remaining time in seconds until the JWT expires.\n *\n * @returns The remaining time in seconds.\n */\n public get tokenRemainingSeconds(): number {\n return this.decodedInfo.exp - Date.now() / 1000;\n }\n\n /**\n * Check if the JWT is expired.\n *\n * @returns True if the JWT is expired, false otherwise.\n */\n public get isExpired(): boolean {\n return this.tokenRemainingSeconds <= 0;\n }\n}\n","import jwt_decode from 'jwt-decode';\nimport { loggerService } from '@conduit-client/utils';\nimport { JwtToken } from './jwt-token';\nimport type { LoggerService } from '@conduit-client/utils';\nimport type { JwtTokenInfo } from './jwt-token';\n\n/**\n * Default logger if none is provided. Is overwritten in non-production environments.\n */\nlet defaultLogger: LoggerService = {\n trace: () => {},\n debug: () => {},\n info: () => {},\n warn: () => {},\n error: () => {},\n};\n\nif (process.env.NODE_ENV !== 'production') {\n defaultLogger = loggerService();\n}\n\n/**\n * Decodes JWT token information and provides a default expiry if none is present.\n *\n * @param token - JWT token as a string.\n * @param defaultTokenTTLInSeconds - Default expiry time in seconds if \"exp\" claim is not present in token.\n * @param logger - Logger for logging warnings and errors.\n *\n * @returns An object of decoded JWT token information.\n */\nfunction computeDecodedInfo<T>(\n token: string,\n defaultTokenTTLInSeconds: number,\n logger: LoggerService\n): JwtTokenInfo<T> {\n const decodedInfo = jwt_decode<JwtTokenInfo<T>>(token);\n\n if (decodedInfo.exp === undefined) {\n logger.warn(`\"exp\" claim is not present in the provided token.`);\n decodedInfo.exp = Date.now() / 1000 + defaultTokenTTLInSeconds;\n }\n\n return decodedInfo;\n}\n\n/**\n * A repository for JWT tokens.\n */\nexport class JwtRepository<T = unknown, ExtraInfo = undefined> {\n private _token?: JwtToken<T, ExtraInfo>;\n private timeoutHandler?: ReturnType<typeof setTimeout>;\n private observers: Array<(token: JwtToken<T, ExtraInfo>) => void> = [];\n\n /**\n * @param limitInSeconds - Time in seconds before the token's expiry to notify observers.\n * @param defaultTokenTTLInSeconds - Default token expiry time in seconds if \"exp\" claim is not present in token.\n * @param logger - Logger for logging warnings and errors.\n */\n constructor(\n private limitInSeconds: number = 5,\n private defaultTokenTTLInSeconds = 120,\n private logger: LoggerService = defaultLogger\n ) {}\n\n /**\n * Get the current token.\n */\n public get token() {\n return this._token;\n }\n\n /**\n * Set the current token.\n *\n * @param token - JWT token as a string.\n * @param extraInfo - Optional extra information.\n */\n public setToken(token: string, extraInfo?: ExtraInfo): JwtToken<T, ExtraInfo> {\n const decodedInfo = computeDecodedInfo<T>(\n token,\n this.defaultTokenTTLInSeconds,\n this.logger\n );\n this._token = new JwtToken<T, ExtraInfo>(token, decodedInfo, extraInfo);\n\n this.observeTokenExpiration();\n\n return this._token;\n }\n\n /**\n * Remove the current token.\n */\n public removeToken(): void {\n this._token = undefined;\n this.clearTimeoutHandler();\n }\n\n /**\n * Subscribe to the token nearing its expiration.\n *\n * @param cb - Callback function to execute when token is nearing expiration.\n */\n public subscribeToTokenNearExpiration(cb: (token: JwtToken<T, ExtraInfo>) => void): () => void {\n this.observers.push(cb);\n this.observeTokenExpiration();\n\n return () => {\n this.observers = this.observers.filter((observer) => observer !== cb);\n };\n }\n\n /**\n * Clear the timeout handler.\n */\n private clearTimeoutHandler(): void {\n if (this.timeoutHandler !== undefined) {\n clearTimeout(this.timeoutHandler);\n }\n }\n\n /**\n * Observe and handle token expiration.\n */\n private observeTokenExpiration(): void {\n this.clearTimeoutHandler();\n if (this.observers.length === 0 || this.token === undefined) {\n return;\n }\n\n this.timeoutHandler = setTimeout(\n () => this.notifyTokenIsExpiring(),\n this.computeTimeoutTimeInMs()\n );\n }\n\n /**\n * Compute the timeout time in milliseconds.\n */\n private computeTimeoutTimeInMs() {\n const remainingSeconds = this.token!.tokenRemainingSeconds;\n\n let timeoutTimeInSeconds = remainingSeconds - this.limitInSeconds;\n\n return timeoutTimeInSeconds < 0 ? 0 : timeoutTimeInSeconds * 1000;\n }\n\n /**\n * Notify all observers that the token is expiring.\n */\n private notifyTokenIsExpiring() {\n this.observers.forEach((cb) => {\n try {\n cb.call(undefined, this.token!);\n } catch (e) {\n this.logger.error((e as Error).message);\n }\n });\n }\n}\n","import type { JwtRepository } from './jwt-repository';\nimport type { JwtToken } from './jwt-token';\n\n/**\n * JwtResolver type. It is used to define the structure for JWT resolver instances.\n * JwtResolver contains a method getJwt that should return a Promise with a JWT and optionally extra information.\n *\n * @template ExtraInfo The type of the optional extra information returned by the getJwt method. Defaults to undefined.\n * @property {() => Promise<{ jwt: string; extraInfo: ExtraInfo }>} getJwt Method for getting a JWT.\n */\nexport type JwtResolver<ExtraInfo = undefined> = {\n getJwt(): Promise<{ jwt: string; extraInfo: ExtraInfo }>;\n};\n\n/**\n * JwtManagerOptions bag\n *\n * keepTokenUpdated: indicates whether the token should be updated each time it nears expiration\n * @property {boolean}\n */\nexport type JwtManagerOptions = {\n keepTokenUpdated?: boolean;\n};\n\n/**\n * JwtManager class.\n * It provides methods for managing JWT (Json Web Token), such as retrieving and refreshing.\n *\n * @template T The data type the JwtToken carries. Default to unknown.\n * @template ExtraInfo The type of the optional extra information returned by the getJwt method. Defaults to undefined.\n * @property {JwtRepository<T, ExtraInfo>} jwtRepository JwtRepository instance used for token management.\n * @property {JwtResolver<ExtraInfo>} resolver JwtResolver instance used for token retrieval.\n */\nexport class JwtManager<T = unknown, ExtraInfo = undefined> {\n private inflightPromise?: Promise<JwtToken<T, ExtraInfo>>;\n\n /**\n * Constructor for JwtManager class.\n *\n * @param {JwtRepository<T, ExtraInfo>} jwtRepository JwtRepository instance used for token management.\n * @param {JwtResolver<ExtraInfo>} resolver JwtResolver instance used for token retrieval.\n * @param {JwtManagerOptions} options JwtManagerOptions bag to customize behavior.\n */\n constructor(\n private jwtRepository: JwtRepository<T, ExtraInfo>,\n private resolver: JwtResolver<ExtraInfo>,\n options?: JwtManagerOptions\n ) {\n if (options?.keepTokenUpdated) {\n jwtRepository.subscribeToTokenNearExpiration(() => this.refreshToken());\n }\n }\n\n /**\n * Method to get a JWT token.\n * If there's a token request in progress, it will return the Promise of this request.\n * If the current token is undefined or expired, it will initiate a token refresh.\n * Otherwise, it will return the current token.\n *\n * @returns {JwtToken<T, ExtraInfo> | Promise<JwtToken<T, ExtraInfo>>} The current token or the Promise of a token request.\n */\n getJwt(): JwtToken<T, ExtraInfo> | Promise<JwtToken<T, ExtraInfo>> {\n if (this.inflightPromise) {\n return this.inflightPromise;\n }\n\n const token = this.jwtRepository.token;\n\n if (token === undefined || token.isExpired) {\n return this.refreshToken();\n }\n\n return token;\n }\n\n /**\n * Method to refresh a JWT token.\n * If a refresh request is already in progress, it will return the Promise of this request.\n * Otherwise, it will start a new refresh request and return its Promise.\n *\n * @returns {Promise<JwtToken<T, ExtraInfo>>} Promise of the refreshed token.\n */\n refreshToken(): Promise<JwtToken<T, ExtraInfo>> {\n if (this.inflightPromise === undefined) {\n this.inflightPromise = new Promise((resolve, reject) => {\n this.resolver\n .getJwt()\n .then(({ jwt, extraInfo }) => {\n this.inflightPromise = undefined;\n const token = this.jwtRepository.setToken(jwt, extraInfo);\n resolve(token);\n })\n .catch((reason) => {\n this.inflightPromise = undefined;\n reject(reason);\n });\n });\n }\n\n return this.inflightPromise;\n }\n\n /**\n * Method to check if a token refresh is in progress.\n *\n * @returns {boolean} true if a token refresh is in progress, false otherwise.\n */\n get isRefreshingToken() {\n return this.inflightPromise !== undefined;\n }\n}\n"],"names":["e","r","t","n","o","jwt_decode"],"mappings":"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","x_google_ignoreList":[0]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@conduit-client/jwt-manager",
3
- "version": "3.0.0",
3
+ "version": "3.3.0",
4
4
  "description": "Luvio Next generic JWT manager",
5
5
  "type": "module",
6
6
  "repository": {
@@ -25,7 +25,7 @@
25
25
  "jwt-decode": "~3.1.2"
26
26
  },
27
27
  "devDependencies": {
28
- "@conduit-client/utils": "3.0.0"
28
+ "@conduit-client/utils": "3.3.0"
29
29
  },
30
30
  "size-limit": [
31
31
  {