@pwrdrvr/microapps-router-lib 0.4.0-alpha.8 → 0.4.0-alpha.9
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/app-cache.d.ts +58 -0
- package/dist/app-cache.d.ts.map +1 -0
- package/dist/app-cache.js +154 -0
- package/dist/app-cache.js.map +1 -0
- package/dist/index.d.ts +97 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +375 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/log.d.ts +5 -0
- package/dist/lib/log.d.ts.map +1 -0
- package/dist/lib/log.js +11 -0
- package/dist/lib/log.js.map +1 -0
- package/package.json +2 -1
- package/src/app-cache.spec.ts +175 -0
- package/src/app-cache.ts +193 -0
- package/src/index.spec.ts +28 -24
- package/src/index.ts +46 -45
package/dist/index.js
ADDED
|
@@ -0,0 +1,375 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.GetAppInfo = exports.GetRoute = exports.normalizePathPrefix = exports.loadAppFrame = exports.AppVersionCache = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
require("source-map-support/register");
|
|
6
|
+
const path_1 = tslib_1.__importDefault(require("path"));
|
|
7
|
+
const fs_extra_1 = require("fs-extra");
|
|
8
|
+
const log_1 = tslib_1.__importDefault(require("./lib/log"));
|
|
9
|
+
const app_cache_1 = require("./app-cache");
|
|
10
|
+
Object.defineProperty(exports, "AppVersionCache", { enumerable: true, get: function () { return app_cache_1.AppVersionCache; } });
|
|
11
|
+
const log = log_1.default.Instance;
|
|
12
|
+
/**
|
|
13
|
+
* Find and load the appFrame file
|
|
14
|
+
* @returns
|
|
15
|
+
*/
|
|
16
|
+
function loadAppFrame({ basePath = '.' }) {
|
|
17
|
+
const paths = [
|
|
18
|
+
basePath,
|
|
19
|
+
path_1.default.join(basePath, '..'),
|
|
20
|
+
path_1.default.join(basePath, 'templates'),
|
|
21
|
+
basePath,
|
|
22
|
+
'/opt',
|
|
23
|
+
'/opt/templates',
|
|
24
|
+
];
|
|
25
|
+
for (const pathRoot of paths) {
|
|
26
|
+
const fullPath = path_1.default.join(pathRoot, 'appFrame.html');
|
|
27
|
+
try {
|
|
28
|
+
if ((0, fs_extra_1.pathExistsSync)(fullPath)) {
|
|
29
|
+
log.info('found html file', { fullPath });
|
|
30
|
+
return (0, fs_extra_1.readFileSync)(fullPath, 'utf-8');
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
catch (_a) {
|
|
34
|
+
// Don't care - we get here if stat throws because the file does not exist
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
log.error('appFrame.html not found');
|
|
38
|
+
throw new Error('appFrame.html not found');
|
|
39
|
+
}
|
|
40
|
+
exports.loadAppFrame = loadAppFrame;
|
|
41
|
+
/**
|
|
42
|
+
* Ensure that the path starts with a / and does not end with a /
|
|
43
|
+
*
|
|
44
|
+
* @param pathPrefix
|
|
45
|
+
* @returns
|
|
46
|
+
*/
|
|
47
|
+
function normalizePathPrefix(pathPrefix) {
|
|
48
|
+
let normalizedPathPrefix = pathPrefix;
|
|
49
|
+
if (normalizedPathPrefix !== '' && !normalizedPathPrefix.startsWith('/')) {
|
|
50
|
+
normalizedPathPrefix = '/' + pathPrefix;
|
|
51
|
+
}
|
|
52
|
+
if (normalizedPathPrefix.endsWith('/')) {
|
|
53
|
+
normalizedPathPrefix.substring(0, normalizedPathPrefix.length - 1);
|
|
54
|
+
}
|
|
55
|
+
return normalizedPathPrefix;
|
|
56
|
+
}
|
|
57
|
+
exports.normalizePathPrefix = normalizePathPrefix;
|
|
58
|
+
/**
|
|
59
|
+
* Get information about immediate redirect, immediate response,
|
|
60
|
+
* or which host to route the request to.
|
|
61
|
+
*
|
|
62
|
+
* @param event
|
|
63
|
+
*
|
|
64
|
+
* @returns IGetRouteResult
|
|
65
|
+
*/
|
|
66
|
+
async function GetRoute(event) {
|
|
67
|
+
const { dbManager, normalizedPathPrefix = '', queryStringParameters } = event;
|
|
68
|
+
try {
|
|
69
|
+
if (normalizedPathPrefix && !event.rawPath.startsWith(normalizedPathPrefix)) {
|
|
70
|
+
// The prefix is required if configured, if missing we cannot serve this app
|
|
71
|
+
return { statusCode: 404, errorMessage: 'Request not routable' };
|
|
72
|
+
}
|
|
73
|
+
const pathAfterPrefix = normalizedPathPrefix && event.rawPath.startsWith(normalizedPathPrefix)
|
|
74
|
+
? event.rawPath.slice(normalizedPathPrefix.length - 1)
|
|
75
|
+
: event.rawPath;
|
|
76
|
+
// /someapp will split into length 2 with ["", "someapp"] as results
|
|
77
|
+
// /someapp/somepath will split into length 3 with ["", "someapp", "somepath"] as results
|
|
78
|
+
// /someapp/somepath/ will split into length 3 with ["", "someapp", "somepath", ""] as results
|
|
79
|
+
// /someapp/somepath/somefile.foo will split into length 4 with ["", "someapp", "somepath", "somefile.foo", ""] as results
|
|
80
|
+
const partsAfterPrefix = pathAfterPrefix.split('/');
|
|
81
|
+
const appName = await GetAppInfo({
|
|
82
|
+
dbManager,
|
|
83
|
+
appName: partsAfterPrefix.length >= 2 ? partsAfterPrefix[1] : '[root]',
|
|
84
|
+
});
|
|
85
|
+
if (!appName) {
|
|
86
|
+
return { statusCode: 404, errorMessage: 'App not found' };
|
|
87
|
+
}
|
|
88
|
+
const isRootApp = appName === '[root]';
|
|
89
|
+
const appNameOrRootTrailingSlash = isRootApp ? '' : `${appName}/`;
|
|
90
|
+
// Strip the appName from the start of the path, if there was one
|
|
91
|
+
const pathAfterAppName = isRootApp
|
|
92
|
+
? pathAfterPrefix
|
|
93
|
+
: pathAfterPrefix.slice(appName.length + 1);
|
|
94
|
+
const partsAfterAppName = pathAfterAppName.split('/');
|
|
95
|
+
// Pass any parts after the appName/Version to the route handler
|
|
96
|
+
let additionalParts = '';
|
|
97
|
+
if (partsAfterAppName.length >= 2 && partsAfterAppName[1] !== '') {
|
|
98
|
+
additionalParts = partsAfterAppName.slice(1).join('/');
|
|
99
|
+
}
|
|
100
|
+
// Route an app and version (only) to include the defaultFile
|
|
101
|
+
// If the second part is not a version that exists, fall through to
|
|
102
|
+
// routing the app and glomming the rest of the path on to the end
|
|
103
|
+
if (partsAfterAppName.length === 2 ||
|
|
104
|
+
(partsAfterAppName.length === 3 && !partsAfterAppName[2])) {
|
|
105
|
+
// / semVer /
|
|
106
|
+
// ^ ^^^^^^ ^
|
|
107
|
+
// 0 1 2
|
|
108
|
+
// This is an app and a version only
|
|
109
|
+
// If the request got here it's likely a static app that has no
|
|
110
|
+
// Lambda function (thus the API Gateway route fell through to the Router)
|
|
111
|
+
const response = await RedirectToDefaultFile({
|
|
112
|
+
dbManager,
|
|
113
|
+
appName,
|
|
114
|
+
normalizedPathPrefix,
|
|
115
|
+
semVer: partsAfterAppName[1],
|
|
116
|
+
appNameOrRootTrailingSlash,
|
|
117
|
+
});
|
|
118
|
+
if (response) {
|
|
119
|
+
return response;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
// Check for a version in the path
|
|
123
|
+
// Examples
|
|
124
|
+
// / semVer / somepath
|
|
125
|
+
// / _next / data / semVer / somepath
|
|
126
|
+
const possibleSemVerPathNextData = partsAfterAppName.length >= 4 ? partsAfterAppName[3] : '';
|
|
127
|
+
const possibleSemVerPathAfterApp = partsAfterAppName.length >= 2 ? partsAfterAppName[1] : '';
|
|
128
|
+
// (/ something)?
|
|
129
|
+
// ^ ^^^^^^^^^^^^
|
|
130
|
+
// 0 1
|
|
131
|
+
// Got at least an application name, try to route it
|
|
132
|
+
const response = await RouteApp({
|
|
133
|
+
dbManager,
|
|
134
|
+
normalizedPathPrefix,
|
|
135
|
+
event,
|
|
136
|
+
appName,
|
|
137
|
+
possibleSemVerPathNextData,
|
|
138
|
+
possibleSemVerPathAfterApp,
|
|
139
|
+
possibleSemVerQuery: (queryStringParameters === null || queryStringParameters === void 0 ? void 0 : queryStringParameters.get('appver')) || '',
|
|
140
|
+
additionalParts,
|
|
141
|
+
appNameOrRootTrailingSlash,
|
|
142
|
+
});
|
|
143
|
+
if (response) {
|
|
144
|
+
return response;
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
statusCode: 599,
|
|
148
|
+
errorMessage: `Router - Could not route: ${event.rawPath}, no matching route`,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
catch (error) {
|
|
152
|
+
log.error('unexpected exception - returning 599', { statusCode: 599, error });
|
|
153
|
+
return {
|
|
154
|
+
statusCode: 599,
|
|
155
|
+
errorMessage: `Router - Could not route: ${event.rawPath}, ${error.message}`,
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
exports.GetRoute = GetRoute;
|
|
160
|
+
/**
|
|
161
|
+
* Determine if we have an appname or a catch all app
|
|
162
|
+
*/
|
|
163
|
+
async function GetAppInfo(opts) {
|
|
164
|
+
const { dbManager, appName } = opts;
|
|
165
|
+
let rules;
|
|
166
|
+
const appVersionCache = app_cache_1.AppVersionCache.GetInstance({ dbManager });
|
|
167
|
+
// Check if we got a matching app name
|
|
168
|
+
rules = await appVersionCache.GetRules({ key: { AppName: appName } });
|
|
169
|
+
if (rules && rules.AppName === appName.toLowerCase()) {
|
|
170
|
+
return appName;
|
|
171
|
+
}
|
|
172
|
+
// Check if we have a `[root]` app that is a catch all
|
|
173
|
+
rules = await appVersionCache.GetRules({ key: { AppName: '[root]' } });
|
|
174
|
+
if (rules && rules.AppName === '[root]') {
|
|
175
|
+
return '[root]';
|
|
176
|
+
}
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
exports.GetAppInfo = GetAppInfo;
|
|
180
|
+
/**
|
|
181
|
+
* Lookup the version of the app to run
|
|
182
|
+
* @param event
|
|
183
|
+
* @param response
|
|
184
|
+
* @param appName
|
|
185
|
+
* @param additionalParts
|
|
186
|
+
* @param log
|
|
187
|
+
* @returns
|
|
188
|
+
*/
|
|
189
|
+
async function RouteApp(opts) {
|
|
190
|
+
var _a;
|
|
191
|
+
const { dbManager, event, normalizedPathPrefix = '', appName, possibleSemVerPathNextData, possibleSemVerPathAfterApp, possibleSemVerQuery, additionalParts, appNameOrRootTrailingSlash, } = opts;
|
|
192
|
+
let versionInfoToUse;
|
|
193
|
+
const appVersionCache = app_cache_1.AppVersionCache.GetInstance({ dbManager });
|
|
194
|
+
// Check if the semver placeholder is actually a defined version
|
|
195
|
+
const possibleSemVerPathAfterAppVersionInfo = possibleSemVerPathAfterApp
|
|
196
|
+
? await appVersionCache.GetVersionInfo({
|
|
197
|
+
key: { AppName: appName, SemVer: possibleSemVerPathAfterApp },
|
|
198
|
+
})
|
|
199
|
+
: undefined;
|
|
200
|
+
const possibleSemVerPathNextDataVersionInfo = possibleSemVerPathNextData
|
|
201
|
+
? await appVersionCache.GetVersionInfo({
|
|
202
|
+
key: { AppName: appName, SemVer: possibleSemVerPathNextData },
|
|
203
|
+
})
|
|
204
|
+
: undefined;
|
|
205
|
+
const possibleSemVerQueryVersionInfo = possibleSemVerQuery
|
|
206
|
+
? await appVersionCache.GetVersionInfo({
|
|
207
|
+
key: { AppName: appName, SemVer: possibleSemVerQuery },
|
|
208
|
+
})
|
|
209
|
+
: undefined;
|
|
210
|
+
// If there is a version in the path, use it
|
|
211
|
+
const possibleSemVerPathVersionInfo = possibleSemVerPathAfterAppVersionInfo || possibleSemVerPathNextDataVersionInfo;
|
|
212
|
+
if (possibleSemVerPathVersionInfo) {
|
|
213
|
+
// This is a version, and it's in the path already, route the request to it
|
|
214
|
+
// without creating iframe
|
|
215
|
+
return {
|
|
216
|
+
appName,
|
|
217
|
+
semVer: possibleSemVerPathVersionInfo.SemVer,
|
|
218
|
+
...((possibleSemVerPathVersionInfo === null || possibleSemVerPathVersionInfo === void 0 ? void 0 : possibleSemVerPathVersionInfo.URL) ? { url: possibleSemVerPathVersionInfo === null || possibleSemVerPathVersionInfo === void 0 ? void 0 : possibleSemVerPathVersionInfo.URL } : {}),
|
|
219
|
+
...((possibleSemVerPathVersionInfo === null || possibleSemVerPathVersionInfo === void 0 ? void 0 : possibleSemVerPathVersionInfo.Type)
|
|
220
|
+
? {
|
|
221
|
+
type: (possibleSemVerPathVersionInfo === null || possibleSemVerPathVersionInfo === void 0 ? void 0 : possibleSemVerPathVersionInfo.Type) === 'lambda'
|
|
222
|
+
? 'apigwy'
|
|
223
|
+
: possibleSemVerPathVersionInfo === null || possibleSemVerPathVersionInfo === void 0 ? void 0 : possibleSemVerPathVersionInfo.Type,
|
|
224
|
+
}
|
|
225
|
+
: {}),
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
else if (possibleSemVerQueryVersionInfo) {
|
|
229
|
+
// We got a version for the query string, but it's not in the path,
|
|
230
|
+
// so fall back to normal routing (create an iframe or direct route)
|
|
231
|
+
versionInfoToUse = possibleSemVerQueryVersionInfo;
|
|
232
|
+
}
|
|
233
|
+
else if (possibleSemVerQuery) {
|
|
234
|
+
// We got a version in the query string but it does not exist
|
|
235
|
+
// This needs to 404 as this is a very specific request for a specific version
|
|
236
|
+
log.error(`could not find app ${appName}, for path ${event.rawPath} - returning 404`, {
|
|
237
|
+
statusCode: 404,
|
|
238
|
+
});
|
|
239
|
+
return {
|
|
240
|
+
statusCode: 404,
|
|
241
|
+
errorMessage: `Router - Could not find app: ${event.rawPath}, ${appName}`,
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
else {
|
|
245
|
+
//
|
|
246
|
+
// TODO: Get the incoming attributes of user
|
|
247
|
+
// For logged in users, these can be: department, product type,
|
|
248
|
+
// employee, office, division, etc.
|
|
249
|
+
// For anonymous users this can be: geo region, language,
|
|
250
|
+
// browser, IP, CIDR, ASIN, etc.
|
|
251
|
+
//
|
|
252
|
+
// The Rules can be either a version or a distribution of versions,
|
|
253
|
+
// including default, for example:
|
|
254
|
+
// 80% to 1.1.0, 20% to default (1.0.3)
|
|
255
|
+
//
|
|
256
|
+
const rules = await appVersionCache.GetRules({ key: { AppName: appName } });
|
|
257
|
+
const defaultVersion = (_a = rules === null || rules === void 0 ? void 0 : rules.RuleSet.default) === null || _a === void 0 ? void 0 : _a.SemVer;
|
|
258
|
+
if (defaultVersion == null) {
|
|
259
|
+
log.error(`could not find app ${appName}, for path ${event.rawPath} - returning 404`, {
|
|
260
|
+
statusCode: 404,
|
|
261
|
+
});
|
|
262
|
+
return {
|
|
263
|
+
statusCode: 404,
|
|
264
|
+
errorMessage: `Router - Could not find app: ${event.rawPath}, ${appName}`,
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
const defaultVersionInfo = await appVersionCache.GetVersionInfo({
|
|
268
|
+
key: { AppName: appName, SemVer: defaultVersion },
|
|
269
|
+
});
|
|
270
|
+
versionInfoToUse = defaultVersionInfo;
|
|
271
|
+
}
|
|
272
|
+
if (!versionInfoToUse) {
|
|
273
|
+
log.error(`could not find version info for app ${appName}, for path ${event.rawPath} - returning 404`, {
|
|
274
|
+
statusCode: 404,
|
|
275
|
+
});
|
|
276
|
+
return {
|
|
277
|
+
statusCode: 404,
|
|
278
|
+
errorMessage: `Router - Could not find version info for app: ${event.rawPath}, ${appName}`,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
if ((versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.StartupType) === 'iframe' || !(versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.StartupType)) {
|
|
282
|
+
// Prepare the iframe contents
|
|
283
|
+
let appVersionPath;
|
|
284
|
+
if ((versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.Type) !== 'static' &&
|
|
285
|
+
((versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.DefaultFile) === undefined ||
|
|
286
|
+
(versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.DefaultFile) === '' ||
|
|
287
|
+
additionalParts !== '')) {
|
|
288
|
+
// KLUDGE: We're going to take a missing default file to mean that the
|
|
289
|
+
// app type is Next.js (or similar) and that it wants no trailing slash after the version
|
|
290
|
+
// TODO: Move this to an attribute of the version
|
|
291
|
+
appVersionPath = `${normalizedPathPrefix}/${appNameOrRootTrailingSlash}${versionInfoToUse.SemVer}`;
|
|
292
|
+
if (additionalParts !== '') {
|
|
293
|
+
appVersionPath += `/${additionalParts}`;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
else {
|
|
297
|
+
// Linking to the file directly means this will be peeled off by the S3 route
|
|
298
|
+
// That means we won't have to proxy this from S3
|
|
299
|
+
appVersionPath = `${normalizedPathPrefix}/${appNameOrRootTrailingSlash}${versionInfoToUse.SemVer}/${versionInfoToUse.DefaultFile}`;
|
|
300
|
+
}
|
|
301
|
+
return {
|
|
302
|
+
statusCode: 200,
|
|
303
|
+
appName,
|
|
304
|
+
semVer: versionInfoToUse.SemVer,
|
|
305
|
+
startupType: 'iframe',
|
|
306
|
+
...((versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.URL) ? { url: versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.URL } : {}),
|
|
307
|
+
...((versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.Type)
|
|
308
|
+
? { type: (versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.Type) === 'lambda' ? 'apigwy' : versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.Type }
|
|
309
|
+
: {}),
|
|
310
|
+
iFrameAppVersionPath: appVersionPath,
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
// This is a direct app version, no iframe needed
|
|
315
|
+
if ((versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.Type) === 'lambda') {
|
|
316
|
+
throw new Error('Invalid type for direct app version');
|
|
317
|
+
}
|
|
318
|
+
if (['apigwy', 'static'].includes((versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.Type) || '')) {
|
|
319
|
+
throw new Error('Invalid type for direct app version');
|
|
320
|
+
}
|
|
321
|
+
return {
|
|
322
|
+
appName,
|
|
323
|
+
semVer: versionInfoToUse.SemVer,
|
|
324
|
+
startupType: 'direct',
|
|
325
|
+
...((versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.URL) ? { url: versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.URL } : {}),
|
|
326
|
+
...((versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.Type) ? { type: versionInfoToUse === null || versionInfoToUse === void 0 ? void 0 : versionInfoToUse.Type } : {}),
|
|
327
|
+
};
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Redirect the request to app/x.y.z/? to app/x.y.z/{defaultFile}
|
|
332
|
+
* @param response
|
|
333
|
+
* @param normalizedPathPrefix
|
|
334
|
+
* @param appName
|
|
335
|
+
* @param semVer
|
|
336
|
+
* @returns
|
|
337
|
+
*/
|
|
338
|
+
async function RedirectToDefaultFile(opts) {
|
|
339
|
+
const { dbManager, normalizedPathPrefix = '', appName, appNameOrRootTrailingSlash, semVer, } = opts;
|
|
340
|
+
let versionInfo;
|
|
341
|
+
try {
|
|
342
|
+
// Get the cache
|
|
343
|
+
const appVersionCache = app_cache_1.AppVersionCache.GetInstance({ dbManager });
|
|
344
|
+
versionInfo = await appVersionCache.GetVersionInfo({
|
|
345
|
+
key: { AppName: appName, SemVer: semVer },
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
catch (error) {
|
|
349
|
+
log.info(`LoadVersion threw for '${normalizedPathPrefix}/${appNameOrRootTrailingSlash}${semVer}' - falling through to app routing'`, {
|
|
350
|
+
appName,
|
|
351
|
+
semVer,
|
|
352
|
+
error,
|
|
353
|
+
});
|
|
354
|
+
return undefined;
|
|
355
|
+
}
|
|
356
|
+
if (versionInfo === undefined) {
|
|
357
|
+
log.info(`LoadVersion returned undefined for '${normalizedPathPrefix}/${appNameOrRootTrailingSlash}${semVer}', assuming not found - falling through to app routing'`, {
|
|
358
|
+
appName,
|
|
359
|
+
semVer,
|
|
360
|
+
});
|
|
361
|
+
return undefined;
|
|
362
|
+
}
|
|
363
|
+
if (!versionInfo.DefaultFile) {
|
|
364
|
+
return undefined;
|
|
365
|
+
}
|
|
366
|
+
log.info(`found '${normalizedPathPrefix}/${appNameOrRootTrailingSlash}${semVer}' - returning 302 to ${normalizedPathPrefix}/${appNameOrRootTrailingSlash}${semVer}/${versionInfo.DefaultFile}`, {
|
|
367
|
+
statusCode: 302,
|
|
368
|
+
routedPath: `${normalizedPathPrefix}/${appNameOrRootTrailingSlash}${semVer}/${versionInfo.DefaultFile}`,
|
|
369
|
+
});
|
|
370
|
+
return {
|
|
371
|
+
statusCode: 302,
|
|
372
|
+
redirectLocation: `${normalizedPathPrefix}/${appNameOrRootTrailingSlash}${semVer}/${versionInfo.DefaultFile}`,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.d.ts","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAEvC,MAAM,CAAC,OAAO,OAAO,GAAG;IACtB,OAAc,QAAQ,YAGnB;CACJ"}
|
package/dist/lib/log.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const lambda_log_1 = require("lambda-log");
|
|
4
|
+
class Log {
|
|
5
|
+
}
|
|
6
|
+
exports.default = Log;
|
|
7
|
+
Log.Instance = new lambda_log_1.LambdaLog({
|
|
8
|
+
silent: process.env.JEST_WORKER_ID !== undefined,
|
|
9
|
+
// debug: process.env.DEBUG ? true : false,
|
|
10
|
+
});
|
|
11
|
+
//# sourceMappingURL=log.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"log.js","sourceRoot":"","sources":["../../src/lib/log.ts"],"names":[],"mappings":";;AAAA,2CAAuC;AAEvC,MAAqB,GAAG;;AAAxB,sBAKC;AAJe,YAAQ,GAAG,IAAI,sBAAS,CAAC;IACrC,MAAM,EAAE,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,SAAS;IAChD,2CAA2C;CAC5C,CAAC,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@pwrdrvr/microapps-router-lib",
|
|
3
|
-
"version": "0.4.0-alpha.
|
|
3
|
+
"version": "0.4.0-alpha.9",
|
|
4
4
|
"description": "Router library for the microapps framework",
|
|
5
5
|
"types": "dist/index.d.ts",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
"homepage": "https://github.com/pwrdrvr/microapps-core#readme",
|
|
20
20
|
"peerDependencies": {
|
|
21
21
|
"@aws-sdk/client-dynamodb": "^3.0.0",
|
|
22
|
+
"@pwrdrvr/microapps-datalib": "*",
|
|
22
23
|
"fs-extra": "^9.0.0",
|
|
23
24
|
"lambda-log": "^3.0.0",
|
|
24
25
|
"source-map-support": "^0.5.0",
|
|
@@ -0,0 +1,175 @@
|
|
|
1
|
+
/// <reference types="jest" />
|
|
2
|
+
import 'jest-dynalite/withDb';
|
|
3
|
+
import * as dynamodb from '@aws-sdk/client-dynamodb';
|
|
4
|
+
import { Application, DBManager, Version, Rules } from '@pwrdrvr/microapps-datalib';
|
|
5
|
+
import { AppVersionCache } from './app-cache';
|
|
6
|
+
|
|
7
|
+
let dynamoClient: dynamodb.DynamoDBClient;
|
|
8
|
+
let dbManager: DBManager;
|
|
9
|
+
|
|
10
|
+
const TEST_TABLE_NAME = 'microapps';
|
|
11
|
+
|
|
12
|
+
describe('app-cache', () => {
|
|
13
|
+
beforeAll(() => {
|
|
14
|
+
jest.setTimeout(30000);
|
|
15
|
+
|
|
16
|
+
dynamoClient = new dynamodb.DynamoDBClient({
|
|
17
|
+
endpoint: process.env.MOCK_DYNAMODB_ENDPOINT,
|
|
18
|
+
tls: false,
|
|
19
|
+
region: 'local',
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Init the DB manager to point it at the right table
|
|
23
|
+
dbManager = new DBManager({ dynamoClient, tableName: TEST_TABLE_NAME });
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
describe('GetRules', () => {
|
|
27
|
+
it('Returns cached record after deleted from DB', async () => {
|
|
28
|
+
const app = new Application({
|
|
29
|
+
AppName: 'Cached',
|
|
30
|
+
DisplayName: 'Cached App',
|
|
31
|
+
});
|
|
32
|
+
await app.Save(dbManager);
|
|
33
|
+
|
|
34
|
+
const version = new Version({
|
|
35
|
+
AppName: 'Cached',
|
|
36
|
+
LambdaARN: 'arn:aws:lambda:us-east-1:123456789012:function:cached',
|
|
37
|
+
URL: 'https://some-lambda-function-url-id.lambda-url.us-east-2.on.aws/',
|
|
38
|
+
SemVer: '3.2.1-beta.1',
|
|
39
|
+
Status: 'deployed',
|
|
40
|
+
Type: 'lambda',
|
|
41
|
+
});
|
|
42
|
+
await version.Save(dbManager);
|
|
43
|
+
|
|
44
|
+
const rules = new Rules({
|
|
45
|
+
AppName: 'Cached',
|
|
46
|
+
Version: 0,
|
|
47
|
+
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
48
|
+
});
|
|
49
|
+
await rules.Save(dbManager);
|
|
50
|
+
|
|
51
|
+
const appVersionCache = new AppVersionCache({ dbManager });
|
|
52
|
+
|
|
53
|
+
// Seed the cache while record exists
|
|
54
|
+
const versionWhenDBExists = await appVersionCache.GetRules({
|
|
55
|
+
key: { AppName: 'Cached' },
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
expect(versionWhenDBExists).toHaveProperty('AppName', 'cached');
|
|
59
|
+
expect(versionWhenDBExists).toHaveProperty('RuleSet', {
|
|
60
|
+
default: { AttributeName: '', AttributeValue: '', SemVer: '3.2.1-beta.1' },
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
// Clobber the Rules record
|
|
64
|
+
await Application.UpdateDefaultRule({
|
|
65
|
+
dbManager,
|
|
66
|
+
key: { AppName: 'Cached', SemVer: '9.9.9' },
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
// Get record from cache after DB record is deleted
|
|
70
|
+
const rulesWhenCleared = await appVersionCache.GetRules({
|
|
71
|
+
key: { AppName: 'Cached' },
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
expect(rulesWhenCleared).toEqual(versionWhenDBExists);
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe('GetVersionInfo', () => {
|
|
79
|
+
it('Returns cached record after deleted from DB', async () => {
|
|
80
|
+
const app = new Application({
|
|
81
|
+
AppName: 'Cached',
|
|
82
|
+
DisplayName: 'Cached App',
|
|
83
|
+
});
|
|
84
|
+
await app.Save(dbManager);
|
|
85
|
+
|
|
86
|
+
const version = new Version({
|
|
87
|
+
AppName: 'Cached',
|
|
88
|
+
LambdaARN: 'arn:aws:lambda:us-east-1:123456789012:function:cached',
|
|
89
|
+
URL: 'https://some-lambda-function-url-id.lambda-url.us-east-2.on.aws/',
|
|
90
|
+
SemVer: '3.2.1-beta.1',
|
|
91
|
+
Status: 'deployed',
|
|
92
|
+
Type: 'lambda',
|
|
93
|
+
});
|
|
94
|
+
await version.Save(dbManager);
|
|
95
|
+
|
|
96
|
+
const rules = new Rules({
|
|
97
|
+
AppName: 'Cached',
|
|
98
|
+
Version: 0,
|
|
99
|
+
RuleSet: { default: { SemVer: '3.2.1-beta.1', AttributeName: '', AttributeValue: '' } },
|
|
100
|
+
});
|
|
101
|
+
await rules.Save(dbManager);
|
|
102
|
+
|
|
103
|
+
const appVersionCache = new AppVersionCache({ dbManager });
|
|
104
|
+
|
|
105
|
+
// Seed the cache while record exists
|
|
106
|
+
const versionWhenDBExists = await appVersionCache.GetVersionInfo({
|
|
107
|
+
key: { AppName: 'Cached', SemVer: '3.2.1-beta.1' },
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
expect(versionWhenDBExists).toHaveProperty('AppName', 'cached');
|
|
111
|
+
expect(versionWhenDBExists).toHaveProperty(
|
|
112
|
+
'URL',
|
|
113
|
+
'https://some-lambda-function-url-id.lambda-url.us-east-2.on.aws/',
|
|
114
|
+
);
|
|
115
|
+
expect(versionWhenDBExists).toHaveProperty('SemVer', '3.2.1-beta.1');
|
|
116
|
+
expect(versionWhenDBExists).toHaveProperty('Status', 'deployed');
|
|
117
|
+
expect(versionWhenDBExists).toHaveProperty('Type', 'lambda');
|
|
118
|
+
|
|
119
|
+
// Delete the record
|
|
120
|
+
await Version.DeleteVersion({
|
|
121
|
+
dbManager,
|
|
122
|
+
key: { AppName: 'Cached', SemVer: '3.2.1-beta.1' },
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
// Get record from cache after DB record is deleted
|
|
126
|
+
const versionWhenDBCleared = await appVersionCache.GetVersionInfo({
|
|
127
|
+
key: { AppName: 'Cached', SemVer: '3.2.1-beta.1' },
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
expect(versionWhenDBCleared).toEqual(versionWhenDBExists);
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
it('Negative Cache', async () => {
|
|
134
|
+
const appVersionCache = new AppVersionCache({ dbManager });
|
|
135
|
+
|
|
136
|
+
// Seed the negative cache
|
|
137
|
+
const versionWhenDBExists = await appVersionCache.GetVersionInfo({
|
|
138
|
+
key: { AppName: 'Missing', SemVer: '7.6.8' },
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
// Confirm record is not in the DB
|
|
142
|
+
expect(versionWhenDBExists).toBeUndefined();
|
|
143
|
+
|
|
144
|
+
const app = new Application({
|
|
145
|
+
AppName: 'Missing',
|
|
146
|
+
DisplayName: 'Bat App',
|
|
147
|
+
});
|
|
148
|
+
await app.Save(dbManager);
|
|
149
|
+
|
|
150
|
+
const version = new Version({
|
|
151
|
+
AppName: 'Missing',
|
|
152
|
+
SemVer: '7.6.8',
|
|
153
|
+
LambdaARN: 'arn:aws:lambda:us-east-1:123456789012:function:bat',
|
|
154
|
+
URL: 'https://some-lambda-function-url-id.lambda-url.us-east-2.on.aws/',
|
|
155
|
+
Status: 'deployed',
|
|
156
|
+
Type: 'lambda',
|
|
157
|
+
});
|
|
158
|
+
await version.Save(dbManager);
|
|
159
|
+
|
|
160
|
+
const rules = new Rules({
|
|
161
|
+
AppName: 'Missing',
|
|
162
|
+
Version: 0,
|
|
163
|
+
RuleSet: { default: { SemVer: '7.6.8', AttributeName: '', AttributeValue: '' } },
|
|
164
|
+
});
|
|
165
|
+
await rules.Save(dbManager);
|
|
166
|
+
|
|
167
|
+
// Get record from cache after DB record is created - should be hidden by negative cache
|
|
168
|
+
const versionWhenDBCreated = await appVersionCache.GetVersionInfo({
|
|
169
|
+
key: { AppName: 'Missing', SemVer: '7.6.8' },
|
|
170
|
+
});
|
|
171
|
+
|
|
172
|
+
expect(versionWhenDBCreated).toBeUndefined();
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
});
|