@ah-oh/ao-workspaces-api-sdk 1.0.22 → 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 +24 -0
- package/README.md +91 -3
- package/package.json +2 -2
- package/src/index.d.ts +1 -0
- package/src/index.js +1 -0
- package/src/index.js.map +1 -1
- package/src/lib/auth.module.js +15 -22
- 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 +76 -0
- package/src/lib/print.client.js +154 -0
- package/src/lib/print.client.js.map +1 -0
- 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
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var PrintClient_1;
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.PrintClient = exports.PrintClientError = void 0;
|
|
5
|
+
const tslib_1 = require("tslib");
|
|
6
|
+
const ao_workspaces_types_1 = require("@ah-oh/ao-workspaces-types");
|
|
7
|
+
const common_1 = require("@nestjs/common");
|
|
8
|
+
const axios_1 = require("axios");
|
|
9
|
+
const auth_constants_1 = require("./auth.constants");
|
|
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");
|
|
14
|
+
/**
|
|
15
|
+
* Error of the hardware API. `code` is the machine-readable code of the body
|
|
16
|
+
* `{ type: 'error', code, message }` (e.g. `target_unassigned`,
|
|
17
|
+
* `target_not_found`, `option_not_allowed`, `content_too_large`). It is
|
|
18
|
+
* undefined for errors without such a body (validation, network).
|
|
19
|
+
*/
|
|
20
|
+
class PrintClientError extends common_1.HttpException {
|
|
21
|
+
code;
|
|
22
|
+
constructor(code, message, status) {
|
|
23
|
+
super({ type: 'error', code, message }, status);
|
|
24
|
+
this.code = code;
|
|
25
|
+
this.name = 'PrintClientError';
|
|
26
|
+
this.message = message;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
exports.PrintClientError = PrintClientError;
|
|
30
|
+
const CONTENT_MIME_TYPES = {
|
|
31
|
+
[ao_workspaces_types_1.PrintContentType.PDF]: 'application/pdf',
|
|
32
|
+
[ao_workspaces_types_1.PrintContentType.ZPL]: 'application/octet-stream',
|
|
33
|
+
};
|
|
34
|
+
const DEFAULT_WAIT_TIMEOUT_MS = 60_000;
|
|
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;
|
|
40
|
+
/** Creates print jobs on the hardware connector API and reads their state (HC-12). */
|
|
41
|
+
let PrintClient = PrintClient_1 = class PrintClient {
|
|
42
|
+
customerCenterService;
|
|
43
|
+
http;
|
|
44
|
+
uploadTimeoutMs;
|
|
45
|
+
constructor(options, customerCenterService) {
|
|
46
|
+
this.customerCenterService = customerCenterService;
|
|
47
|
+
this.http = (0, http_client_1.createHttpClient)(options);
|
|
48
|
+
this.uploadTimeoutMs = Math.max(this.http.defaults.timeout ?? 0, MIN_UPLOAD_TIMEOUT_MS);
|
|
49
|
+
}
|
|
50
|
+
/** True once the job will not change anymore (completed, failed, expired, canceled). */
|
|
51
|
+
static isFinal(job) {
|
|
52
|
+
return ao_workspaces_types_1.FINAL_PRINT_JOB_STATES.includes(job.state);
|
|
53
|
+
}
|
|
54
|
+
/** Creates a print job on a print target. Resolves as soon as the job is queued. */
|
|
55
|
+
async print(args) {
|
|
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
|
+
}
|
|
59
|
+
const form = new FormData();
|
|
60
|
+
form.append('target', args.target);
|
|
61
|
+
form.append('contentType', args.contentType);
|
|
62
|
+
if (args.copies !== undefined)
|
|
63
|
+
form.append('copies', String(args.copies));
|
|
64
|
+
if (args.paperSize)
|
|
65
|
+
form.append('paperSize', args.paperSize);
|
|
66
|
+
if (args.color)
|
|
67
|
+
form.append('color', args.color);
|
|
68
|
+
if (args.idempotencyKey)
|
|
69
|
+
form.append('idempotencyKey', args.idempotencyKey);
|
|
70
|
+
if (args.expiresInSeconds !== undefined)
|
|
71
|
+
form.append('expiresInSeconds', String(args.expiresInSeconds));
|
|
72
|
+
form.append('content', new Blob([args.content], {
|
|
73
|
+
type: CONTENT_MIME_TYPES[args.contentType],
|
|
74
|
+
}), args.fileName ?? `content.${args.contentType}`);
|
|
75
|
+
return this.request(args, {
|
|
76
|
+
method: 'POST',
|
|
77
|
+
url: (0, url_path_1.urlPath) `/auth-api/companies/${args.companyId}/hardware/print-jobs`,
|
|
78
|
+
data: form,
|
|
79
|
+
maxBodyLength: MAX_CONTENT_BYTES + 1024 * 1024,
|
|
80
|
+
timeout: this.uploadTimeoutMs,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
async getJob(args) {
|
|
84
|
+
return this.customerCenterService.withToken(credentialsOf(args), authorization => this.fetchJob(args, authorization));
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Polls the job until it reaches a final state or `timeoutMs` has passed.
|
|
88
|
+
* On timeout the last known (non-final) job is returned; check it with
|
|
89
|
+
* `PrintClient.isFinal`. A job for an offline connector stays `queued` until
|
|
90
|
+
* it expires.
|
|
91
|
+
*/
|
|
92
|
+
async waitForJob(args) {
|
|
93
|
+
const timeoutMs = args.timeoutMs ?? DEFAULT_WAIT_TIMEOUT_MS;
|
|
94
|
+
const intervalMs = args.intervalMs ?? DEFAULT_WAIT_INTERVAL_MS;
|
|
95
|
+
const deadline = Date.now() + timeoutMs;
|
|
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
|
+
});
|
|
104
|
+
}
|
|
105
|
+
fetchJob(args, authorization) {
|
|
106
|
+
return this.send(authorization, {
|
|
107
|
+
method: 'GET',
|
|
108
|
+
url: (0, url_path_1.urlPath) `/auth-api/companies/${args.companyId}/hardware/print-jobs/${args.jobId}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
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));
|
|
114
|
+
}
|
|
115
|
+
async send(authorization, config) {
|
|
116
|
+
try {
|
|
117
|
+
const res = await this.http.request({
|
|
118
|
+
...config,
|
|
119
|
+
headers: { ...config.headers, authorization },
|
|
120
|
+
});
|
|
121
|
+
return res.data;
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
throw toPrintClientError(error);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
exports.PrintClient = PrintClient;
|
|
129
|
+
exports.PrintClient = PrintClient = PrintClient_1 = tslib_1.__decorate([
|
|
130
|
+
(0, common_1.Injectable)(),
|
|
131
|
+
tslib_1.__param(0, (0, common_1.Inject)(auth_constants_1.AUTH_MODULE_OPTIONS)),
|
|
132
|
+
tslib_1.__metadata("design:paramtypes", [Object, customer_center_service_1.CustomerCenterService])
|
|
133
|
+
], PrintClient);
|
|
134
|
+
function credentialsOf(args) {
|
|
135
|
+
return { tokenId: args.tokenId, tokenKey: args.tokenKey, product: args.product };
|
|
136
|
+
}
|
|
137
|
+
function toPrintClientError(error) {
|
|
138
|
+
if (!(error instanceof axios_1.AxiosError))
|
|
139
|
+
return error;
|
|
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;
|
|
146
|
+
const code = typeof body?.code === 'string' ? body.code : undefined;
|
|
147
|
+
const message = Array.isArray(body?.message)
|
|
148
|
+
? body.message.join('; ')
|
|
149
|
+
: typeof body?.message === 'string'
|
|
150
|
+
? body.message
|
|
151
|
+
: error.message;
|
|
152
|
+
return new PrintClientError(code, message, status);
|
|
153
|
+
}
|
|
154
|
+
//# sourceMappingURL=print.client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
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"}
|