@ah-oh/ao-workspaces-api-sdk 1.0.23 → 1.0.24
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/CHANGELOG.md +11 -0
- package/README.md +24 -21
- package/package.json +1 -1
- package/src/lib/auth.module.js +14 -23
- package/src/lib/auth.module.js.map +1 -1
- package/src/lib/customer-center.service.d.ts +42 -6
- package/src/lib/customer-center.service.js +136 -42
- package/src/lib/customer-center.service.js.map +1 -1
- package/src/lib/guards/auth.guard.js +3 -4
- package/src/lib/guards/auth.guard.js.map +1 -1
- package/src/lib/guards/company.guard.js +3 -0
- package/src/lib/guards/company.guard.js.map +1 -1
- package/src/lib/guards/sethub-permissions.guard.js +4 -1
- package/src/lib/guards/sethub-permissions.guard.js.map +1 -1
- package/src/lib/guards/super-admin.guard.js +3 -0
- package/src/lib/guards/super-admin.guard.js.map +1 -1
- package/src/lib/guards/szales-basic-auth.guard.js +33 -14
- package/src/lib/guards/szales-basic-auth.guard.js.map +1 -1
- package/src/lib/mail-settings.service.d.ts +3 -3
- package/src/lib/mail-settings.service.js +63 -251
- package/src/lib/mail-settings.service.js.map +1 -1
- package/src/lib/models/auth.options.d.ts +13 -0
- package/src/lib/print.client.d.ts +4 -3
- package/src/lib/print.client.js +46 -32
- package/src/lib/print.client.js.map +1 -1
- package/src/lib/utils/axios-error.handler.d.ts +11 -0
- package/src/lib/utils/axios-error.handler.js +24 -3
- package/src/lib/utils/axios-error.handler.js.map +1 -1
- package/src/lib/utils/http-client.d.ts +9 -0
- package/src/lib/utils/http-client.js +35 -0
- package/src/lib/utils/http-client.js.map +1 -0
- package/src/lib/utils/jwt.util.d.ts +6 -0
- package/src/lib/utils/jwt.util.js +21 -0
- package/src/lib/utils/jwt.util.js.map +1 -0
- package/src/lib/utils/ttl-cache.d.ts +26 -0
- package/src/lib/utils/ttl-cache.js +66 -0
- package/src/lib/utils/ttl-cache.js.map +1 -0
- package/src/lib/utils/url-path.d.ts +7 -0
- package/src/lib/utils/url-path.js +28 -0
- package/src/lib/utils/url-path.js.map +1 -0
package/src/lib/print.client.js
CHANGED
|
@@ -8,6 +8,9 @@ const common_1 = require("@nestjs/common");
|
|
|
8
8
|
const axios_1 = require("axios");
|
|
9
9
|
const auth_constants_1 = require("./auth.constants");
|
|
10
10
|
const customer_center_service_1 = require("./customer-center.service");
|
|
11
|
+
const axios_error_handler_1 = require("./utils/axios-error.handler");
|
|
12
|
+
const http_client_1 = require("./utils/http-client");
|
|
13
|
+
const url_path_1 = require("./utils/url-path");
|
|
11
14
|
/**
|
|
12
15
|
* Error of the hardware API. `code` is the machine-readable code of the body
|
|
13
16
|
* `{ type: 'error', code, message }` (e.g. `target_unassigned`,
|
|
@@ -30,15 +33,19 @@ const CONTENT_MIME_TYPES = {
|
|
|
30
33
|
};
|
|
31
34
|
const DEFAULT_WAIT_TIMEOUT_MS = 60_000;
|
|
32
35
|
const DEFAULT_WAIT_INTERVAL_MS = 2_000;
|
|
36
|
+
/** Same limit as the server; larger content is rejected before the upload. */
|
|
37
|
+
const MAX_CONTENT_BYTES = 50 * 1024 * 1024;
|
|
38
|
+
/** Uploads of up to 50 MB need longer than the default timeout. */
|
|
39
|
+
const MIN_UPLOAD_TIMEOUT_MS = 120_000;
|
|
33
40
|
/** Creates print jobs on the hardware connector API and reads their state (HC-12). */
|
|
34
41
|
let PrintClient = PrintClient_1 = class PrintClient {
|
|
35
|
-
options;
|
|
36
42
|
customerCenterService;
|
|
37
|
-
|
|
43
|
+
http;
|
|
44
|
+
uploadTimeoutMs;
|
|
38
45
|
constructor(options, customerCenterService) {
|
|
39
|
-
this.options = options;
|
|
40
46
|
this.customerCenterService = customerCenterService;
|
|
41
|
-
this.
|
|
47
|
+
this.http = (0, http_client_1.createHttpClient)(options);
|
|
48
|
+
this.uploadTimeoutMs = Math.max(this.http.defaults.timeout ?? 0, MIN_UPLOAD_TIMEOUT_MS);
|
|
42
49
|
}
|
|
43
50
|
/** True once the job will not change anymore (completed, failed, expired, canceled). */
|
|
44
51
|
static isFinal(job) {
|
|
@@ -46,7 +53,9 @@ let PrintClient = PrintClient_1 = class PrintClient {
|
|
|
46
53
|
}
|
|
47
54
|
/** Creates a print job on a print target. Resolves as soon as the job is queued. */
|
|
48
55
|
async print(args) {
|
|
49
|
-
|
|
56
|
+
if (args.content.byteLength > MAX_CONTENT_BYTES) {
|
|
57
|
+
throw new PrintClientError('content_too_large', 'Content is larger than 50 MB', common_1.HttpStatus.PAYLOAD_TOO_LARGE);
|
|
58
|
+
}
|
|
50
59
|
const form = new FormData();
|
|
51
60
|
form.append('target', args.target);
|
|
52
61
|
form.append('contentType', args.contentType);
|
|
@@ -63,17 +72,16 @@ let PrintClient = PrintClient_1 = class PrintClient {
|
|
|
63
72
|
form.append('content', new Blob([args.content], {
|
|
64
73
|
type: CONTENT_MIME_TYPES[args.contentType],
|
|
65
74
|
}), args.fileName ?? `content.${args.contentType}`);
|
|
66
|
-
return this.request({
|
|
75
|
+
return this.request(args, {
|
|
67
76
|
method: 'POST',
|
|
68
|
-
url: `/auth-api/companies/${args.companyId}/hardware/print-jobs`,
|
|
69
|
-
headers: { accept: 'application/json', authorization },
|
|
77
|
+
url: (0, url_path_1.urlPath) `/auth-api/companies/${args.companyId}/hardware/print-jobs`,
|
|
70
78
|
data: form,
|
|
71
|
-
maxBodyLength:
|
|
79
|
+
maxBodyLength: MAX_CONTENT_BYTES + 1024 * 1024,
|
|
80
|
+
timeout: this.uploadTimeoutMs,
|
|
72
81
|
});
|
|
73
82
|
}
|
|
74
83
|
async getJob(args) {
|
|
75
|
-
|
|
76
|
-
return this.fetchJob(args, authorization);
|
|
84
|
+
return this.customerCenterService.withToken(credentialsOf(args), authorization => this.fetchJob(args, authorization));
|
|
77
85
|
}
|
|
78
86
|
/**
|
|
79
87
|
* Polls the job until it reaches a final state or `timeoutMs` has passed.
|
|
@@ -85,32 +93,31 @@ let PrintClient = PrintClient_1 = class PrintClient {
|
|
|
85
93
|
const timeoutMs = args.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;
|
|
86
94
|
const intervalMs = args.intervalMs ?? DEFAULT_WAIT_INTERVAL_MS;
|
|
87
95
|
const deadline = Date.now() + timeoutMs;
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
96
|
+
return this.customerCenterService.withToken(credentialsOf(args), async (authorization) => {
|
|
97
|
+
let job = await this.fetchJob(args, authorization);
|
|
98
|
+
while (!PrintClient_1.isFinal(job) && Date.now() + intervalMs <= deadline) {
|
|
99
|
+
await new Promise(resolve => setTimeout(resolve, intervalMs));
|
|
100
|
+
job = await this.fetchJob(args, authorization);
|
|
101
|
+
}
|
|
102
|
+
return job;
|
|
103
|
+
});
|
|
95
104
|
}
|
|
96
105
|
fetchJob(args, authorization) {
|
|
97
|
-
return this.
|
|
106
|
+
return this.send(authorization, {
|
|
98
107
|
method: 'GET',
|
|
99
|
-
url: `/auth-api/companies/${args.companyId}/hardware/print-jobs/${args.jobId}`,
|
|
100
|
-
headers: { accept: 'application/json', authorization },
|
|
108
|
+
url: (0, url_path_1.urlPath) `/auth-api/companies/${args.companyId}/hardware/print-jobs/${args.jobId}`,
|
|
101
109
|
});
|
|
102
110
|
}
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
tokenKey: credentials.tokenKey,
|
|
107
|
-
product: credentials.product,
|
|
108
|
-
});
|
|
109
|
-
return `Bearer ${token}`;
|
|
111
|
+
/** Signs in with the credentials (token cached by `CustomerCenterService`) and sends the request. */
|
|
112
|
+
request(credentials, config) {
|
|
113
|
+
return this.customerCenterService.withToken(credentialsOf(credentials), authorization => this.send(authorization, config));
|
|
110
114
|
}
|
|
111
|
-
async
|
|
115
|
+
async send(authorization, config) {
|
|
112
116
|
try {
|
|
113
|
-
const res = await
|
|
117
|
+
const res = await this.http.request({
|
|
118
|
+
...config,
|
|
119
|
+
headers: { ...config.headers, authorization },
|
|
120
|
+
});
|
|
114
121
|
return res.data;
|
|
115
122
|
}
|
|
116
123
|
catch (error) {
|
|
@@ -124,11 +131,18 @@ exports.PrintClient = PrintClient = PrintClient_1 = tslib_1.__decorate([
|
|
|
124
131
|
tslib_1.__param(0, (0, common_1.Inject)(auth_constants_1.AUTH_MODULE_OPTIONS)),
|
|
125
132
|
tslib_1.__metadata("design:paramtypes", [Object, customer_center_service_1.CustomerCenterService])
|
|
126
133
|
], PrintClient);
|
|
134
|
+
function credentialsOf(args) {
|
|
135
|
+
return { tokenId: args.tokenId, tokenKey: args.tokenKey, product: args.product };
|
|
136
|
+
}
|
|
127
137
|
function toPrintClientError(error) {
|
|
128
138
|
if (!(error instanceof axios_1.AxiosError))
|
|
129
139
|
return error;
|
|
130
|
-
|
|
131
|
-
|
|
140
|
+
if (!error.response) {
|
|
141
|
+
const { status, message } = (0, axios_error_handler_1.describeTransportError)(error);
|
|
142
|
+
return new PrintClientError(undefined, message, status);
|
|
143
|
+
}
|
|
144
|
+
const status = error.response.status;
|
|
145
|
+
const body = error.response.data;
|
|
132
146
|
const code = typeof body?.code === 'string' ? body.code : undefined;
|
|
133
147
|
const message = Array.isArray(body?.message)
|
|
134
148
|
? body.message.join('; ')
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"print.client.js","sourceRoot":"","sources":["../../../../../libs/api-sdk/src/lib/print.client.ts"],"names":[],"mappings":";;;;;AAAA,oEAOoC;AACpC,2CAA+E;AAC/E,
|
|
1
|
+
{"version":3,"file":"print.client.js","sourceRoot":"","sources":["../../../../../libs/api-sdk/src/lib/print.client.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1,12 @@
|
|
|
1
|
+
import { AxiosError } from 'axios';
|
|
2
|
+
/**
|
|
3
|
+
* Status and message for an axios error without a response. The message stays
|
|
4
|
+
* generic: the original names internal hosts and ports.
|
|
5
|
+
*/
|
|
6
|
+
export declare function describeTransportError(error: AxiosError): {
|
|
7
|
+
status: number;
|
|
8
|
+
message: string;
|
|
9
|
+
};
|
|
1
10
|
export declare function handleAxiosError(error: unknown): never;
|
|
11
|
+
/** True for a 401 from the server, as axios error or already converted. */
|
|
12
|
+
export declare function isUnauthorizedError(error: unknown): boolean;
|
|
@@ -1,14 +1,35 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.describeTransportError = describeTransportError;
|
|
3
4
|
exports.handleAxiosError = handleAxiosError;
|
|
5
|
+
exports.isUnauthorizedError = isUnauthorizedError;
|
|
4
6
|
const common_1 = require("@nestjs/common");
|
|
5
7
|
const axios_1 = require("axios");
|
|
8
|
+
const TIMEOUT_CODES = new Set(['ECONNABORTED', 'ETIMEDOUT']);
|
|
9
|
+
/**
|
|
10
|
+
* Status and message for an axios error without a response. The message stays
|
|
11
|
+
* generic: the original names internal hosts and ports.
|
|
12
|
+
*/
|
|
13
|
+
function describeTransportError(error) {
|
|
14
|
+
return TIMEOUT_CODES.has(error.code ?? '')
|
|
15
|
+
? { status: common_1.HttpStatus.GATEWAY_TIMEOUT, message: 'Upstream request timed out' }
|
|
16
|
+
: { status: common_1.HttpStatus.BAD_GATEWAY, message: 'Upstream request failed' };
|
|
17
|
+
}
|
|
6
18
|
function handleAxiosError(error) {
|
|
7
19
|
if (error instanceof axios_1.AxiosError) {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
20
|
+
if (!error.response) {
|
|
21
|
+
const { status, message } = describeTransportError(error);
|
|
22
|
+
throw new common_1.HttpException(message, status);
|
|
23
|
+
}
|
|
24
|
+
const message = error.response.data?.message ?? error.message;
|
|
25
|
+
throw new common_1.HttpException(message, error.response.status);
|
|
11
26
|
}
|
|
12
27
|
throw error;
|
|
13
28
|
}
|
|
29
|
+
/** True for a 401 from the server, as axios error or already converted. */
|
|
30
|
+
function isUnauthorizedError(error) {
|
|
31
|
+
if (error instanceof axios_1.AxiosError)
|
|
32
|
+
return error.response?.status === common_1.HttpStatus.UNAUTHORIZED;
|
|
33
|
+
return error instanceof common_1.HttpException && error.getStatus() === common_1.HttpStatus.UNAUTHORIZED;
|
|
34
|
+
}
|
|
14
35
|
//# sourceMappingURL=axios-error.handler.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"axios-error.handler.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/utils/axios-error.handler.ts"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"axios-error.handler.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/utils/axios-error.handler.ts"],"names":[],"mappings":";;AASA,wDAIC;AAED,4CAUC;AAGD,kDAGC;AA/BD,2CAA2D;AAC3D,iCAAmC;AAEnC,MAAM,aAAa,GAAG,IAAI,GAAG,CAAC,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC,CAAC;AAE7D;;;GAGG;AACH,SAAgB,sBAAsB,CAAC,KAAiB;IACtD,OAAO,aAAa,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC;QACxC,CAAC,CAAC,EAAE,MAAM,EAAE,mBAAU,CAAC,eAAe,EAAE,OAAO,EAAE,4BAA4B,EAAE;QAC/E,CAAC,CAAC,EAAE,MAAM,EAAE,mBAAU,CAAC,WAAW,EAAE,OAAO,EAAE,yBAAyB,EAAE,CAAC;AAC7E,CAAC;AAED,SAAgB,gBAAgB,CAAC,KAAc;IAC7C,IAAI,KAAK,YAAY,kBAAU,EAAE,CAAC;QAChC,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,CAAC;YACpB,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,sBAAsB,CAAC,KAAK,CAAC,CAAC;YAC1D,MAAM,IAAI,sBAAa,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;QAC3C,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,OAAO,IAAI,KAAK,CAAC,OAAO,CAAC;QAC9D,MAAM,IAAI,sBAAa,CAAC,OAAO,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;IAC1D,CAAC;IACD,MAAM,KAAK,CAAC;AACd,CAAC;AAED,2EAA2E;AAC3E,SAAgB,mBAAmB,CAAC,KAAc;IAChD,IAAI,KAAK,YAAY,kBAAU;QAAE,OAAO,KAAK,CAAC,QAAQ,EAAE,MAAM,KAAK,mBAAU,CAAC,YAAY,CAAC;IAC3F,OAAO,KAAK,YAAY,sBAAa,IAAI,KAAK,CAAC,SAAS,EAAE,KAAK,mBAAU,CAAC,YAAY,CAAC;AACzF,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { AxiosInstance } from 'axios';
|
|
2
|
+
import { AuthModuleOptions } from '../models/auth.options';
|
|
3
|
+
export declare const DEFAULT_TIMEOUT_MS = 30000;
|
|
4
|
+
/**
|
|
5
|
+
* Axios instance of the SDK. Its own instance keeps interceptors of the
|
|
6
|
+
* consuming app, which might log or rewrite requests, away from calls that
|
|
7
|
+
* carry tokens.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createHttpClient(options: AuthModuleOptions): AxiosInstance;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DEFAULT_TIMEOUT_MS = void 0;
|
|
4
|
+
exports.createHttpClient = createHttpClient;
|
|
5
|
+
const axios_1 = require("axios");
|
|
6
|
+
exports.DEFAULT_TIMEOUT_MS = 30_000;
|
|
7
|
+
/**
|
|
8
|
+
* Axios instance of the SDK. Its own instance keeps interceptors of the
|
|
9
|
+
* consuming app, which might log or rewrite requests, away from calls that
|
|
10
|
+
* carry tokens.
|
|
11
|
+
*/
|
|
12
|
+
function createHttpClient(options) {
|
|
13
|
+
return axios_1.default.create({
|
|
14
|
+
baseURL: validateBaseUrl(options.baseUrl),
|
|
15
|
+
timeout: options.timeoutMs ?? exports.DEFAULT_TIMEOUT_MS,
|
|
16
|
+
headers: { accept: 'application/json' },
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function validateBaseUrl(baseUrl) {
|
|
20
|
+
let url;
|
|
21
|
+
try {
|
|
22
|
+
url = new URL(baseUrl ?? '');
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
throw new Error(`AuthModule: baseUrl "${baseUrl}" is not a valid URL`);
|
|
26
|
+
}
|
|
27
|
+
if (url.protocol !== 'https:' && url.protocol !== 'http:') {
|
|
28
|
+
throw new Error(`AuthModule: baseUrl must use http or https, got "${url.protocol}"`);
|
|
29
|
+
}
|
|
30
|
+
if (url.username || url.password) {
|
|
31
|
+
throw new Error('AuthModule: baseUrl must not contain credentials');
|
|
32
|
+
}
|
|
33
|
+
return baseUrl;
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=http-client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"http-client.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/utils/http-client.ts"],"names":[],"mappings":";;;AAWA,4CAMC;AAjBD,iCAA6C;AAIhC,QAAA,kBAAkB,GAAG,MAAM,CAAC;AAEzC;;;;GAIG;AACH,SAAgB,gBAAgB,CAAC,OAA0B;IACzD,OAAO,eAAK,CAAC,MAAM,CAAC;QAClB,OAAO,EAAE,eAAe,CAAC,OAAO,CAAC,OAAO,CAAC;QACzC,OAAO,EAAE,OAAO,CAAC,SAAS,IAAI,0BAAkB;QAChD,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;KACxC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,eAAe,CAAC,OAA2B;IAClD,IAAI,GAAQ,CAAC;IACb,IAAI,CAAC;QACH,GAAG,GAAG,IAAI,GAAG,CAAC,OAAO,IAAI,EAAE,CAAC,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,sBAAsB,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,OAAO,EAAE,CAAC;QAC1D,MAAM,IAAI,KAAK,CAAC,oDAAoD,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC;IACvF,CAAC;IACD,IAAI,GAAG,CAAC,QAAQ,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;QACjC,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Expiry of a JWT in epoch milliseconds, read from the `exp` claim without
|
|
3
|
+
* verifying the signature. Only use it to decide how long to cache a token,
|
|
4
|
+
* never to trust it. Undefined if the token is not a JWT or has no `exp`.
|
|
5
|
+
*/
|
|
6
|
+
export declare function getJwtExpiresAt(token: string): number | undefined;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getJwtExpiresAt = getJwtExpiresAt;
|
|
4
|
+
/**
|
|
5
|
+
* Expiry of a JWT in epoch milliseconds, read from the `exp` claim without
|
|
6
|
+
* verifying the signature. Only use it to decide how long to cache a token,
|
|
7
|
+
* never to trust it. Undefined if the token is not a JWT or has no `exp`.
|
|
8
|
+
*/
|
|
9
|
+
function getJwtExpiresAt(token) {
|
|
10
|
+
const payload = token.split('.')[1];
|
|
11
|
+
if (!payload)
|
|
12
|
+
return undefined;
|
|
13
|
+
try {
|
|
14
|
+
const { exp } = JSON.parse(Buffer.from(payload, 'base64url').toString('utf8'));
|
|
15
|
+
return typeof exp === 'number' && Number.isFinite(exp) ? exp * 1000 : undefined;
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return undefined;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=jwt.util.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"jwt.util.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/utils/jwt.util.ts"],"names":[],"mappings":";;AAKA,0CAWC;AAhBD;;;;GAIG;AACH,SAAgB,eAAe,CAAC,KAAa;IAC3C,MAAM,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,IAAI,CAAC,OAAO;QAAE,OAAO,SAAS,CAAC;IAC/B,IAAI,CAAC;QACH,MAAM,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,OAAO,EAAE,WAAW,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAE5E,CAAC;QACF,OAAO,OAAO,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC;IAClF,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export interface CacheLoadResult<T> {
|
|
2
|
+
value: T;
|
|
3
|
+
/** How long the value stays valid. `0` or less returns it without caching. */
|
|
4
|
+
ttlMs: number;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* In-memory cache with a lifetime per entry and a fixed maximum size; the
|
|
8
|
+
* least recently used entry goes first. Concurrent loads of the same key share
|
|
9
|
+
* one request. Failed loads are not cached.
|
|
10
|
+
*/
|
|
11
|
+
export declare class TtlCache<T> {
|
|
12
|
+
private readonly maxEntries;
|
|
13
|
+
private readonly entries;
|
|
14
|
+
private readonly pending;
|
|
15
|
+
constructor(maxEntries: number);
|
|
16
|
+
/** `fromCache` is false when this call ran `load` itself. */
|
|
17
|
+
getOrLoad(key: string, load: () => Promise<CacheLoadResult<T>>): Promise<{
|
|
18
|
+
value: T;
|
|
19
|
+
fromCache: boolean;
|
|
20
|
+
}>;
|
|
21
|
+
/** Removes the entry; with `value` only if it still holds that value. */
|
|
22
|
+
delete(key: string, value?: T): void;
|
|
23
|
+
clear(): void;
|
|
24
|
+
get size(): number;
|
|
25
|
+
private set;
|
|
26
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TtlCache = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* In-memory cache with a lifetime per entry and a fixed maximum size; the
|
|
6
|
+
* least recently used entry goes first. Concurrent loads of the same key share
|
|
7
|
+
* one request. Failed loads are not cached.
|
|
8
|
+
*/
|
|
9
|
+
class TtlCache {
|
|
10
|
+
maxEntries;
|
|
11
|
+
entries = new Map();
|
|
12
|
+
pending = new Map();
|
|
13
|
+
constructor(maxEntries) {
|
|
14
|
+
this.maxEntries = maxEntries;
|
|
15
|
+
}
|
|
16
|
+
/** `fromCache` is false when this call ran `load` itself. */
|
|
17
|
+
async getOrLoad(key, load) {
|
|
18
|
+
const entry = this.entries.get(key);
|
|
19
|
+
if (entry && entry.expiresAt > Date.now()) {
|
|
20
|
+
// Re-insert to mark the entry as recently used.
|
|
21
|
+
this.entries.delete(key);
|
|
22
|
+
this.entries.set(key, entry);
|
|
23
|
+
return { value: entry.value, fromCache: true };
|
|
24
|
+
}
|
|
25
|
+
if (entry)
|
|
26
|
+
this.entries.delete(key);
|
|
27
|
+
const running = this.pending.get(key);
|
|
28
|
+
if (running)
|
|
29
|
+
return { value: await running, fromCache: true };
|
|
30
|
+
const loading = load().then(({ value, ttlMs }) => {
|
|
31
|
+
if (ttlMs > 0 && this.pending.get(key) === loading)
|
|
32
|
+
this.set(key, value, ttlMs);
|
|
33
|
+
return value;
|
|
34
|
+
});
|
|
35
|
+
this.pending.set(key, loading);
|
|
36
|
+
try {
|
|
37
|
+
return { value: await loading, fromCache: false };
|
|
38
|
+
}
|
|
39
|
+
finally {
|
|
40
|
+
if (this.pending.get(key) === loading)
|
|
41
|
+
this.pending.delete(key);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/** Removes the entry; with `value` only if it still holds that value. */
|
|
45
|
+
delete(key, value) {
|
|
46
|
+
if (value === undefined || this.entries.get(key)?.value === value) {
|
|
47
|
+
this.entries.delete(key);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
clear() {
|
|
51
|
+
this.entries.clear();
|
|
52
|
+
this.pending.clear();
|
|
53
|
+
}
|
|
54
|
+
get size() {
|
|
55
|
+
return this.entries.size;
|
|
56
|
+
}
|
|
57
|
+
set(key, value, ttlMs) {
|
|
58
|
+
this.entries.delete(key);
|
|
59
|
+
this.entries.set(key, { value, expiresAt: Date.now() + ttlMs });
|
|
60
|
+
while (this.entries.size > this.maxEntries) {
|
|
61
|
+
this.entries.delete(this.entries.keys().next().value);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
exports.TtlCache = TtlCache;
|
|
66
|
+
//# sourceMappingURL=ttl-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ttl-cache.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/utils/ttl-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** True if the value can be used as a single URL path segment. */
|
|
2
|
+
export declare function isValidPathSegment(value: unknown): boolean;
|
|
3
|
+
/**
|
|
4
|
+
* Builds a request path and encodes every interpolated value as one path
|
|
5
|
+
* segment, so a value like `../x` or `a/b` cannot reach another endpoint.
|
|
6
|
+
*/
|
|
7
|
+
export declare function urlPath(strings: TemplateStringsArray, ...values: (string | number)[]): string;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isValidPathSegment = isValidPathSegment;
|
|
4
|
+
exports.urlPath = urlPath;
|
|
5
|
+
const common_1 = require("@nestjs/common");
|
|
6
|
+
/** True if the value can be used as a single URL path segment. */
|
|
7
|
+
function isValidPathSegment(value) {
|
|
8
|
+
if (typeof value !== 'string' && typeof value !== 'number')
|
|
9
|
+
return false;
|
|
10
|
+
const segment = String(value);
|
|
11
|
+
return segment.length > 0 && segment !== '.' && segment !== '..';
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Builds a request path and encodes every interpolated value as one path
|
|
15
|
+
* segment, so a value like `../x` or `a/b` cannot reach another endpoint.
|
|
16
|
+
*/
|
|
17
|
+
function urlPath(strings, ...values) {
|
|
18
|
+
return strings.reduce((path, part, i) => {
|
|
19
|
+
if (i >= values.length)
|
|
20
|
+
return path + part;
|
|
21
|
+
const value = values[i];
|
|
22
|
+
if (!isValidPathSegment(value)) {
|
|
23
|
+
throw new common_1.BadRequestException('Invalid path parameter');
|
|
24
|
+
}
|
|
25
|
+
return path + part + encodeURIComponent(String(value));
|
|
26
|
+
}, '');
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=url-path.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"url-path.js","sourceRoot":"","sources":["../../../../../../libs/api-sdk/src/lib/utils/url-path.ts"],"names":[],"mappings":";;AAGA,gDAIC;AAMD,0BASC;AAtBD,2CAAqD;AAErD,kEAAkE;AAClE,SAAgB,kBAAkB,CAAC,KAAc;IAC/C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAAK,CAAC;IACzE,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,OAAO,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,KAAK,GAAG,IAAI,OAAO,KAAK,IAAI,CAAC;AACnE,CAAC;AAED;;;GAGG;AACH,SAAgB,OAAO,CAAC,OAA6B,EAAE,GAAG,MAA2B;IACnF,OAAO,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,EAAE,EAAE;QACtC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM;YAAE,OAAO,IAAI,GAAG,IAAI,CAAC;QAC3C,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,IAAI,CAAC,kBAAkB,CAAC,KAAK,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,4BAAmB,CAAC,wBAAwB,CAAC,CAAC;QAC1D,CAAC;QACD,OAAO,IAAI,GAAG,IAAI,GAAG,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACzD,CAAC,EAAE,EAAE,CAAC,CAAC;AACT,CAAC"}
|