@sasjs/cli 6.30.0 → 6.31.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/build/commands/build/internal/mockSite/assets/api-console.css +365 -0
- package/build/commands/build/internal/mockSite/assets/api-console.js +762 -0
- package/build/commands/build/internal/mockSite/assets/api-index.html +83 -0
- package/build/commands/build/internal/mockSite/assets/boot.js +23 -1
- package/build/commands/build/internal/mockSite/assets/persist.js +76 -5
- package/build/commands/build/internal/mockSite/assets/runtime-core.js +413 -50
- package/build/commands/build/internal/mockSite/assets/sw.js +156 -15
- package/build/commands/build/internal/mockSite/mockSite.d.ts +25 -0
- package/build/commands/build/internal/mockSite/mockSite.js +311 -24
- package/build/commands/build/internal/mockSite/spec/apiConsole.spec.d.ts +1 -0
- package/build/commands/build/internal/mockSite/spec/apiConsole.spec.js +1371 -0
- package/build/commands/build/internal/mockSite/spec/apiConsoleBasePath.spec.d.ts +1 -0
- package/build/commands/build/internal/mockSite/spec/apiConsoleBasePath.spec.js +303 -0
- package/build/commands/build/internal/mockSite/spec/boot.spec.js +50 -3
- package/build/commands/build/internal/mockSite/spec/mockSite.spec.js +217 -3
- package/build/commands/build/internal/mockSite/spec/persist.spec.js +179 -1
- package/build/commands/build/internal/mockSite/spec/runtime-core.spec.js +546 -0
- package/build/commands/build/internal/mockSite/spec/sw.spec.js +407 -53
- package/build/commands/version/spec/version.spec.js +11 -1
- package/build/commands/version/version.d.ts +5 -3
- package/build/commands/version/version.js +17 -7
- package/build/types/mockWebBasePath.d.ts +9 -0
- package/package.json +13 -32
|
@@ -86,6 +86,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
86
86
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
87
87
|
};
|
|
88
88
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
89
|
+
var fs_1 = __importDefault(require("fs"));
|
|
89
90
|
var path_1 = __importDefault(require("path"));
|
|
90
91
|
var api_1 = require("@sasjs/api");
|
|
91
92
|
var os_1 = __importDefault(require("os"));
|
|
@@ -147,7 +148,11 @@ var loadWorker = function (base, options) {
|
|
|
147
148
|
}
|
|
148
149
|
};
|
|
149
150
|
global.self = self;
|
|
151
|
+
// what the worker pulled into itself, so a test can assert that a script it
|
|
152
|
+
// does not need at boot is not fetched at boot
|
|
153
|
+
var imported = [];
|
|
150
154
|
global.importScripts = function (path) {
|
|
155
|
+
imported.push(path);
|
|
151
156
|
if (path.includes('md5'))
|
|
152
157
|
return;
|
|
153
158
|
if (path.includes('api-browser'))
|
|
@@ -185,7 +190,7 @@ var loadWorker = function (base, options) {
|
|
|
185
190
|
};
|
|
186
191
|
require('../assets/sw.js');
|
|
187
192
|
global.fetch = jest.fn(function (input) { return __awaiter(void 0, void 0, void 0, function () {
|
|
188
|
-
var target, fixture, fixture;
|
|
193
|
+
var target, fixture, fixture, shards, piece, id, requested, shards_1;
|
|
189
194
|
var _a;
|
|
190
195
|
return __generator(this, function (_b) {
|
|
191
196
|
target = typeof input === 'string' ? input : (input && input.url) || String(input);
|
|
@@ -222,7 +227,29 @@ var loadWorker = function (base, options) {
|
|
|
222
227
|
userId: mockSite_1.WEBOUT_SENTINELS.userId,
|
|
223
228
|
apiServerUrl: mockSite_1.WEBOUT_SENTINELS.apiServerUrl
|
|
224
229
|
})
|
|
225
|
-
})
|
|
230
|
+
})
|
|
231
|
+
// a sharded drive, when a test sets one up: the index answers the snapshot
|
|
232
|
+
// URL and each piece answers its own file, so the worker's fetch of a shard
|
|
233
|
+
// is the same request it makes against a static host
|
|
234
|
+
];
|
|
235
|
+
shards = global.__sasjsShards;
|
|
236
|
+
if (shards && target.includes('vfs-snapshot')) {
|
|
237
|
+
piece = /vfs-snapshot-(\d+)\.json/.exec(target);
|
|
238
|
+
if (piece) {
|
|
239
|
+
id = Number(piece[1]);
|
|
240
|
+
requested = (global.__sasjsShardFetches =
|
|
241
|
+
global.__sasjsShardFetches || []);
|
|
242
|
+
requested.push(id);
|
|
243
|
+
return [2 /*return*/, jsonResponse({ format: mockSite_1.DRIVE_FORMAT, files: shards[id] || {} })];
|
|
244
|
+
}
|
|
245
|
+
return [2 /*return*/, jsonResponse(shards.index)];
|
|
246
|
+
}
|
|
247
|
+
if (target.includes('mock-config')) {
|
|
248
|
+
shards_1 = global.__sasjsShards;
|
|
249
|
+
return [2 /*return*/, jsonResponse(__assign({ appLoc: appLoc }, (shards_1
|
|
250
|
+
? { snapshotShards: (shards_1.index.shards || []).length }
|
|
251
|
+
: {})))];
|
|
252
|
+
}
|
|
226
253
|
return [2 /*return*/, target.includes('vfs-seed')
|
|
227
254
|
? jsonResponse({
|
|
228
255
|
files: (_a = {},
|
|
@@ -266,6 +293,7 @@ var loadWorker = function (base, options) {
|
|
|
266
293
|
dispatch: dispatch,
|
|
267
294
|
message: message,
|
|
268
295
|
lifecycle: lifecycle,
|
|
296
|
+
imported: imported,
|
|
269
297
|
self: self,
|
|
270
298
|
refuseWrites: function (value) {
|
|
271
299
|
refusingWrites = value;
|
|
@@ -308,6 +336,8 @@ describe('service worker host', function () {
|
|
|
308
336
|
delete global.importScripts;
|
|
309
337
|
delete global.fetch;
|
|
310
338
|
delete global.__sasjsIdentity;
|
|
339
|
+
delete global.__sasjsShards;
|
|
340
|
+
delete global.__sasjsShardFetches;
|
|
311
341
|
delete global.__mockHostClients;
|
|
312
342
|
});
|
|
313
343
|
var seeded = function () {
|
|
@@ -1412,6 +1442,161 @@ describe('service worker host', function () {
|
|
|
1412
1442
|
}
|
|
1413
1443
|
});
|
|
1414
1444
|
}); });
|
|
1445
|
+
/**
|
|
1446
|
+
* The linter is not part of the install.
|
|
1447
|
+
*
|
|
1448
|
+
* The page cannot make its first request until the worker has installed, so
|
|
1449
|
+
* anything the worker imports at boot is on the critical path of every
|
|
1450
|
+
* visit. The linter answers two routes; it is fetched when one of them is
|
|
1451
|
+
* called.
|
|
1452
|
+
*/
|
|
1453
|
+
it('fetches the linter on the first code route, not at boot', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1454
|
+
var worker, response;
|
|
1455
|
+
return __generator(this, function (_a) {
|
|
1456
|
+
switch (_a.label) {
|
|
1457
|
+
case 0:
|
|
1458
|
+
worker = seeded();
|
|
1459
|
+
expect(worker.imported.some(function (path) { return path.includes('lint-browser'); })).toBe(false);
|
|
1460
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/code/lint', runRequest({ code: 'data a;\nrun;\n' }))];
|
|
1461
|
+
case 1:
|
|
1462
|
+
response = _a.sent();
|
|
1463
|
+
expect(response.status).toBe(200);
|
|
1464
|
+
expect(worker.imported.some(function (path) { return path.includes('lint-browser'); })).toBe(true);
|
|
1465
|
+
return [2 /*return*/];
|
|
1466
|
+
}
|
|
1467
|
+
});
|
|
1468
|
+
}); });
|
|
1469
|
+
/**
|
|
1470
|
+
* A route that resolves a path from the drive is not left with a hole.
|
|
1471
|
+
*
|
|
1472
|
+
* The rules an edited file is linted against are found by walking up from
|
|
1473
|
+
* the file, so the request names neither path. The read that fails says
|
|
1474
|
+
* which piece it needs, and the request is answered again with it - the body
|
|
1475
|
+
* re-read from the copy taken before the first attempt.
|
|
1476
|
+
*/
|
|
1477
|
+
it('fetches the piece a route resolves from the drive, not the one it names', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1478
|
+
var worker, longLine, response, _a, _b, _c;
|
|
1479
|
+
return __generator(this, function (_d) {
|
|
1480
|
+
switch (_d.label) {
|
|
1481
|
+
case 0:
|
|
1482
|
+
;
|
|
1483
|
+
global.__sasjsShards = {
|
|
1484
|
+
index: {
|
|
1485
|
+
format: mockSite_1.DRIVE_FORMAT,
|
|
1486
|
+
sharded: true,
|
|
1487
|
+
boot: 0,
|
|
1488
|
+
entries: {
|
|
1489
|
+
'/sasjs/drive/files/.sasjslint': { shard: 1, bytes: 20 },
|
|
1490
|
+
'/sasjs/drive/files/Public/app/test/prog.sas': {
|
|
1491
|
+
shard: 0,
|
|
1492
|
+
bytes: 12
|
|
1493
|
+
}
|
|
1494
|
+
},
|
|
1495
|
+
shards: [
|
|
1496
|
+
{ id: 0, file: 'host/vfs-snapshot-0.json' },
|
|
1497
|
+
{ id: 1, file: 'host/vfs-snapshot-1.json' }
|
|
1498
|
+
]
|
|
1499
|
+
},
|
|
1500
|
+
0: { '/sasjs/drive/files/Public/app/test/prog.sas': 'data a; run;' },
|
|
1501
|
+
1: {
|
|
1502
|
+
'/sasjs/drive/files/.sasjslint': JSON.stringify({
|
|
1503
|
+
maxLineLength: 200
|
|
1504
|
+
})
|
|
1505
|
+
}
|
|
1506
|
+
};
|
|
1507
|
+
global.__sasjsShardFetches = [];
|
|
1508
|
+
worker = loadWorker();
|
|
1509
|
+
return [4 /*yield*/, worker.runtime.load({})];
|
|
1510
|
+
case 1:
|
|
1511
|
+
_d.sent();
|
|
1512
|
+
longLine = 'x'.repeat(150);
|
|
1513
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/code/lint', runRequest({
|
|
1514
|
+
code: "data _null_;\n".concat(longLine, "\nrun;\n"),
|
|
1515
|
+
filePath: '/Public/app/test/prog.sas'
|
|
1516
|
+
}))];
|
|
1517
|
+
case 2:
|
|
1518
|
+
response = _d.sent();
|
|
1519
|
+
expect(response.status).toBe(200);
|
|
1520
|
+
// the line is over the linter's default 80 and under this drive's 200, so
|
|
1521
|
+
// the answer proves the rules file was read - from a piece the request
|
|
1522
|
+
// never named
|
|
1523
|
+
_a = expect;
|
|
1524
|
+
_c = (_b = JSON).stringify;
|
|
1525
|
+
return [4 /*yield*/, response.json()];
|
|
1526
|
+
case 3:
|
|
1527
|
+
// the line is over the linter's default 80 and under this drive's 200, so
|
|
1528
|
+
// the answer proves the rules file was read - from a piece the request
|
|
1529
|
+
// never named
|
|
1530
|
+
_a.apply(void 0, [_c.apply(_b, [_d.sent()])]).not.toContain('Line exceeds');
|
|
1531
|
+
expect(global.__sasjsShardFetches).toEqual([0, 1]);
|
|
1532
|
+
return [2 /*return*/];
|
|
1533
|
+
}
|
|
1534
|
+
});
|
|
1535
|
+
}); });
|
|
1536
|
+
/**
|
|
1537
|
+
* A request that needs a second piece is answered, body and all.
|
|
1538
|
+
*
|
|
1539
|
+
* The first retry fetches the piece the failed read named; a request that
|
|
1540
|
+
* reads two pieces one after another reaches the second retry, which fetches
|
|
1541
|
+
* the rest. Either way the body has to arrive again - a Request's body can
|
|
1542
|
+
* only be read once, so the first attempt keeps an unread copy and each
|
|
1543
|
+
* attempt after it is made from a copy of that.
|
|
1544
|
+
*/
|
|
1545
|
+
it('replays a request that needs two pieces, with its body intact', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
1546
|
+
var near, far, worker, longLine, response, findings, _a, _b;
|
|
1547
|
+
var _c, _d, _e;
|
|
1548
|
+
return __generator(this, function (_f) {
|
|
1549
|
+
switch (_f.label) {
|
|
1550
|
+
case 0:
|
|
1551
|
+
near = '/sasjs/drive/files/Public/app/test/.sasjslint';
|
|
1552
|
+
far = '/sasjs/drive/files/.sasjslint';
|
|
1553
|
+
global.__sasjsShards = {
|
|
1554
|
+
index: {
|
|
1555
|
+
format: mockSite_1.DRIVE_FORMAT,
|
|
1556
|
+
sharded: true,
|
|
1557
|
+
boot: 0,
|
|
1558
|
+
entries: (_c = {},
|
|
1559
|
+
_c[near] = { shard: 1, bytes: 20 },
|
|
1560
|
+
_c[far] = { shard: 2, bytes: 20 },
|
|
1561
|
+
_c),
|
|
1562
|
+
shards: [
|
|
1563
|
+
{ id: 0, file: 'host/vfs-snapshot-0.json' },
|
|
1564
|
+
{ id: 1, file: 'host/vfs-snapshot-1.json' },
|
|
1565
|
+
{ id: 2, file: 'host/vfs-snapshot-2.json' }
|
|
1566
|
+
]
|
|
1567
|
+
},
|
|
1568
|
+
0: {},
|
|
1569
|
+
// the nearest rules file is unreadable as a config, so the walk goes on
|
|
1570
|
+
// to the drive root's - a second piece, in a second shard
|
|
1571
|
+
1: (_d = {}, _d[near] = 'not json', _d),
|
|
1572
|
+
2: (_e = {}, _e[far] = JSON.stringify({ maxLineLength: 200 }), _e)
|
|
1573
|
+
};
|
|
1574
|
+
global.__sasjsShardFetches = [];
|
|
1575
|
+
worker = loadWorker();
|
|
1576
|
+
return [4 /*yield*/, worker.runtime.load({})];
|
|
1577
|
+
case 1:
|
|
1578
|
+
_f.sent();
|
|
1579
|
+
longLine = 'x'.repeat(150);
|
|
1580
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/code/lint', runRequest({
|
|
1581
|
+
code: "data _null_;\n".concat(longLine, "\nrun;\n"),
|
|
1582
|
+
filePath: '/Public/app/test/prog.sas'
|
|
1583
|
+
}))];
|
|
1584
|
+
case 2:
|
|
1585
|
+
response = _f.sent();
|
|
1586
|
+
expect(response.status).toBe(200);
|
|
1587
|
+
_b = (_a = JSON).stringify;
|
|
1588
|
+
return [4 /*yield*/, response.json()];
|
|
1589
|
+
case 3:
|
|
1590
|
+
findings = _b.apply(_a, [_f.sent()]);
|
|
1591
|
+
// the code arrived on the second attempt and the root rules applied: both
|
|
1592
|
+
// halves of the claim
|
|
1593
|
+
expect(findings).toContain('Doxygen');
|
|
1594
|
+
expect(findings).not.toContain('Line exceeds');
|
|
1595
|
+
expect(global.__sasjsShardFetches).toEqual([0, 1, 2]);
|
|
1596
|
+
return [2 /*return*/];
|
|
1597
|
+
}
|
|
1598
|
+
});
|
|
1599
|
+
}); });
|
|
1415
1600
|
/**
|
|
1416
1601
|
* The rules are the drive's, not the linter's defaults.
|
|
1417
1602
|
*
|
|
@@ -2264,6 +2449,168 @@ describe('service worker host', function () {
|
|
|
2264
2449
|
}
|
|
2265
2450
|
});
|
|
2266
2451
|
}); });
|
|
2452
|
+
/**
|
|
2453
|
+
* A sharded drive supplies the piece a request names, and only that one.
|
|
2454
|
+
*
|
|
2455
|
+
* The build splits a captured drive so the first page does not download every
|
|
2456
|
+
* app's bundle. That makes it the host's job to fetch the piece holding the
|
|
2457
|
+
* path a route reads - here a drive file, named in `_filePath` - and to leave
|
|
2458
|
+
* the pieces nobody asked for on the site.
|
|
2459
|
+
*/
|
|
2460
|
+
it('fetches the piece a drive request names, and leaves the rest', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2461
|
+
var small, large, worker, response, _a;
|
|
2462
|
+
var _b, _c, _d;
|
|
2463
|
+
return __generator(this, function (_e) {
|
|
2464
|
+
switch (_e.label) {
|
|
2465
|
+
case 0:
|
|
2466
|
+
small = '/sasjs/drive/files/config.json';
|
|
2467
|
+
large = '/sasjs/drive/files/data/large.csv';
|
|
2468
|
+
global.__sasjsShards = {
|
|
2469
|
+
index: {
|
|
2470
|
+
format: mockSite_1.DRIVE_FORMAT,
|
|
2471
|
+
sharded: true,
|
|
2472
|
+
boot: 0,
|
|
2473
|
+
entries: (_b = {},
|
|
2474
|
+
_b[small] = { shard: 0, bytes: 2 },
|
|
2475
|
+
_b[large] = { shard: 1, bytes: 64 },
|
|
2476
|
+
_b),
|
|
2477
|
+
shards: [
|
|
2478
|
+
{ id: 0, file: 'host/vfs-snapshot-0.json' },
|
|
2479
|
+
{ id: 1, file: 'host/vfs-snapshot-1.json' }
|
|
2480
|
+
]
|
|
2481
|
+
},
|
|
2482
|
+
0: (_c = {}, _c[small] = '{}', _c),
|
|
2483
|
+
1: (_d = {}, _d[large] = 'a,b\n1,2\n3,4\n', _d)
|
|
2484
|
+
};
|
|
2485
|
+
global.__sasjsShardFetches = [];
|
|
2486
|
+
worker = loadWorker();
|
|
2487
|
+
return [4 /*yield*/, worker.runtime.load({})
|
|
2488
|
+
// the boot shard arrived with the drive; the second piece did not
|
|
2489
|
+
];
|
|
2490
|
+
case 1:
|
|
2491
|
+
_e.sent();
|
|
2492
|
+
// the boot shard arrived with the drive; the second piece did not
|
|
2493
|
+
expect(global.__sasjsShardFetches).toEqual([0]);
|
|
2494
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/drive/file?_filePath=' + encodeURIComponent('/data/large.csv'))];
|
|
2495
|
+
case 2:
|
|
2496
|
+
response = _e.sent();
|
|
2497
|
+
expect(response.status).toBe(200);
|
|
2498
|
+
_a = expect;
|
|
2499
|
+
return [4 /*yield*/, response.text()];
|
|
2500
|
+
case 3:
|
|
2501
|
+
_a.apply(void 0, [_e.sent()]).toContain('a,b');
|
|
2502
|
+
expect(global.__sasjsShardFetches).toEqual([0, 1]);
|
|
2503
|
+
// a second read of the same piece is answered from memory
|
|
2504
|
+
return [4 /*yield*/, worker.dispatch('/SASjsApi/drive/file?_filePath=' + encodeURIComponent('/data/large.csv'))];
|
|
2505
|
+
case 4:
|
|
2506
|
+
// a second read of the same piece is answered from memory
|
|
2507
|
+
_e.sent();
|
|
2508
|
+
expect(global.__sasjsShardFetches).toEqual([0, 1]);
|
|
2509
|
+
return [2 /*return*/];
|
|
2510
|
+
}
|
|
2511
|
+
});
|
|
2512
|
+
}); });
|
|
2513
|
+
/**
|
|
2514
|
+
* An export is the whole drive, not the part in memory.
|
|
2515
|
+
*
|
|
2516
|
+
* `window.SASjsMock.download()` writes the file a project ships as
|
|
2517
|
+
* `mock-snapshot.json`, so a sharded drive must be fetched before it is
|
|
2518
|
+
* dumped - otherwise the next build ships a snapshot that has quietly lost
|
|
2519
|
+
* every app the visitor never opened.
|
|
2520
|
+
*/
|
|
2521
|
+
it('exports every piece of a sharded drive, not only the loaded ones', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2522
|
+
var small, large, worker, _a, replies, pending, exported;
|
|
2523
|
+
var _b, _c, _d;
|
|
2524
|
+
return __generator(this, function (_e) {
|
|
2525
|
+
switch (_e.label) {
|
|
2526
|
+
case 0:
|
|
2527
|
+
small = '/sasjs/drive/files/config.json';
|
|
2528
|
+
large = '/sasjs/drive/files/data/large.csv';
|
|
2529
|
+
global.__sasjsShards = {
|
|
2530
|
+
index: {
|
|
2531
|
+
format: mockSite_1.DRIVE_FORMAT,
|
|
2532
|
+
sharded: true,
|
|
2533
|
+
boot: 0,
|
|
2534
|
+
entries: (_b = {},
|
|
2535
|
+
_b[small] = { shard: 0, bytes: 2 },
|
|
2536
|
+
_b[large] = { shard: 1, bytes: 8 },
|
|
2537
|
+
_b),
|
|
2538
|
+
shards: [
|
|
2539
|
+
{ id: 0, file: 'host/vfs-snapshot-0.json' },
|
|
2540
|
+
{ id: 1, file: 'host/vfs-snapshot-1.json' }
|
|
2541
|
+
]
|
|
2542
|
+
},
|
|
2543
|
+
0: (_c = {}, _c[small] = '{}', _c),
|
|
2544
|
+
1: (_d = {}, _d[large] = 'a,b\n1,2\n', _d)
|
|
2545
|
+
};
|
|
2546
|
+
global.__sasjsShardFetches = [];
|
|
2547
|
+
worker = loadWorker();
|
|
2548
|
+
return [4 /*yield*/, worker.runtime.load({})];
|
|
2549
|
+
case 1:
|
|
2550
|
+
_e.sent();
|
|
2551
|
+
_a = worker.message({ type: 'sasjs-snapshot' }), replies = _a.replies, pending = _a.pending;
|
|
2552
|
+
return [4 /*yield*/, pending
|
|
2553
|
+
// the piece nobody read was fetched for the export
|
|
2554
|
+
];
|
|
2555
|
+
case 2:
|
|
2556
|
+
_e.sent();
|
|
2557
|
+
// the piece nobody read was fetched for the export
|
|
2558
|
+
expect(global.__sasjsShardFetches).toEqual([0, 1]);
|
|
2559
|
+
exported = replies.find(function (reply) { return reply.type === 'sasjs-snapshot'; });
|
|
2560
|
+
expect(Object.keys(exported.files).sort()).toEqual([large, small].sort());
|
|
2561
|
+
return [2 /*return*/];
|
|
2562
|
+
}
|
|
2563
|
+
});
|
|
2564
|
+
}); });
|
|
2565
|
+
/**
|
|
2566
|
+
* The console's own files are the page, not an API call.
|
|
2567
|
+
*
|
|
2568
|
+
* `/api/...` is the API's short spelling, so the worker answers it - except for
|
|
2569
|
+
* the four files the console is made of, which the static host serves. Getting
|
|
2570
|
+
* that wrong answers the page's own script with an API 404, and the console
|
|
2571
|
+
* renders nothing.
|
|
2572
|
+
*/
|
|
2573
|
+
it('leaves the API console to the static host, and still answers /api calls', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2574
|
+
var worker, source, listed, files, files_1, files_1_1, name_1, log, response;
|
|
2575
|
+
var e_2, _a;
|
|
2576
|
+
return __generator(this, function (_b) {
|
|
2577
|
+
switch (_b.label) {
|
|
2578
|
+
case 0:
|
|
2579
|
+
worker = seeded();
|
|
2580
|
+
source = fs_1.default.readFileSync(path_1.default.join(__dirname, '..', 'assets', 'sw.js'), 'utf8');
|
|
2581
|
+
listed = /const API_CONSOLE_FILES = \[([^\]]*)\]/.exec(source);
|
|
2582
|
+
expect(listed).not.toBeNull();
|
|
2583
|
+
files = listed[1]
|
|
2584
|
+
.split(',')
|
|
2585
|
+
.map(function (entry) { return entry.trim().replace(/^'|'$/g, ''); })
|
|
2586
|
+
.filter(Boolean);
|
|
2587
|
+
expect(files.length).toBeGreaterThan(3);
|
|
2588
|
+
expect(worker.dispatch('/api/')).toBeUndefined();
|
|
2589
|
+
try {
|
|
2590
|
+
for (files_1 = __values(files), files_1_1 = files_1.next(); !files_1_1.done; files_1_1 = files_1.next()) {
|
|
2591
|
+
name_1 = files_1_1.value;
|
|
2592
|
+
expect(worker.dispatch("/api/".concat(name_1))).toBeUndefined();
|
|
2593
|
+
}
|
|
2594
|
+
}
|
|
2595
|
+
catch (e_2_1) { e_2 = { error: e_2_1 }; }
|
|
2596
|
+
finally {
|
|
2597
|
+
try {
|
|
2598
|
+
if (files_1_1 && !files_1_1.done && (_a = files_1.return)) _a.call(files_1);
|
|
2599
|
+
}
|
|
2600
|
+
finally { if (e_2) throw e_2.error; }
|
|
2601
|
+
}
|
|
2602
|
+
return [4 /*yield*/, worker.dispatch('/api/admin/logs/missing.log')];
|
|
2603
|
+
case 1:
|
|
2604
|
+
log = _b.sent();
|
|
2605
|
+
expect(log.status).not.toBeUndefined();
|
|
2606
|
+
return [4 /*yield*/, worker.dispatch('/api/user')];
|
|
2607
|
+
case 2:
|
|
2608
|
+
response = _b.sent();
|
|
2609
|
+
expect(response.status).toBe(200);
|
|
2610
|
+
return [2 /*return*/];
|
|
2611
|
+
}
|
|
2612
|
+
});
|
|
2613
|
+
}); });
|
|
2267
2614
|
it('answers 404 for a drive file the drive does not hold', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2268
2615
|
var dispatch, response, _a;
|
|
2269
2616
|
return __generator(this, function (_b) {
|
|
@@ -2283,8 +2630,8 @@ describe('service worker host', function () {
|
|
|
2283
2630
|
});
|
|
2284
2631
|
}); });
|
|
2285
2632
|
it('publishes, lists, serves and removes an app through the package surface', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
2286
|
-
var dispatch, _a, _b, path_2, listing, _c,
|
|
2287
|
-
var
|
|
2633
|
+
var dispatch, _a, _b, path_2, listing, _c, e_3_1, _d, _e, path_3, landing, e_4_1, root, archive, form, published, app, _f, _g, path_4, listing, _h, e_5_1, _j, _k, path_5, page, _l, e_6_1, folder, _m, refused, missing, removed, _o, after, _p, gone;
|
|
2634
|
+
var e_3, _q, e_4, _r, e_5, _s, e_6, _t;
|
|
2288
2635
|
return __generator(this, function (_u) {
|
|
2289
2636
|
switch (_u.label) {
|
|
2290
2637
|
case 0:
|
|
@@ -2311,14 +2658,14 @@ describe('service worker host', function () {
|
|
|
2311
2658
|
return [3 /*break*/, 2];
|
|
2312
2659
|
case 6: return [3 /*break*/, 9];
|
|
2313
2660
|
case 7:
|
|
2314
|
-
|
|
2315
|
-
|
|
2661
|
+
e_3_1 = _u.sent();
|
|
2662
|
+
e_3 = { error: e_3_1 };
|
|
2316
2663
|
return [3 /*break*/, 9];
|
|
2317
2664
|
case 8:
|
|
2318
2665
|
try {
|
|
2319
2666
|
if (_b && !_b.done && (_q = _a.return)) _q.call(_a);
|
|
2320
2667
|
}
|
|
2321
|
-
finally { if (
|
|
2668
|
+
finally { if (e_3) throw e_3.error; }
|
|
2322
2669
|
return [7 /*endfinally*/];
|
|
2323
2670
|
case 9:
|
|
2324
2671
|
_u.trys.push([9, 14, 15, 16]);
|
|
@@ -2338,14 +2685,14 @@ describe('service worker host', function () {
|
|
|
2338
2685
|
return [3 /*break*/, 10];
|
|
2339
2686
|
case 13: return [3 /*break*/, 16];
|
|
2340
2687
|
case 14:
|
|
2341
|
-
|
|
2342
|
-
|
|
2688
|
+
e_4_1 = _u.sent();
|
|
2689
|
+
e_4 = { error: e_4_1 };
|
|
2343
2690
|
return [3 /*break*/, 16];
|
|
2344
2691
|
case 15:
|
|
2345
2692
|
try {
|
|
2346
2693
|
if (_e && !_e.done && (_r = _d.return)) _r.call(_d);
|
|
2347
2694
|
}
|
|
2348
|
-
finally { if (
|
|
2695
|
+
finally { if (e_4) throw e_4.error; }
|
|
2349
2696
|
return [7 /*endfinally*/];
|
|
2350
2697
|
case 16: return [4 /*yield*/, dispatch('/AppStream')];
|
|
2351
2698
|
case 17:
|
|
@@ -2398,14 +2745,14 @@ describe('service worker host', function () {
|
|
|
2398
2745
|
return [3 /*break*/, 22];
|
|
2399
2746
|
case 26: return [3 /*break*/, 29];
|
|
2400
2747
|
case 27:
|
|
2401
|
-
|
|
2402
|
-
|
|
2748
|
+
e_5_1 = _u.sent();
|
|
2749
|
+
e_5 = { error: e_5_1 };
|
|
2403
2750
|
return [3 /*break*/, 29];
|
|
2404
2751
|
case 28:
|
|
2405
2752
|
try {
|
|
2406
2753
|
if (_g && !_g.done && (_s = _f.return)) _s.call(_f);
|
|
2407
2754
|
}
|
|
2408
|
-
finally { if (
|
|
2755
|
+
finally { if (e_5) throw e_5.error; }
|
|
2409
2756
|
return [7 /*endfinally*/];
|
|
2410
2757
|
case 29:
|
|
2411
2758
|
_u.trys.push([29, 35, 36, 37]);
|
|
@@ -2432,14 +2779,14 @@ describe('service worker host', function () {
|
|
|
2432
2779
|
return [3 /*break*/, 30];
|
|
2433
2780
|
case 34: return [3 /*break*/, 37];
|
|
2434
2781
|
case 35:
|
|
2435
|
-
|
|
2436
|
-
|
|
2782
|
+
e_6_1 = _u.sent();
|
|
2783
|
+
e_6 = { error: e_6_1 };
|
|
2437
2784
|
return [3 /*break*/, 37];
|
|
2438
2785
|
case 36:
|
|
2439
2786
|
try {
|
|
2440
2787
|
if (_k && !_k.done && (_t = _j.return)) _t.call(_j);
|
|
2441
2788
|
}
|
|
2442
|
-
finally { if (
|
|
2789
|
+
finally { if (e_6) throw e_6.error; }
|
|
2443
2790
|
return [7 /*endfinally*/];
|
|
2444
2791
|
case 37: return [4 /*yield*/, dispatch("/app/".concat(app.id))];
|
|
2445
2792
|
case 38:
|
|
@@ -2835,16 +3182,23 @@ describe('service worker host', function () {
|
|
|
2835
3182
|
expect(seed.replies[0]).toEqual(expect.objectContaining({ type: 'sasjs-seed-ack' }));
|
|
2836
3183
|
runtime.load(files);
|
|
2837
3184
|
snapshot = message({ type: 'sasjs-snapshot' });
|
|
3185
|
+
// the reply waits for the drive to be whole, so a sharded site's export is
|
|
3186
|
+
// not the part of it that happens to be in memory
|
|
3187
|
+
return [4 /*yield*/, snapshot.pending];
|
|
3188
|
+
case 3:
|
|
3189
|
+
// the reply waits for the drive to be whole, so a sharded site's export is
|
|
3190
|
+
// not the part of it that happens to be in memory
|
|
3191
|
+
_c.sent();
|
|
2838
3192
|
expect(snapshot.replies[0].type).toBe('sasjs-snapshot');
|
|
2839
3193
|
expect(Object.keys(snapshot.replies[0].files).length).toBe(1);
|
|
2840
3194
|
reset = message({ type: 'sasjs-reset' });
|
|
2841
3195
|
return [4 /*yield*/, reset.pending];
|
|
2842
|
-
case
|
|
3196
|
+
case 4:
|
|
2843
3197
|
_c.sent();
|
|
2844
3198
|
expect(reset.replies[0]).toEqual(expect.objectContaining({ type: 'sasjs-reset-ack' }));
|
|
2845
3199
|
stats = message({ type: 'sasjs-stats' });
|
|
2846
3200
|
return [4 /*yield*/, stats.pending];
|
|
2847
|
-
case
|
|
3201
|
+
case 5:
|
|
2848
3202
|
_c.sent();
|
|
2849
3203
|
expect(stats.replies[0]).toEqual(expect.objectContaining({ type: 'sasjs-stats' }));
|
|
2850
3204
|
return [2 /*return*/];
|
|
@@ -3381,7 +3735,7 @@ describe('service worker host', function () {
|
|
|
3381
3735
|
}); });
|
|
3382
3736
|
});
|
|
3383
3737
|
describe('conformance corpus', function () {
|
|
3384
|
-
var
|
|
3738
|
+
var e_7, _a, e_8, _b;
|
|
3385
3739
|
/**
|
|
3386
3740
|
* The corpus is what "the same API" means: the cases @sasjs/api runs against
|
|
3387
3741
|
* its own services, and against a live sasjs/server, run here against this
|
|
@@ -3390,7 +3744,7 @@ describe('service worker host', function () {
|
|
|
3390
3744
|
* used to have - and it is a test rather than a review.
|
|
3391
3745
|
*/
|
|
3392
3746
|
var httpFor = function (testCase) {
|
|
3393
|
-
var
|
|
3747
|
+
var e_9, _a;
|
|
3394
3748
|
var _b;
|
|
3395
3749
|
var _c = __read(testCase.route.split(' '), 2), method = _c[0], routePath = _c[1];
|
|
3396
3750
|
var query = new URLSearchParams();
|
|
@@ -3401,12 +3755,12 @@ describe('service worker host', function () {
|
|
|
3401
3755
|
query.set(key, String(value));
|
|
3402
3756
|
}
|
|
3403
3757
|
}
|
|
3404
|
-
catch (
|
|
3758
|
+
catch (e_9_1) { e_9 = { error: e_9_1 }; }
|
|
3405
3759
|
finally {
|
|
3406
3760
|
try {
|
|
3407
3761
|
if (_e && !_e.done && (_a = _d.return)) _a.call(_d);
|
|
3408
3762
|
}
|
|
3409
|
-
finally { if (
|
|
3763
|
+
finally { if (e_9) throw e_9.error; }
|
|
3410
3764
|
}
|
|
3411
3765
|
var suffix = query.toString() ? "?".concat(query) : '';
|
|
3412
3766
|
var init = { method: method };
|
|
@@ -3437,8 +3791,8 @@ describe('service worker host', function () {
|
|
|
3437
3791
|
* does.
|
|
3438
3792
|
*/
|
|
3439
3793
|
var seedDrive = function (runtime, testCase) { return __awaiter(void 0, void 0, void 0, function () {
|
|
3440
|
-
var text, _a, _b, _c, file, contents, _d, _e, _f, file, contents,
|
|
3441
|
-
var
|
|
3794
|
+
var text, _a, _b, _c, file, contents, _d, _e, _f, file, contents, e_10_1;
|
|
3795
|
+
var e_11, _g, e_10, _h;
|
|
3442
3796
|
return __generator(this, function (_j) {
|
|
3443
3797
|
switch (_j.label) {
|
|
3444
3798
|
case 0:
|
|
@@ -3450,12 +3804,12 @@ describe('service worker host', function () {
|
|
|
3450
3804
|
text["/sasjs/drive/files".concat(file)] = contents;
|
|
3451
3805
|
}
|
|
3452
3806
|
}
|
|
3453
|
-
catch (
|
|
3807
|
+
catch (e_11_1) { e_11 = { error: e_11_1 }; }
|
|
3454
3808
|
finally {
|
|
3455
3809
|
try {
|
|
3456
3810
|
if (_b && !_b.done && (_g = _a.return)) _g.call(_a);
|
|
3457
3811
|
}
|
|
3458
|
-
finally { if (
|
|
3812
|
+
finally { if (e_11) throw e_11.error; }
|
|
3459
3813
|
}
|
|
3460
3814
|
return [4 /*yield*/, runtime.load(text)];
|
|
3461
3815
|
case 1:
|
|
@@ -3478,14 +3832,14 @@ describe('service worker host', function () {
|
|
|
3478
3832
|
return [3 /*break*/, 3];
|
|
3479
3833
|
case 6: return [3 /*break*/, 9];
|
|
3480
3834
|
case 7:
|
|
3481
|
-
|
|
3482
|
-
|
|
3835
|
+
e_10_1 = _j.sent();
|
|
3836
|
+
e_10 = { error: e_10_1 };
|
|
3483
3837
|
return [3 /*break*/, 9];
|
|
3484
3838
|
case 8:
|
|
3485
3839
|
try {
|
|
3486
3840
|
if (_e && !_e.done && (_h = _d.return)) _h.call(_d);
|
|
3487
3841
|
}
|
|
3488
|
-
finally { if (
|
|
3842
|
+
finally { if (e_10) throw e_10.error; }
|
|
3489
3843
|
return [7 /*endfinally*/];
|
|
3490
3844
|
case 9: return [2 /*return*/];
|
|
3491
3845
|
}
|
|
@@ -3596,12 +3950,12 @@ describe('service worker host', function () {
|
|
|
3596
3950
|
_loop_1(testCase);
|
|
3597
3951
|
}
|
|
3598
3952
|
}
|
|
3599
|
-
catch (
|
|
3953
|
+
catch (e_7_1) { e_7 = { error: e_7_1 }; }
|
|
3600
3954
|
finally {
|
|
3601
3955
|
try {
|
|
3602
3956
|
if (DRIVE_CORPUS_1_1 && !DRIVE_CORPUS_1_1.done && (_a = DRIVE_CORPUS_1.return)) _a.call(DRIVE_CORPUS_1);
|
|
3603
3957
|
}
|
|
3604
|
-
finally { if (
|
|
3958
|
+
finally { if (e_7) throw e_7.error; }
|
|
3605
3959
|
}
|
|
3606
3960
|
/** The app a removal case names, as the corpus states it. */
|
|
3607
3961
|
var CORPUS_APP = {
|
|
@@ -3670,7 +4024,7 @@ describe('service worker host', function () {
|
|
|
3670
4024
|
return __generator(this, function (_a) {
|
|
3671
4025
|
files = {};
|
|
3672
4026
|
walk = function (members, prefix) {
|
|
3673
|
-
var
|
|
4027
|
+
var e_12, _a;
|
|
3674
4028
|
var _b;
|
|
3675
4029
|
try {
|
|
3676
4030
|
for (var _c = __values(members || []), _d = _c.next(); !_d.done; _d = _c.next()) {
|
|
@@ -3685,12 +4039,12 @@ describe('service worker host', function () {
|
|
|
3685
4039
|
: String((_b = member.code) !== null && _b !== void 0 ? _b : '');
|
|
3686
4040
|
}
|
|
3687
4041
|
}
|
|
3688
|
-
catch (
|
|
4042
|
+
catch (e_12_1) { e_12 = { error: e_12_1 }; }
|
|
3689
4043
|
finally {
|
|
3690
4044
|
try {
|
|
3691
4045
|
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
3692
4046
|
}
|
|
3693
|
-
finally { if (
|
|
4047
|
+
finally { if (e_12) throw e_12.error; }
|
|
3694
4048
|
}
|
|
3695
4049
|
};
|
|
3696
4050
|
walk(tree === null || tree === void 0 ? void 0 : tree.members, '');
|
|
@@ -3707,7 +4061,7 @@ describe('service worker host', function () {
|
|
|
3707
4061
|
*/
|
|
3708
4062
|
var deployRequest = function (testCase) { return __awaiter(void 0, void 0, void 0, function () {
|
|
3709
4063
|
var _a, requestPath, init, body, archive, form, _b, _c, _d, field, value;
|
|
3710
|
-
var
|
|
4064
|
+
var e_13, _e;
|
|
3711
4065
|
return __generator(this, function (_f) {
|
|
3712
4066
|
switch (_f.label) {
|
|
3713
4067
|
case 0:
|
|
@@ -3726,12 +4080,12 @@ describe('service worker host', function () {
|
|
|
3726
4080
|
form.set(field, String(value));
|
|
3727
4081
|
}
|
|
3728
4082
|
}
|
|
3729
|
-
catch (
|
|
4083
|
+
catch (e_13_1) { e_13 = { error: e_13_1 }; }
|
|
3730
4084
|
finally {
|
|
3731
4085
|
try {
|
|
3732
4086
|
if (_c && !_c.done && (_e = _b.return)) _e.call(_b);
|
|
3733
4087
|
}
|
|
3734
|
-
finally { if (
|
|
4088
|
+
finally { if (e_13) throw e_13.error; }
|
|
3735
4089
|
}
|
|
3736
4090
|
form.set('file', new Blob([new Uint8Array(archive)]), 'deploy.zip');
|
|
3737
4091
|
return [2 /*return*/, { requestPath: requestPath, init: { method: 'POST', body: form } }];
|
|
@@ -3740,8 +4094,8 @@ describe('service worker host', function () {
|
|
|
3740
4094
|
}); };
|
|
3741
4095
|
var _loop_2 = function (testCase) {
|
|
3742
4096
|
it(testCase.id, function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
3743
|
-
var worker, _a, requestPath, init, response, listing, ids, _b, _c, path_6, file,
|
|
3744
|
-
var
|
|
4097
|
+
var worker, _a, requestPath, init, response, listing, ids, _b, _c, path_6, file, e_14_1, _d, _e, path_7, file, e_15_1;
|
|
4098
|
+
var e_14, _f, e_15, _g;
|
|
3745
4099
|
var _h, _j, _k;
|
|
3746
4100
|
return __generator(this, function (_l) {
|
|
3747
4101
|
switch (_l.label) {
|
|
@@ -3793,14 +4147,14 @@ describe('service worker host', function () {
|
|
|
3793
4147
|
return [3 /*break*/, 9];
|
|
3794
4148
|
case 12: return [3 /*break*/, 15];
|
|
3795
4149
|
case 13:
|
|
3796
|
-
|
|
3797
|
-
|
|
4150
|
+
e_14_1 = _l.sent();
|
|
4151
|
+
e_14 = { error: e_14_1 };
|
|
3798
4152
|
return [3 /*break*/, 15];
|
|
3799
4153
|
case 14:
|
|
3800
4154
|
try {
|
|
3801
4155
|
if (_c && !_c.done && (_f = _b.return)) _f.call(_b);
|
|
3802
4156
|
}
|
|
3803
|
-
finally { if (
|
|
4157
|
+
finally { if (e_14) throw e_14.error; }
|
|
3804
4158
|
return [7 /*endfinally*/];
|
|
3805
4159
|
case 15:
|
|
3806
4160
|
_l.trys.push([15, 20, 21, 22]);
|
|
@@ -3819,14 +4173,14 @@ describe('service worker host', function () {
|
|
|
3819
4173
|
return [3 /*break*/, 16];
|
|
3820
4174
|
case 19: return [3 /*break*/, 22];
|
|
3821
4175
|
case 20:
|
|
3822
|
-
|
|
3823
|
-
|
|
4176
|
+
e_15_1 = _l.sent();
|
|
4177
|
+
e_15 = { error: e_15_1 };
|
|
3824
4178
|
return [3 /*break*/, 22];
|
|
3825
4179
|
case 21:
|
|
3826
4180
|
try {
|
|
3827
4181
|
if (_e && !_e.done && (_g = _d.return)) _g.call(_d);
|
|
3828
4182
|
}
|
|
3829
|
-
finally { if (
|
|
4183
|
+
finally { if (e_15) throw e_15.error; }
|
|
3830
4184
|
return [7 /*endfinally*/];
|
|
3831
4185
|
case 22: return [2 /*return*/];
|
|
3832
4186
|
}
|
|
@@ -3859,12 +4213,12 @@ describe('service worker host', function () {
|
|
|
3859
4213
|
_loop_2(testCase);
|
|
3860
4214
|
}
|
|
3861
4215
|
}
|
|
3862
|
-
catch (
|
|
4216
|
+
catch (e_8_1) { e_8 = { error: e_8_1 }; }
|
|
3863
4217
|
finally {
|
|
3864
4218
|
try {
|
|
3865
4219
|
if (_d && !_d.done && (_b = _c.return)) _b.call(_c);
|
|
3866
4220
|
}
|
|
3867
|
-
finally { if (
|
|
4221
|
+
finally { if (e_8) throw e_8.error; }
|
|
3868
4222
|
}
|
|
3869
4223
|
});
|
|
3870
4224
|
/**
|
|
@@ -3876,7 +4230,7 @@ describe('service worker host', function () {
|
|
|
3876
4230
|
* are the package's.
|
|
3877
4231
|
*/
|
|
3878
4232
|
describe('identity and record conformance', function () {
|
|
3879
|
-
var
|
|
4233
|
+
var e_16, _a;
|
|
3880
4234
|
/**
|
|
3881
4235
|
* Boots the worker from a fixture, the way the page does: the case's own
|
|
3882
4236
|
* identity, and `subject: null` for no implicit caller, so a case that
|
|
@@ -3909,7 +4263,7 @@ describe('service worker host', function () {
|
|
|
3909
4263
|
};
|
|
3910
4264
|
/** The request a case describes, as HTTP: path parameters filled, token sent. */
|
|
3911
4265
|
var httpForCase = function (testCase) {
|
|
3912
|
-
var
|
|
4266
|
+
var e_17, _a;
|
|
3913
4267
|
var _b = __read(testCase.route.split(' '), 2), method = _b[0], routePath = _b[1];
|
|
3914
4268
|
var filled = routePath.replace(/\{(\w+)\}/g, function (_match, name) {
|
|
3915
4269
|
return encodeURIComponent(String((testCase.request.params || {})[name]));
|
|
@@ -3922,12 +4276,12 @@ describe('service worker host', function () {
|
|
|
3922
4276
|
query.set(key, String(value));
|
|
3923
4277
|
}
|
|
3924
4278
|
}
|
|
3925
|
-
catch (
|
|
4279
|
+
catch (e_17_1) { e_17 = { error: e_17_1 }; }
|
|
3926
4280
|
finally {
|
|
3927
4281
|
try {
|
|
3928
4282
|
if (_d && !_d.done && (_a = _c.return)) _a.call(_c);
|
|
3929
4283
|
}
|
|
3930
|
-
finally { if (
|
|
4284
|
+
finally { if (e_17) throw e_17.error; }
|
|
3931
4285
|
}
|
|
3932
4286
|
var suffix = query.toString() ? "?".concat(query) : '';
|
|
3933
4287
|
var headers = {};
|
|
@@ -4049,12 +4403,12 @@ describe('service worker host', function () {
|
|
|
4049
4403
|
_loop_3(testCase);
|
|
4050
4404
|
}
|
|
4051
4405
|
}
|
|
4052
|
-
catch (
|
|
4406
|
+
catch (e_16_1) { e_16 = { error: e_16_1 }; }
|
|
4053
4407
|
finally {
|
|
4054
4408
|
try {
|
|
4055
4409
|
if (_c && !_c.done && (_a = _b.return)) _a.call(_b);
|
|
4056
4410
|
}
|
|
4057
|
-
finally { if (
|
|
4411
|
+
finally { if (e_16) throw e_16.error; }
|
|
4058
4412
|
}
|
|
4059
4413
|
it('answers as the fixture administrator when no subject was chosen', function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
4060
4414
|
var worker, response, rules;
|