@openstax/ts-utils 1.27.6 → 1.29.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/cjs/errors/index.d.ts +11 -0
- package/dist/cjs/errors/index.js +15 -1
- package/dist/cjs/fetch/fetchStatusRetry.d.ts +1 -0
- package/dist/cjs/fetch/fetchStatusRetry.js +18 -7
- package/dist/cjs/guards/index.d.ts +8 -0
- package/dist/cjs/guards/index.js +10 -1
- package/dist/cjs/services/documentStore/unversioned/dynamodb.d.ts +9 -0
- package/dist/cjs/services/documentStore/unversioned/dynamodb.js +67 -0
- package/dist/cjs/services/documentStore/unversioned/file-system.d.ts +12 -1
- package/dist/cjs/services/documentStore/unversioned/file-system.js +49 -1
- package/dist/cjs/services/launchParams/verifier.d.ts +2 -0
- package/dist/cjs/services/launchParams/verifier.js +12 -4
- package/dist/cjs/services/searchProvider/openSearch.js +3 -0
- package/dist/cjs/tsconfig.without-specs.cjs.tsbuildinfo +1 -1
- package/dist/esm/errors/index.d.ts +11 -0
- package/dist/esm/errors/index.js +13 -0
- package/dist/esm/fetch/fetchStatusRetry.d.ts +1 -0
- package/dist/esm/fetch/fetchStatusRetry.js +18 -7
- package/dist/esm/guards/index.d.ts +8 -0
- package/dist/esm/guards/index.js +8 -0
- package/dist/esm/services/documentStore/unversioned/dynamodb.d.ts +9 -0
- package/dist/esm/services/documentStore/unversioned/dynamodb.js +65 -1
- package/dist/esm/services/documentStore/unversioned/file-system.d.ts +12 -1
- package/dist/esm/services/documentStore/unversioned/file-system.js +50 -2
- package/dist/esm/services/launchParams/verifier.d.ts +2 -0
- package/dist/esm/services/launchParams/verifier.js +12 -4
- package/dist/esm/services/searchProvider/openSearch.js +3 -0
- package/dist/esm/tsconfig.without-specs.esm.tsbuildinfo +1 -1
- package/package.json +3 -1
|
@@ -75,3 +75,14 @@ export declare class SessionExpiredError extends Error {
|
|
|
75
75
|
static matches: (e: any) => e is typeof SessionExpiredError;
|
|
76
76
|
constructor(message?: string);
|
|
77
77
|
}
|
|
78
|
+
/**
|
|
79
|
+
* Conflict error
|
|
80
|
+
*
|
|
81
|
+
* `ConflictError.matches(error)` is a reliable way to check if an error is a
|
|
82
|
+
* `ConflictError`; `instanceof` checks may not work if code is split into multiple bundles
|
|
83
|
+
*/
|
|
84
|
+
export declare class ConflictError extends Error {
|
|
85
|
+
static readonly TYPE = "ConflictError";
|
|
86
|
+
static matches: (e: any) => e is typeof ConflictError;
|
|
87
|
+
constructor(message?: string);
|
|
88
|
+
}
|
package/dist/cjs/errors/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.SessionExpiredError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.ValidationError = exports.InvalidRequestError = exports.isAppError = void 0;
|
|
3
|
+
exports.ConflictError = exports.SessionExpiredError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.ValidationError = exports.InvalidRequestError = exports.isAppError = void 0;
|
|
4
4
|
/*
|
|
5
5
|
* if code is split into multiple bundles, sometimes each bundle
|
|
6
6
|
* will get its own definition of this module and then instanceof checks
|
|
@@ -107,3 +107,17 @@ class SessionExpiredError extends Error {
|
|
|
107
107
|
exports.SessionExpiredError = SessionExpiredError;
|
|
108
108
|
SessionExpiredError.TYPE = 'SessionExpiredError';
|
|
109
109
|
SessionExpiredError.matches = errorIsType(SessionExpiredError);
|
|
110
|
+
/**
|
|
111
|
+
* Conflict error
|
|
112
|
+
*
|
|
113
|
+
* `ConflictError.matches(error)` is a reliable way to check if an error is a
|
|
114
|
+
* `ConflictError`; `instanceof` checks may not work if code is split into multiple bundles
|
|
115
|
+
*/
|
|
116
|
+
class ConflictError extends Error {
|
|
117
|
+
constructor(message) {
|
|
118
|
+
super(message || ConflictError.TYPE);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
exports.ConflictError = ConflictError;
|
|
122
|
+
ConflictError.TYPE = 'ConflictError';
|
|
123
|
+
ConflictError.matches = errorIsType(ConflictError);
|
|
@@ -2,6 +2,7 @@ import { RetryOptions } from '../misc/helpers';
|
|
|
2
2
|
import { GenericFetch } from '.';
|
|
3
3
|
interface Options extends RetryOptions {
|
|
4
4
|
status?: number[];
|
|
5
|
+
timeout?: number;
|
|
5
6
|
}
|
|
6
7
|
export declare const fetchStatusRetry: (base: GenericFetch, options: Options) => GenericFetch;
|
|
7
8
|
export {};
|
|
@@ -3,14 +3,25 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.fetchStatusRetry = void 0;
|
|
4
4
|
const helpers_1 = require("../misc/helpers");
|
|
5
5
|
const fetchStatusRetry = (base, options) => {
|
|
6
|
-
return (...params) => (0, helpers_1.retryWithDelay)(() =>
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
return (...params) => (0, helpers_1.retryWithDelay)(() => {
|
|
7
|
+
const fetchPromise = base(...params).then(r => {
|
|
8
|
+
var _a;
|
|
9
|
+
if ((_a = options.status) === null || _a === void 0 ? void 0 : _a.includes(r.status)) {
|
|
10
|
+
return r.text().then(text => {
|
|
11
|
+
throw new Error(`fetch failed ${params[0]} -- ${r.status}: ${text}`);
|
|
12
|
+
});
|
|
13
|
+
}
|
|
14
|
+
return r;
|
|
15
|
+
});
|
|
16
|
+
if (options.timeout) {
|
|
17
|
+
const timeoutPromise = new Promise((_, reject) => {
|
|
18
|
+
setTimeout(() => {
|
|
19
|
+
reject(new Error(`fetch timeout after ${options.timeout}ms: ${params[0]}`));
|
|
20
|
+
}, options.timeout);
|
|
11
21
|
});
|
|
22
|
+
return Promise.race([fetchPromise, timeoutPromise]);
|
|
12
23
|
}
|
|
13
|
-
return
|
|
14
|
-
}
|
|
24
|
+
return fetchPromise;
|
|
25
|
+
}, options);
|
|
15
26
|
};
|
|
16
27
|
exports.fetchStatusRetry = fetchStatusRetry;
|
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
* `const result = (array as Array<string | undefined>).filter(isDefined);`
|
|
7
7
|
*/
|
|
8
8
|
export declare const isDefined: <X>(x: X) => x is Exclude<X, undefined>;
|
|
9
|
+
/**
|
|
10
|
+
* checks if a thing is not null. while often easy to do with a simple if statement,
|
|
11
|
+
* in certain situations the guard is required and its nice to have one pre-defined.
|
|
12
|
+
* E.g. in the following example, the result is `Array<string>`.
|
|
13
|
+
*
|
|
14
|
+
* `const result = (array as Array<string | null>).filter(isNotNull);`
|
|
15
|
+
*/
|
|
16
|
+
export declare const isNotNull: <X>(x: X) => x is Exclude<X, null>;
|
|
9
17
|
/**
|
|
10
18
|
* checks if a thing is a number. while often easy to do with a simple if statement, in certain
|
|
11
19
|
* situations the guard is required and its nice to have one pre-defined. E.g. in the following
|
package/dist/cjs/guards/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ifDefined = exports.isPlainObject = exports.isNumber = exports.isDefined = void 0;
|
|
3
|
+
exports.ifDefined = exports.isPlainObject = exports.isNumber = exports.isNotNull = exports.isDefined = void 0;
|
|
4
4
|
/**
|
|
5
5
|
* checks if a thing is defined. while often easy to do with a simple if statement, in certain
|
|
6
6
|
* situations the guard is required and its nice to have one pre-defined. E.g. in the following
|
|
@@ -10,6 +10,15 @@ exports.ifDefined = exports.isPlainObject = exports.isNumber = exports.isDefined
|
|
|
10
10
|
*/
|
|
11
11
|
const isDefined = (x) => x !== undefined;
|
|
12
12
|
exports.isDefined = isDefined;
|
|
13
|
+
/**
|
|
14
|
+
* checks if a thing is not null. while often easy to do with a simple if statement,
|
|
15
|
+
* in certain situations the guard is required and its nice to have one pre-defined.
|
|
16
|
+
* E.g. in the following example, the result is `Array<string>`.
|
|
17
|
+
*
|
|
18
|
+
* `const result = (array as Array<string | null>).filter(isNotNull);`
|
|
19
|
+
*/
|
|
20
|
+
const isNotNull = (x) => x !== null;
|
|
21
|
+
exports.isNotNull = isNotNull;
|
|
13
22
|
/**
|
|
14
23
|
* checks if a thing is a number. while often easy to do with a simple if statement, in certain
|
|
15
24
|
* situations the guard is required and its nice to have one pre-defined. E.g. in the following
|
|
@@ -9,6 +9,7 @@ export declare const dynamoUnversionedDocumentStore: <C extends string = "dynamo
|
|
|
9
9
|
tableName: import("../../../config").ConfigValueProvider<string>;
|
|
10
10
|
}; }) => <K extends keyof T>(_: {}, hashKey: K, options?: {
|
|
11
11
|
afterWrite?: ((item: T) => void | Promise<void>) | undefined;
|
|
12
|
+
batchAfterWrite?: ((items: T[]) => void | Promise<void>) | undefined;
|
|
12
13
|
} | undefined) => {
|
|
13
14
|
loadAllDocumentsTheBadWay: () => Promise<T[]>;
|
|
14
15
|
getItemsByField: (key: keyof T, value: T[K], pageKey?: string | undefined) => Promise<{
|
|
@@ -20,5 +21,13 @@ export declare const dynamoUnversionedDocumentStore: <C extends string = "dynamo
|
|
|
20
21
|
incrementItemAttribute: (id: T[K], attribute: keyof T) => Promise<number>;
|
|
21
22
|
patchItem: (item: Partial<T>) => Promise<T>;
|
|
22
23
|
putItem: (item: T) => Promise<T>;
|
|
24
|
+
createItem: (item: T) => Promise<T>;
|
|
25
|
+
batchCreateItem: (items: T[], concurrency?: number) => Promise<{
|
|
26
|
+
successful: T[];
|
|
27
|
+
failed: {
|
|
28
|
+
item: T;
|
|
29
|
+
error: Error;
|
|
30
|
+
}[];
|
|
31
|
+
}>;
|
|
23
32
|
};
|
|
24
33
|
export {};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
2
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
6
|
exports.dynamoUnversionedDocumentStore = void 0;
|
|
4
7
|
const client_dynamodb_1 = require("@aws-sdk/client-dynamodb");
|
|
8
|
+
const tiny_async_pool_1 = __importDefault(require("tiny-async-pool"));
|
|
5
9
|
const __1 = require("../../..");
|
|
6
10
|
const config_1 = require("../../../config");
|
|
7
11
|
const errors_1 = require("../../../errors");
|
|
@@ -160,6 +164,69 @@ const dynamoUnversionedDocumentStore = (initializer) => {
|
|
|
160
164
|
await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, updatedDoc));
|
|
161
165
|
return updatedDoc;
|
|
162
166
|
},
|
|
167
|
+
/* creates a new document, fails if the primary key already exists */
|
|
168
|
+
createItem: async (item) => {
|
|
169
|
+
const cmd = new client_dynamodb_1.PutItemCommand({
|
|
170
|
+
TableName: await tableName(),
|
|
171
|
+
Item: (0, dynamoEncoding_1.encodeDynamoDocument)(item),
|
|
172
|
+
ConditionExpression: 'attribute_not_exists(#k)',
|
|
173
|
+
ExpressionAttributeNames: {
|
|
174
|
+
'#k': hashKey.toString(),
|
|
175
|
+
},
|
|
176
|
+
});
|
|
177
|
+
return await dynamodb().send(cmd).then(() => item).catch((error) => {
|
|
178
|
+
throw error.name === 'ConditionalCheckFailedException' ?
|
|
179
|
+
new errors_1.ConflictError(`Item with ${String(hashKey)} "${item[hashKey]}" already exists`) : error;
|
|
180
|
+
}).then(async (createdDoc) => {
|
|
181
|
+
var _a;
|
|
182
|
+
await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, createdDoc));
|
|
183
|
+
return createdDoc;
|
|
184
|
+
});
|
|
185
|
+
},
|
|
186
|
+
/* creates multiple new documents, returns successful and failed items separately */
|
|
187
|
+
batchCreateItem: async (items, concurrency = 10) => {
|
|
188
|
+
if (items.length === 0)
|
|
189
|
+
return { successful: [], failed: [] };
|
|
190
|
+
const successful = [];
|
|
191
|
+
const failed = [];
|
|
192
|
+
// Process using async iterator (tiny-async-pool v2)
|
|
193
|
+
for await (const result of (0, tiny_async_pool_1.default)(concurrency, items, async (item) => {
|
|
194
|
+
var _a;
|
|
195
|
+
try {
|
|
196
|
+
const cmd = new client_dynamodb_1.PutItemCommand({
|
|
197
|
+
TableName: await tableName(),
|
|
198
|
+
Item: (0, dynamoEncoding_1.encodeDynamoDocument)(item),
|
|
199
|
+
ConditionExpression: 'attribute_not_exists(#k)',
|
|
200
|
+
ExpressionAttributeNames: {
|
|
201
|
+
'#k': hashKey.toString(),
|
|
202
|
+
},
|
|
203
|
+
});
|
|
204
|
+
await dynamodb().send(cmd);
|
|
205
|
+
// Only call individual afterWrite if batchAfterWrite is not defined
|
|
206
|
+
if (!(options === null || options === void 0 ? void 0 : options.batchAfterWrite)) {
|
|
207
|
+
await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, item));
|
|
208
|
+
}
|
|
209
|
+
return { success: true, item };
|
|
210
|
+
}
|
|
211
|
+
catch (error) {
|
|
212
|
+
const processedError = error.name === 'ConditionalCheckFailedException' ?
|
|
213
|
+
new errors_1.ConflictError(`Item with ${String(hashKey)} "${item[hashKey]}" already exists`) : error;
|
|
214
|
+
return { success: false, item, error: processedError };
|
|
215
|
+
}
|
|
216
|
+
})) {
|
|
217
|
+
if (result.success) {
|
|
218
|
+
successful.push(result.item);
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
failed.push({ item: result.item, error: result.error });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
// Call batchAfterWrite with all successful items if defined
|
|
225
|
+
if ((options === null || options === void 0 ? void 0 : options.batchAfterWrite) && successful.length > 0) {
|
|
226
|
+
await options.batchAfterWrite(successful);
|
|
227
|
+
}
|
|
228
|
+
return { successful, failed };
|
|
229
|
+
},
|
|
163
230
|
};
|
|
164
231
|
};
|
|
165
232
|
};
|
|
@@ -7,7 +7,10 @@ interface Initializer<C> {
|
|
|
7
7
|
}
|
|
8
8
|
export declare const fileSystemUnversionedDocumentStore: <C extends string = "fileSystem">(initializer: Initializer<C>) => <T extends TDocument<T>>() => (configProvider: { [key in C]: {
|
|
9
9
|
tableName: import("../../../config").ConfigValueProvider<string>;
|
|
10
|
-
}; }) => <K extends keyof T>(_: {}, hashKey: K
|
|
10
|
+
}; }) => <K extends keyof T>(_: {}, hashKey: K, options?: {
|
|
11
|
+
afterWrite?: ((item: T) => void | Promise<void>) | undefined;
|
|
12
|
+
batchAfterWrite?: ((items: T[]) => void | Promise<void>) | undefined;
|
|
13
|
+
} | undefined) => {
|
|
11
14
|
loadAllDocumentsTheBadWay: () => Promise<T[]>;
|
|
12
15
|
getItemsByField: (key: keyof T, value: T[K], pageKey?: string | undefined) => Promise<{
|
|
13
16
|
items: T[];
|
|
@@ -18,5 +21,13 @@ export declare const fileSystemUnversionedDocumentStore: <C extends string = "fi
|
|
|
18
21
|
incrementItemAttribute: (id: T[K], attribute: keyof T) => Promise<number>;
|
|
19
22
|
patchItem: (item: Partial<T>) => Promise<T>;
|
|
20
23
|
putItem: (item: T) => Promise<T>;
|
|
24
|
+
createItem: (item: T) => Promise<T>;
|
|
25
|
+
batchCreateItem: (items: T[], _concurrency?: number) => Promise<{
|
|
26
|
+
successful: T[];
|
|
27
|
+
failed: {
|
|
28
|
+
item: T;
|
|
29
|
+
error: Error;
|
|
30
|
+
}[];
|
|
31
|
+
}>;
|
|
21
32
|
};
|
|
22
33
|
export {};
|
|
@@ -33,7 +33,7 @@ const __1 = require("../../..");
|
|
|
33
33
|
const config_1 = require("../../../config");
|
|
34
34
|
const errors_1 = require("../../../errors");
|
|
35
35
|
const guards_1 = require("../../../guards");
|
|
36
|
-
const fileSystemUnversionedDocumentStore = (initializer) => () => (configProvider) => (_, hashKey) => {
|
|
36
|
+
const fileSystemUnversionedDocumentStore = (initializer) => () => (configProvider) => (_, hashKey, options) => {
|
|
37
37
|
const tableName = (0, config_1.resolveConfigValue)(configProvider[initializer.configSpace || 'fileSystem'].tableName);
|
|
38
38
|
const tablePath = tableName.then((table) => path_1.default.join(initializer.dataDir, table));
|
|
39
39
|
const { mkdir, readdir, readFile, writeFile } = (0, guards_1.ifDefined)(initializer.fs, fsModule);
|
|
@@ -128,6 +128,54 @@ const fileSystemUnversionedDocumentStore = (initializer) => () => (configProvide
|
|
|
128
128
|
writeFile(path, JSON.stringify(item, null, 2), (err) => err ? reject(err) : resolve(item));
|
|
129
129
|
});
|
|
130
130
|
},
|
|
131
|
+
createItem: async (item) => {
|
|
132
|
+
const hashed = hashFilename(item[hashKey]);
|
|
133
|
+
const existingItem = await load(hashed);
|
|
134
|
+
if (existingItem) {
|
|
135
|
+
throw new errors_1.ConflictError(`Item with ${String(hashKey)} "${item[hashKey]}" already exists`);
|
|
136
|
+
}
|
|
137
|
+
const path = await filePath(hashed);
|
|
138
|
+
await mkTableDir;
|
|
139
|
+
return new Promise((resolve, reject) => {
|
|
140
|
+
writeFile(path, JSON.stringify(item, null, 2), (err) => err ? reject(err) : resolve(item));
|
|
141
|
+
});
|
|
142
|
+
},
|
|
143
|
+
batchCreateItem: async (items, _concurrency = 1) => {
|
|
144
|
+
var _a;
|
|
145
|
+
if (items.length === 0)
|
|
146
|
+
return { successful: [], failed: [] };
|
|
147
|
+
const successful = [];
|
|
148
|
+
const failed = [];
|
|
149
|
+
// Process items sequentially to ensure consistent conflict detection
|
|
150
|
+
// Note: concurrency parameter is ignored for filesystem to avoid race conditions
|
|
151
|
+
for (const item of items) {
|
|
152
|
+
try {
|
|
153
|
+
const hashed = hashFilename(item[hashKey]);
|
|
154
|
+
const existingItem = await load(hashed);
|
|
155
|
+
if (existingItem) {
|
|
156
|
+
throw new errors_1.ConflictError(`Item with ${String(hashKey)} "${item[hashKey]}" already exists`);
|
|
157
|
+
}
|
|
158
|
+
const path = await filePath(hashed);
|
|
159
|
+
await mkTableDir;
|
|
160
|
+
const createdItem = await new Promise((resolve, reject) => {
|
|
161
|
+
writeFile(path, JSON.stringify(item, null, 2), (err) => err ? reject(err) : resolve(item));
|
|
162
|
+
});
|
|
163
|
+
successful.push(createdItem);
|
|
164
|
+
// Only call individual afterWrite if batchAfterWrite is not defined
|
|
165
|
+
if (!(options === null || options === void 0 ? void 0 : options.batchAfterWrite)) {
|
|
166
|
+
await ((_a = options === null || options === void 0 ? void 0 : options.afterWrite) === null || _a === void 0 ? void 0 : _a.call(options, createdItem));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch (error) {
|
|
170
|
+
failed.push({ item, error: error });
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
// Call batchAfterWrite with all successful items if defined
|
|
174
|
+
if ((options === null || options === void 0 ? void 0 : options.batchAfterWrite) && successful.length > 0) {
|
|
175
|
+
await options.batchAfterWrite(successful);
|
|
176
|
+
}
|
|
177
|
+
return { successful, failed };
|
|
178
|
+
},
|
|
131
179
|
};
|
|
132
180
|
};
|
|
133
181
|
exports.fileSystemUnversionedDocumentStore = fileSystemUnversionedDocumentStore;
|
|
@@ -3,6 +3,7 @@ import type { JWK } from 'node-jose';
|
|
|
3
3
|
import { ConfigProviderForConfig } from '../../config';
|
|
4
4
|
declare type Config = {
|
|
5
5
|
trustedDomain: string;
|
|
6
|
+
bypassSignatureVerification: string;
|
|
6
7
|
};
|
|
7
8
|
interface Initializer<C> {
|
|
8
9
|
configSpace?: C;
|
|
@@ -15,6 +16,7 @@ interface Initializer<C> {
|
|
|
15
16
|
*/
|
|
16
17
|
export declare const createLaunchVerifier: <C extends string = "launch">({ configSpace, fetcher }: Initializer<C>) => (configProvider: { [key in C]: {
|
|
17
18
|
trustedDomain: import("../../config").ConfigValueProvider<string>;
|
|
19
|
+
bypassSignatureVerification: import("../../config").ConfigValueProvider<string>;
|
|
18
20
|
}; }) => (_services: {}, getDefaultToken?: (() => string) | undefined) => {
|
|
19
21
|
verify: <T = undefined>(...args: T extends undefined ? [] | [string] : [(input: any) => T] | [string, (input: any) => T]) => Promise<T extends undefined ? jwt.JwtPayload : T>;
|
|
20
22
|
};
|
|
@@ -37,6 +37,7 @@ const helpers_1 = require("../../misc/helpers");
|
|
|
37
37
|
const createLaunchVerifier = ({ configSpace, fetcher }) => (configProvider) => {
|
|
38
38
|
const config = configProvider[(0, guards_1.ifDefined)(configSpace, 'launch')];
|
|
39
39
|
const getTrustedDomain = (0, helpers_1.once)(() => (0, config_1.resolveConfigValue)(config.trustedDomain));
|
|
40
|
+
const getBypassSignatureVerification = (0, helpers_1.once)(async () => (await (0, config_1.resolveConfigValue)(config.bypassSignatureVerification)) === 'true');
|
|
40
41
|
const getJwksClient = (0, __1.memoize)((jwksUri) => new jwks_rsa_1.JwksClient({ fetcher, jwksUri }));
|
|
41
42
|
const getJwksKey = (0, __1.memoize)(async (jwksUri, kid) => {
|
|
42
43
|
const client = getJwksClient(jwksUri);
|
|
@@ -63,25 +64,26 @@ const createLaunchVerifier = ({ configSpace, fetcher }) => (configProvider) => {
|
|
|
63
64
|
}
|
|
64
65
|
};
|
|
65
66
|
return (_services, getDefaultToken) => {
|
|
66
|
-
const verify = (...args) => {
|
|
67
|
+
const verify = async (...args) => {
|
|
67
68
|
const [inputToken, validator] = args.length === 1
|
|
68
69
|
? typeof args[0] === 'string'
|
|
69
70
|
? [args[0], undefined]
|
|
70
71
|
: [undefined, args[0]]
|
|
71
72
|
: args;
|
|
73
|
+
const bypassSignatureVerification = await getBypassSignatureVerification();
|
|
72
74
|
return new Promise((resolve, reject) => {
|
|
73
75
|
const token = inputToken !== null && inputToken !== void 0 ? inputToken : getDefaultToken === null || getDefaultToken === void 0 ? void 0 : getDefaultToken();
|
|
74
76
|
if (!token) {
|
|
75
77
|
return reject(new errors_1.InvalidRequestError('Missing token for launch verification'));
|
|
76
78
|
}
|
|
77
|
-
|
|
79
|
+
const resolvePayload = (err, payload) => {
|
|
78
80
|
if (err && err instanceof jsonwebtoken_1.TokenExpiredError) {
|
|
79
81
|
reject(new errors_1.SessionExpiredError());
|
|
80
82
|
}
|
|
81
83
|
else if (err) {
|
|
82
84
|
reject(err);
|
|
83
85
|
}
|
|
84
|
-
else if (typeof payload !== 'object') {
|
|
86
|
+
else if (typeof payload !== 'object' || payload === null) {
|
|
85
87
|
reject(new Error('received JWT token with unexpected non-JSON payload'));
|
|
86
88
|
}
|
|
87
89
|
else if (!payload.sub) {
|
|
@@ -102,7 +104,13 @@ const createLaunchVerifier = ({ configSpace, fetcher }) => (configProvider) => {
|
|
|
102
104
|
// conditional return types are annoying
|
|
103
105
|
resolve((validator ? validator(parsed) : parsed));
|
|
104
106
|
}
|
|
105
|
-
}
|
|
107
|
+
};
|
|
108
|
+
if (bypassSignatureVerification) {
|
|
109
|
+
return resolvePayload(null, jsonwebtoken_1.default.decode(token));
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
return jsonwebtoken_1.default.verify(token, getKey, {}, resolvePayload);
|
|
113
|
+
}
|
|
106
114
|
});
|
|
107
115
|
};
|
|
108
116
|
return { verify };
|
|
@@ -26,6 +26,9 @@ const openSearchService = (initializer = {}) => (configProvider) => {
|
|
|
26
26
|
region: await (0, config_1.resolveConfigValue)(config.region),
|
|
27
27
|
service: 'es',
|
|
28
28
|
}),
|
|
29
|
+
maxRetries: 3,
|
|
30
|
+
requestTimeout: 3000,
|
|
31
|
+
pingTimeout: 1000,
|
|
29
32
|
node: await (0, config_1.resolveConfigValue)(config.node),
|
|
30
33
|
}));
|
|
31
34
|
return (indexConfig) => {
|